Part II — Predictive analytics · Chapter 5

Neural models: MLP, RNN, LSTM and GRU

~36 min read6 interactive widgets

In this chapter

  1. Why neural networks for forecasting
  2. Time-lagged networks and the sliding window
  3. From series to supervised dataset
  4. What each architecture is, statistically
  5. An MLP in torch, end to end
  6. The modelling process, in five phases
  7. Heuristic choices and sizing rules
  8. Recurrent networks and BPTT
  9. LSTM and GRU
  10. The fil rouge scoreboard
  11. Check your understanding

1. Why neural networks for forecasting

The claim the deck opens with is strong and precisely worded: neural networks are very effective in identifying non linear models. Even with input data deriving from complex, nonlinear processes, NN are able to combine linear and nonlinear models to get whichever accuracy level is requested — in prediction. That parenthesis is doing a lot of work, and it is the honest one: the guarantee is about fitting, not about forecasting.

Three capabilities are listed:

Two structural properties follow. NN are nonparametric: they do not make hypotheses on noise distribution (Gaussian or otherwise) — contrast this with the Kalman filter of chapter 3, whose optimality is conditional on Gaussian noise, and with the AIC approximation of chapter 4, which assumes Gaussian residuals. And NN identify a model from input data, essentially defining a model of the generating process.

A vocabulary you must be able to translate

Given the loosely neurobiological inspiration of the model, terminology is peculiar. The deck supplies the dictionary, and exam questions have been known to consist of nothing but this table.

NNStatistic
input nodesindependent variables
output nodesdependent variables
weightsparameters
trainingidentification
Key idea

Read the right-hand column and chapter 4 reappears. Training is identification — the first of the three phases of an objective model. A neural network is not a different kind of object from an ARIMA; it is a different function class fitted by a different optimizer, and chapter 9 will show that the optimizer is the same gradient descent in both worlds.

2. Time-lagged networks and the sliding window

The architecture is described in one sentence: the net is structured according to a feedforward scheme, where inputs are associated to past data and the output is the forecast. Input nodes take xt-1, xt-2, …, xt-K plus a bias; the output node produces xt.

A time-lagged feedforward network: K input nodes holding past values plus a bias, fully connected to a hidden layer, which connects to a single output node producing the forecast. INPUT (past values) HIDDEN OUTPUT 1 bias x t-1 x t-2 x t-K x t weights = parameters · training = identification · input nodes = independent variables if hidden and output neurons see only PRE-DEFINED SUBSETS of the previous layer, the net is convolutional
Plate 5.1 — The time-lagged feedforward network. Full connectivity is what makes it an MLP; restricting each neuron to a predefined subset of the previous layer, with specific operators, is what makes it convolutional.

The slides add a note on convolutional nets that is easy to misread, so here it is verbatim: if the input of hidden and output neurons sees only pre-defined subsets of the output of the previous layer and applies them specific operators, the net is named convolutional. These are networks most effective for classification, less so for regression. For forecasting, then, CNNs are mentioned and set aside.

How learning proceeds

The sliding window is the training loop, in five steps:

  1. A window on past data is shown in input.
  2. The corresponding output is computed.
  3. The output is compared with its corresponding actual value.
  4. Backpropagation: weights are changed in order to reduce prediction error.
  5. The window is shifted forward, presenting the following input.
A sliding window moving along a series, each position producing one training record whose inputs are the windowed values and whose target is the next value. SERIES 128 181 87 219 407 226 214 383 505 387 278 523 i=0 X = 128 181 87 219 y=407 i=1 X = 181 87 219 407 y=226 i=2 X = 87 219 407 226 y=214 ⋮ the window shifts forward, one step at a time look_back = 4 → a matrix of (n - look_back) rows × 4 columns, plus a target column this is the same lagged-feature matrix LASSO needed in chapter 4 forecasting has become supervised regression — which is why trees work too (chapter 6)
Plate 5.2 — The sliding window converts a time series into a supervised learning dataset. Every model in chapters 5 and 6 consumes exactly this matrix; only the regressor changes.

3. From series to supervised dataset

The task is stated as: transform a data series into a learning dataset where the next datapoint of each record is the unknown. The deck gives three implementations, differing only in the container they expect — array, series, or dataframe.

# converts a 1D array of values into two np arrays
def create_dataset(arrdata, look_back=1):
    dataX, dataY = [], []
    for i in range(len(arrdata) - look_back):
        a = arrdata[i:(i + look_back)]
        dataX.append(a)
        dataY.append(arrdata[i + look_back])
    return np.array(dataX), np.array(dataY)
# converts a series into a windowed dataframe
def create_dataset2(df, look_back=1, colname='value'):
    cols = ['x{}'.format(x) for x in range(look_back)] + ['y']
    df_win = []
    for i in range(look_back, df.shape[0]):
        df_win.append(df.loc[i-look_back:i, colname].tolist())
    return pd.DataFrame(df_win, columns=cols)

# works directly on the dataframe, building it by columns
def create_dataset3(df, look_back=1, colname='value'):
    dataset = pd.DataFrame()
    for i in range(lookback, 0, -1):
        dataset['t-' + str(i)] = df.Passengers.shift(i)
    dataset['t'] = df.values
    dataset = dataset[lookback:]   # removes the first lookback rows

Build the window yourself

The fil rouge, turned into a supervised dataset. Change look_back and watch two things move in opposite directions: the width of each record, and how many records you have left.

4
Careful

Note the shape comment in the torch code: dataset = df.values.astype('float32') # COLUMN VECTOR !!!. The array version of create_dataset indexes dataset[i:(i+look_back), 0], so it expects a 2-D column, not a flat 1-D array. Shape errors of this kind are the single most common way a working forecasting script stops working when moved between the array and dataframe versions.

4. What each architecture is, statistically

The deck states, without ceremony, that NN are able to approximate any function, and that forecasting can be thought of as the identification of a specific (nonlinear) function. It then gives a three-row table that maps each architecture onto its statistical twin — the single most useful table in the chapter, because it lets you carry every intuition from chapter 4 across the divide.

ArchitectureStatistical equivalent
Only one neuronAR(p)
Feedforward NN (MLP)nonlinear combination of AR(p)
Recurrent NN (Elman, Jordan)ARMA(p,q), nonlinear

Read the first row and the reason becomes obvious: a single neuron with a linear activation computes a weighted sum of its inputs plus a bias, and its inputs are the last p observations. That is an AR(p). Add a hidden layer with nonlinear activations and you get a nonlinear combination of such sums. Add a feedback loop and the network carries forward an internal state which plays the role of the error memory in an MA term.

The slides illustrate the point with two small examples: a linear regression including exogenous variables — which they label ARX — and a nonlinear (logistic) regression of the same process, showing that the same network topology moves between the two by changing the activation function alone.

5. An MLP in torch, end to end

The worked example is the Box-Jenkins airline series, with a network described as (12-8-1): 12 input nodes, 8 hidden units, 1 output node. The 12 input values are t, t-1, …, t-11 — the last twelve observations — and the prediction value is t+1. The benchmark has 132 input values over 13 time periods of monthly data.

Preliminaries and the split

import numpy as np, pandas as pd, matplotlib.pyplot as plt
import torch, torch.nn as nn, torch.optim as optim
from sklearn.metrics import root_mean_squared_error

df = pd.read_csv('BoxJenkins.csv', usecols=[1])
dataset = df.values.astype('float32')          # COLUMN VECTOR !!!
train_size = int(len(dataset) - 12)            # hold out the last year
train, test = dataset[0:train_size, :], dataset[train_size:len(dataset), :]

look_back = 12
testdata = np.concatenate((train[-look_back:], test))
trainX, trainy = create_dataset(train, look_back)

The line building testdata is worth a second: to predict the first test point the network needs the twelve values that precede it, and those live at the end of the training set. Stitching them on is not leakage — it is giving the model the context it would have in production.

The model and the training loop

X = torch.FloatTensor(trainX)
y = torch.FloatTensor(trainy)

model = nn.Sequential(nn.Linear(12, 10), nn.ReLU(),
                      nn.Linear(10, 8),  nn.ReLU(),
                      nn.Linear(8, 1)   # no activation, allowing negative outputs
                     )

loss_fn   = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)   # mind the learning rate!
n_epochs, batch_size = 200, 1

for epoch in range(n_epochs):
   for i in range(0, len(X), batch_size):
      Xbatch = X[i:i + batch_size]
      y_pred = model(Xbatch)
      ybatch = y[i:i + batch_size]
      loss   = loss_fn(y_pred, ybatch)
      optimizer.zero_grad()      # clear old gradients
      loss.backward()            # here the learning
      optimizer.step()

Two annotations in the original are the ones that bite in practice. No activation function on the output layer, allowing for negative outputs — essential when the target is a differenced or standardised series, which is centred on zero. And mind the learning rate: with lr too large the loss oscillates and never settles, with lr too small two hundred epochs are not enough. Chapter 9 gives that parameter its proper name, λ, and its proper theory.

Evaluating: RMSE or AIC

The deck offers two alternatives, and the second is a nice bridge back to chapter 4.

# alternative 1: model evaluation as RMSE
model.eval()            # tells the model we are evaluating, not training
with torch.no_grad():   # stop tracking gradient computations
   y_pred = model(X)
   rmse = root_mean_squared_error(trainy, y_pred.numpy())

# alternative 2: model evaluation as AIC
k = sum(p.numel() for p in model.parameters() if p.requires_grad)   # count params
model.eval()
with torch.no_grad():
   y_pred = model(X)
   rss    = torch.sum((y - y_pred) ** 2).item()
   n      = trainX.shape[0]
   aic    = n * np.log(rss / n) + 2 * k

The AIC of a neural network counts every weight and bias as a parameter. For the (12-10-8-1) network above that is 12×10 + 10 + 10×8 + 8 + 8×1 + 1 = 227 parameters, against 132 monthly observations. Chapter 4 warned that with a small sample AIC prefers overfits; here the penalty term alone is 454.

Recursive forecasting

To produce more than one step ahead, the network is fed its own output. This is recursive forecasting, and it is the same pattern XGBoost and random forest will use in chapter 6.

# start from the last window of train (or the first of testX)
input_seq = trainX[-1].tolist()
testForecast = []
model.eval()
with torch.no_grad():
   for _ in range(len(test)):
      input_tensor = torch.tensor(input_seq, dtype=torch.float32).unsqueeze(0)
      pred = model(input_tensor).item()      # scalar prediction
      testForecast.append(pred)
      input_seq = input_seq[1:] + [pred]     # roll the window forward by 1
Careful — error accumulation

input_seq = input_seq[1:] + [pred] pushes a prediction into the input window. After k steps the window contains k predictions and 12-k observations; after twelve steps it is predictions all the way down. Errors compound. This is the mechanical reason, on the neural side, for the chapter 2 attribute that reliability decreases with the distance in the future.

6. The modelling process, in five phases

The deck lays out the phases for the definition of a neural forecast model. Note that phase 1 is a pointer straight back to chapter 3 — the same as statistical models.

PhaseDecisions
1. Preprocessing
(the same as statistical models)
Transforms (diff, log, …); scaling, if different variables they must have comparable values; normalization, to [0,1] or [-1,1].
2. Choice of architectureNumber of neurons — input, hidden, output; number of hidden layers (one: MLP, many: deep network); processing at the nodes (activation function: linear, logistic, …); connections between layers.
3. TrainingWeights initialization (and reinitialization?); training algorithm (backpropagation — which one?); parameter setting.
4. Use of the NNProducing forecasts, recursively if the horizon exceeds one step.
5. ValidationChoice of the dataset; validation criteria.

Preprocessing is mandatory here, not optional

The deck lists the procedures needed to improve forecast effectiveness: verification, correction and editing (errors in the data); re-encoding of variables (from categorical to numeric, one-hot); scaling of variables (e.g. linear interval scaling); normalization; selection of independent variables (PCA, …); removal of the outliers; insertion of missing values (means, regression, default, …). All of chapter 3, invoked as a prerequisite.

And then the sentence that turns a recommendation into a requirement: data preprocessing of the input vector is a mandatory requirement for the application of MLPs. The reason is stated precisely: as the sigmoid activation functions in the hidden nodes are only defined in the interval of ]-1, 1[ for the hyperbolic tangent or ]0, 1[ for the logistic function, input data must be scaled to facilitate learning. Some authors recommend linear scaling of data into smaller intervals, e.g. [0.2, 0.8], to avoid saturation effects at the asymptotic bounds of the activation functions.

Key idea

Saturation is the failure mode to understand. Push a logistic unit far into its tail and its output stops changing — which means its derivative is near zero, which means backpropagation sends no signal through it. An unscaled input does not merely train slowly: it can stop the gradient dead. This is the same mechanism as the vanishing gradient problem in section 8.

7. Heuristic choices and sizing rules

How many hidden neurons? The literature disagrees, and the deck simply lists who says what, for a network with n input nodes.

Hidden neuronsAttributed to
2n + 1Lippmann 87; Hecht, Nielsen 90; Zhang, Pauwo, Hu 98
2nWong 91
nTang, Fishwick 93
n/2Kang 91
0.75nBailey 90
1.5n – 3nKasstra, Boyd 96

And the activation function:

ChoiceAttributed to
Logistic, both in hidden and output nodesTang, Fischwick 93; Lattermacher, Fuller 95; Sharda, Patil 92
Hyperbolic tangent, both in hidden and output nodesZhang, Hutchinson 93; DeGroot, Wurtz 91
Linear in output nodesLapedes, Faber 87; Weigend 91; Wong 90

Three concluding suggestions

Sizing an MLP by the book

All six hidden-layer heuristics at once, plus the weight count and the 5× overfitting rule applied to your series length.

12
8
144

8. Recurrent networks and BPTT

Recurrent neural networks are introduced as a very effective neural model for forecasting, with five defining properties:

The consequence for modelling is stated compactly: RNNs compile preceding data in their context layer, they do not need an input neuron for each past value. That is the structural difference from the time-lagged MLP of section 2, which needs K input nodes for K lags. And then a sentence worth underlining twice: their effect is not function approximation, but process modeling. The prediction model is structured as

outputₜ₊₁ ≈ RNN(NetworkState, inputₜ, outputₜ)

where NetworkState is represented by the activation of the neurons in the context layer.

A recurrent network drawn with its feedback loop, and the same network unfolded across four time steps so that backpropagation through time can be applied to the unfolded chain. FOLDED h feedback x(t) y(t) UNFOLDED (what BPTT differentiates) h0 h1 h2 h3 x0x1x2x3 y0y1y2y3 error propagated backwards across k time steps the gradient is a PRODUCT of k terms — if each is < 1, the product tends to 0 VANISHING GRADIENT: no weight update reaches the early steps, so long dependencies are never learned the deeper the network, the more pronounced — common to deep MLPs too
Plate 5.3 — Folded and unfolded views of an RNN. BPTT is ordinary backpropagation applied to the unfolded chain; its characteristic failure, the vanishing gradient, is what LSTM was invented to fix.

Activation functions

We can use any activation function we like in the recurrent neural network. Common choices: the sigmoid function, the tanh function, and the ReLU function, max(0, x).

The BPTT(k) algorithm

BPTT(k)      // pₜ is the target value at time step t
1. while not (termination condition)
2.     set all h to zero                     // hidden neurons states
3.     repeat for t = 0 to n-k
4.         forward propagate the network over the unfolded network
           for k time steps to compute all h and y.
5.         compute the error as: e = pₜ - yₜ
6.         backpropagate the error across the unfolded network and
           update the weights.

Line 2 is the key one: the hidden state is reset at the start of each sweep, and then the network is unrolled for k steps so that ordinary backpropagation applies to what is now a deep feedforward network with shared weights.

Advantages and shortcomings

AdvantagesDisadvantages
Ability to handle sequence data.
Ability to handle inputs of varying lengths.
Ability to store or memorize historical information.
The computation can be very slow.
Vanishing gradient problem: the gradients used for the weight update may get very close to zero, which prevents the network from learning new weights. The deeper the network, the more pronounced is this problem (common to deep MLPs).

9. LSTM and GRU

Long Short-Term Memory (LSTM) networks are RNN trained by Backpropagation Through Time. The structural novelty: they do not have proper neurons, but memory blocks connecting layers. A block is more complex than a normal neuron — it contains "gates" to maintain internal state and output, and each gate works on the input sequence and uses an activation function that determines its contribution to internal state and output. The weights of all gates must be defined during training.

An LSTM memory block showing the forget gate updating the cell state, the input gate selecting which values pass on, and the output gate computing the block output from input and state. MEMORY BLOCK cell state c(t-1) → c(t) FORGET gate what is dropped × INPUT gate values to pass on + OUTPUT gate compute output input x(t) output h(t) c(t) = f(t)·c(t-1) + i(t)·tanh(...) — the cell state is EDITED, not overwritten that additive path is what lets gradients survive across many steps GRU: update + reset gates only, no output gate, no separate cell state
Plate 5.4 — The three LSTM gates. The horizontal cell-state line is the important feature: information travels along it with only multiplicative forgetting and additive updating, which is why long-range dependencies are not squeezed to zero.

Decide which information is dropped. In the equations of the deck, ft = σ(W(xf)xt + W(hf)ht-1 + W(cf)ct-1 + b(f)). It multiplies the previous cell state, so a value near 0 erases a memory and a value near 1 preserves it intact.

Decide which input values contribute to the state. it = σ(W(xi)xt + W(hi)ht-1 + W(ci)ct-1 + b(i)), and the state update is ct = ft•ct-1 + it•tanh(W(xc)xt + W(hc)ht-1 + b(c)).

Decide the output based on input and state. ot = σ(W(xo)xt + W(ho)ht-1 + W(co)ct + b(o)) and then ht = ot • tanh(ct). Here σ is the logistic sigmoid; it, ft, ot are the gate vectors; ct and ht the "normal" and hidden state of the layer; the W matrices are weight matrices, of which W(ci), W(cf) and W(co) are diagonal (thus vectors, actually).

Gated Recurrent Units are another type of RNN, similar to LSTM but with fewer parameters: they do not have an output gate. The two gates are the update gate — decides the previous memory to keep — and the reset gate — defines how to combine new input with previous memory. And a structural difference worth stating explicitly: unlike LSTM, in GRU there is no persistent cell state distinct from the hidden state.

An LSTM in torch

class LSTM(nn.Module):
   def __init__(self, input_size=1, hidden_size=24, num_layers=1):
      super().__init__()
      self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
      self.fc   = nn.Linear(hidden_size, 1)

   def forward(self, x):
      out, _ = self.lstm(x)
      return self.fc(out[:, -1, :])      # take the LAST time step only
df   = pd.read_csv("BoxJenkins.csv", usecols=[1])
data = df.values.astype(float)

scaler = MinMaxScaler()          # Normalize, needed
data_scaled = scaler.fit_transform(data)

lag = 12
X, y = create_dataset(data_scaled, lag)
X_train = torch.tensor(X, dtype=torch.float32)
y_train = torch.tensor(y, dtype=torch.float32)

model     = LSTM()
loss_fn   = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

for epoch in range(100):
   model.train()
   output = model(X_train)
   loss   = loss_fn(output, y_train)
   optimizer.zero_grad(); loss.backward(); optimizer.step()
# Forecast next 12 values, recursively
model.eval()
fore = []
seq = torch.tensor(X[-1], dtype=torch.float32).unsqueeze(0)
for _ in range(12):
   with torch.no_grad():
      pred = model(seq)
      fore.append(pred.item())
      seq = torch.cat([seq[:, 1:], pred.unsqueeze(1)], dim=1)   # roll forward

forecast = scaler.inverse_transform(np.array(fore).reshape(-1, 1))   # inverse scale

Three details in that block carry the whole chapter. MinMaxScaler with the comment needed — section 6's mandatory preprocessing. out[:, -1, :] — the LSTM emits an output at every step, but only the last one is the forecast. And scaler.inverse_transform — the transform is undone before anyone reads the numbers, exactly as in chapters 3 and 4.

10. The fil rouge scoreboard

The deck evaluates a simple MLP model on the same experiment used for SARIMA in chapter 4: train 2004-2007, test 2008.

ACTUALMLPy - f|y - f|(y - f)²
752529.55222.45222.4549482.93
468374.3793.6393.638767.44
419518.23-99.2399.239845.96
725788.36-63.3663.364014.96
resultBIAS 38.37 · MAD 119.67 · RMSE 134.27 · MAPE 23.55

The slides annotate this table with two words: easy to improve. And they are right — but the honest reading is the comparison, and it is not flattering for the network.

SARIMA versus MLP on 2008

Both tables from the course, side by side, with the errors drawn to scale. The neural model has more parameters, more freedom and worse numbers — on twenty quarterly observations.

For the exam

Do not conclude "statistics beats neural networks". Conclude what the data supports: on a twenty-point series, a model with hundreds of weights cannot be identified, and the sizing rule of section 7 says so in advance — the training set should be at least five times the number of network weights. Twenty points support roughly four weights. The neural models in this chapter earn their keep on the 144-point airline series and on genuinely nonlinear processes, not here.

Check your understanding

Translate the neural vocabulary into statistical terms.

Input nodes = independent variables. Output nodes = dependent variables. Weights = parameters. Training = identification. The terminology is peculiar because of the loosely neurobiological inspiration of the model, but the objects are the familiar ones.

What does it mean that neural networks are nonparametric, and why does it matter here?

It means they do not make hypotheses on the noise distribution — Gaussian or otherwise. It matters because most of the statistical machinery of this course does make such an assumption: the Kalman filter is MSE-optimal only under Gaussian noise, and the AIC log-likelihood approximation assumes Gaussian residuals. A neural network identifies a model from the input data, essentially defining a model of the generating process, without that commitment.

Describe the sliding window learning procedure in five steps.

(1) A window on past data is shown in input. (2) The corresponding output is computed. (3) The output is compared with its corresponding actual value. (4) Backpropagation: weights are changed in order to reduce prediction error. (5) The window is shifted forward, presenting the following input.

Give the statistical equivalent of a single neuron, of an MLP and of an RNN.

Only one neuron → AR(p). Feedforward NN (MLP) → nonlinear combination of AR(p). Recurrent NN (Elman, Jordan) → nonlinear ARMA(p,q). Forecasting is thereby the identification of a specific, generally nonlinear, function.

When is a network called convolutional, and how useful is that for forecasting?

When the input of hidden and output neurons sees only pre-defined subsets of the output of the previous layer, and applies to them specific operators. The deck's verdict: these are the networks most effective for classification, less so for regression — so for forecasting they are mentioned and set aside.

Why is preprocessing described as mandatory for MLPs, and what interval is recommended?

Because the sigmoid activation functions in the hidden nodes are only defined in ]-1, 1[ for the hyperbolic tangent, or ]0, 1[ for the logistic function, so input data must be scaled to facilitate learning. Some authors recommend linear scaling into smaller intervals such as [0.2, 0.8], to avoid saturation effects at the asymptotic bounds of the activation functions — a saturated unit has a near-zero derivative and therefore transmits no gradient.

List the five phases of defining a neural forecasting model.

(1) Preprocessing — the same as statistical models: transforms (diff, log), scaling, normalization to [0,1] or [-1,1]. (2) Choice of the architecture — number of input/hidden/output neurons, number of hidden layers (one: MLP, many: deep), activation function, connections between layers. (3) Training — weight initialization, training algorithm, parameter setting. (4) Use of the NN. (5) Validation — choice of dataset and validation criteria.

Quote the three sizing suggestions for an MLP.

The test set should be about 10% to 30% of the size of the training set. To avoid overfitting, the training set size should be at least 5 times the number of network weights. In theory a single hidden layer is enough to approximate any continuous function, but in practice a further hidden layer often helps; more than 4 layers (input, output, two hidden) can work wonders but usually only in very controlled contexts. Hidden-neuron heuristics range from n/2 up to 2n+1 and 1.5n-3n, depending on the author.

What distinguishes an RNN from a time-lagged MLP?

An RNN has at least one backward connection and therefore an internal state: it keeps activations even with no input. Consequently RNNs compile preceding data in their context layer and do not need an input neuron for each past value, whereas a time-lagged MLP needs K inputs for K lags. Their effect is described as not function approximation but process modeling: outputt+1 ≈ RNN(NetworkState, inputt, outputt).

Sketch the BPTT(k) algorithm and name the RNN failure mode it suffers from.

While not terminated: set all hidden states h to zero; then for t = 0 to n-k, forward propagate over the unfolded network for k time steps to compute all h and y, compute the error e = pt - yt, and backpropagate the error across the unfolded network, updating the weights. The failure mode is the vanishing gradient problem: gradients used for the weight update may get very close to zero, preventing the network from learning new weights, and the deeper the network the more pronounced the problem — a defect shared with deep MLPs. RNNs are also very slow to compute.

Name the three LSTM gates and what each decides.

Forget gate: decides which information is dropped. Input gate: decides which input values contribute to the state. Output gate: decides the output based on input and state. LSTMs have no proper neurons but memory blocks; each gate works on the input sequence with its own activation function, and all gate weights must be learned during training. LSTMs are RNNs trained by BPTT.

How does a GRU differ from an LSTM?

GRUs are similar to LSTM but with fewer parameters: they do not have an output gate. Their two gates are the update gate, deciding how much previous memory to keep, and the reset gate, defining how to combine new input with previous memory. Structurally, there is no persistent cell state distinct from the hidden state as there is in LSTM.

How is a multi-step forecast produced from a one-step network, and what is the cost?

Recursively: predict one step, append the prediction to the input window, drop the oldest value, predict again — input_seq = input_seq[1:] + [pred]. The cost is error accumulation: after k steps the window is filled with k of the model's own predictions, so errors compound and accuracy decays with the horizon.

The MLP scored worse than SARIMA on the fil rouge 2008 test. What is the correct explanation?

The MLP gave BIAS 38.37, MAD 119.67, RMSE 134.27, MAPE 23.55, against SARIMA's 3.97 / 50.26 / 68.90 / 8.73. The explanation is not that neural models are inferior in general but that the fil rouge has twenty points. The deck's own sizing rule requires a training set at least five times the number of network weights, so a network of any useful size cannot be identified from this series. The slides themselves comment that the result is easy to improve.