Neural Networks1990intermediate19 min read

Backpropagation Through Time: What It Does and How to Do It

الانتشار العكسي عبر الزمن: كيف تتعلّم الشبكة من ماضيها

Werbos, P. J. — Proceedings of the IEEE

The problem

By 1990 was the most popular way to train neural networks, but most people knew it only as a recipe for layered, memoryless networks. Many real problems unfold over time: speech, moving targets, forecasting, and control. There the right answer at one moment depends on what happened earlier, and an action taken now pays off or goes wrong many steps later. The field needed exact, affordable derivatives through systems whose own outputs feed back into them, and a notation careful enough that people could apply it to complicated systems without making mistakes.

The contribution

Werbos restates backpropagation as a general method: exact derivatives of one target through any ordered system of differentiable steps, based on his for ordered derivatives and "F_" feedback variables. He then gives the equations and Fortran-style pseudocode for . The network runs forward and stores every state, then sweeps backward from the last step to the first, summing each shared weight's over all steps, with lag-1 and lag-2 recurrent connections included. He shows the same machinery at work in and in , where is backpropagated through a model of the plant into an action network. He also sets out the costs honestly: full storage, batch updates, a forward-time exact alternative whose cost grows with the square of the network's size, and adaptive critics for truly real-time learning.

The impact

This paper became the standard reference for training recurrent networks. Every modern is trained with the unroll-and-sweep-back procedure it describes, usually truncated to a window. Its clear statement of the memory and time costs set up the next questions: Bengio and colleagues' analysis of why gradients vanish or explode over long spans, LSTM's gated memory designed to fix that, and the continuing search for learning rules that work online, without storing the past.

Picture an accountant closing the books on a year of trading. The final loss is known, and every transaction that led to it is in the ledger in the order it happened. The accountant starts from the last entry and works back through the year. Each transaction is charged for the damage it did directly, plus its share of whatever it caused in later transactions.

Two things make this work. The whole ledger has to be kept, because nothing can be charged until the final number is in. And the same rule applied every month is charged across all twelve months at once. That is backpropagation through time.

Backpropagation is bookkeeping, not a neural-network trick

Werbos opens with a claim that was easy to miss in 1990. Backpropagation is not really about neurons. It is a way to compute, exactly and cheaply, the derivatives of one target quantity with respect to every input and parameter of a system built from known, differentiable steps. The target might be a classification error, and the parameters the weights of a network. But the first practical use, in his 1974 thesis, was fitting a dynamic model of nationalism and social communication.

He first sets up the familiar case with a new notation. A computes each neuron from every neuron before it: a weighted sum neti\mathrm{net}_i, then a s(z)=1/(1+e−z)s(z) = 1/(1+e^{-z}). Layered networks are the special case where most of those weights are fixed at zero. Training minimises the summed squared error over the training set by : find the derivative of the error for every weight, then step each weight against it by a . His advice is to start the weights small and random, and to raise the rate until the error starts to diverge.

None of this was new. What is unusual, he says, is only how the derivatives are computed: exactly, for all weights, in a single pass through the system.

A variable's direct effect is not its total effect

When Werbos presented the idea to the Harvard faculty in 1972, they doubted that such tangled calculations could be trusted. His answer was a theorem: the chain rule for . It applies to any system whose quantities can be computed one after another in a fixed order, ending with a target.

The key distinction is between two kinds of derivative. An ordinary measures the direct effect: change one variable and hold everything else fixed. An ordered derivative measures the total effect: change the variable, then recompute everything that comes after it. The paper's example is z2=4z1z_2 = 4 z_1 and z3=3z1+5z2z_3 = 3 z_1 + 5 z_2. The direct effect of z1z_1 on z3z_3 is 3. The total effect is 23, because z1z_1 also moves z2z_2, which moves z3z_3 again: 3+4×53 + 4 \times 5. Which of the two matters for training? The total effect, since in a real network nothing downstream stays still.

Open in Lab
Nudge z₁ with z₂ held fixed, then again with z₂ free to react, and compare how far z₃ moves. Then drag the link from z₂ to z₃ below zero: the direct and total effects can end up with opposite signs. Finally, run the backward pass and watch one sweep produce the total effect for every variable.
The demo wakes as you arrive…
∂+ TARGET∂zi=∂ TARGET∂zi+∑j>i∂+ TARGET∂zj ∂zj∂zi\frac{\partial^{+}\,\mathrm{TARGET}}{\partial z_i} = \frac{\partial\,\mathrm{TARGET}}{\partial z_i} + \sum_{j>i} \frac{\partial^{+}\,\mathrm{TARGET}}{\partial z_j}\, \frac{\partial z_j}{\partial z_i}
The chain rule for ordered derivatives (eq. 7) — This equation gives the total effect of one variable on the target. It does so by starting from the variables that come later. The superscript + marks a total effect; the plain derivatives are direct effects, read off a single equation of the system. So the total effect of ziz_i is its direct effect on the target, plus, for every later variable zjz_j that it feeds, the direct push it gives zjz_j times zjz_j's own total effect. Because each zjz_j comes after ziz_i, its total effect is already known if we work from the end.

Werbos gives the ordered derivative of the error with respect to a variable a short name: the feedback to that variable, written with an "F_" prefix. The recipe then becomes mechanical. Start with the feedback to the outputs, which is just output minus target. Walk the neurons in reverse order. Each neuron's feedback collects the feedback of every later neuron it feeds, weighted by the connection. Multiply by the sigmoid's slope, s′(z)=s(z)(1−s(z))s'(z) = s(z)(1-s(z)), to get the feedback to its net\mathrm{net} input. The gradient for a weight is then that feedback times the activation flowing into the weight. This backward flow of information is where the name comes from. Each neuron's code has a matching that runs the same connections in reverse.

Two practical notes from the paper are worth keeping. First, any ordered derivative can be checked by perturbation: nudge the variable where it is computed and rerun. Werbos insists on this for debugging, and admits he has not run his own pseudocode. Second, the feedback that reaches the inputs is itself useful. It says how sensitive the target is to each input, which is the basis of .

A network with no memory loses the ball

Some classifications improve when the network can use what it saw earlier. Speech and submarine detection are the paper's examples, along with recognising moving objects, which requires comparing the scene at tt with the scene at t−1t-1. Many good recognisers also refine their picture of the world at tt starting from their picture at t−1t-1. Even a Kalman filter works this way.

Werbos's clearest illustration comes later in the paper. Picture a ball that rolls under a table and out the far side. A memoryless predictor sees only the current input. Once the ball is out of sight, it has nothing left to reason from. A predictor with memory can keep tracking the ball. Werbos also cites Harold Szu's version: a memoryless person chased by a tiger forgets the tiger as soon as they turn to run.

The solution is a network whose neurons also take inputs from earlier time steps. Werbos's version is deliberately general: a in which any neuron can read any neuron's value from one or two steps back.

Open in Lab
Press Play and watch both panels when the ball goes under the table. Then change the ball's speed and replay. The memoryless network is now wrong even while it can see the ball, because a single frame shows where the ball is but not how fast it is moving.
The demo wakes as you arrive…
neti(t)=∑j=1i−1Wij xj(t)+∑j=1N+nWij′ xj(t−1)+∑j=1N+nWij′′ xj(t−2)\mathrm{net}_i(t) = \sum_{j=1}^{i-1} W_{ij}\, x_j(t) + \sum_{j=1}^{N+n} W'_{ij}\, x_j(t-1) + \sum_{j=1}^{N+n} W''_{ij}\, x_j(t-2)
A neuron with memory (eq. 15) — The neuron's input now mixes the present with the recent past. The first sum is the ordinary feedforward part, from earlier neurons at the same moment. The second reads every neuron's value one step ago through the weights W′W'. The third reads two steps ago through W′′W''. Any of these weights can be fixed at zero. Werbos notes that most practitioners kept only each neuron's link to its own previous value, which is the form time-delay networks used. Longer lags follow the same pattern. At t=1t = 1 the network needs values for x(0)x(0) and x(−1)x(-1). Most people set them to zero; treating them as extra weights fits the training data but raises the question of what to use on new data.

Unroll, store, then sweep backward

Here is the paper's central observation. A recurrent network still computes its values in a fixed order, as long as that order runs over time as well as over neurons. So the ordered-derivative chain rule applies without change. Backpropagation through time follows from that in three steps.

First, run the network forward over the whole sequence, from t=1t = 1 to t=Tt = T, and keep every intermediate value. Second, treat the run as one large feedforward , with a copy of the network for each time step. This is . The copies are not independent. They share the same weights, which is . Third, send the backward from the last step to the first. At every step, add that step's contribution to each shared weight's gradient.

This solves over time. An input at step tt can now be credited, or blamed, for an error at step t+kt + k. The chain of feedback between them carries that into the gradient.

Open in Lab
Press Next step and watch memory fill during the forward pass; nothing can go backward until step 10 is stored. Then follow the error signal from t = 10 down to t = 1, and see every step add to the same F_W′. The W′ slider sits in a panel marked as later hindsight. Werbos does not discuss vanishing or exploding gradients. The slider only shows how the signal reaching t = 1 shrinks or grows, which Bengio and colleagues analysed in 1994.
The demo wakes as you arrive…
Fxi(t)=FY^i−N(t)+∑j=i+1N+nWji Fnetj(t)+∑j=m+1N+nWji′ Fnetj(t+1)+∑j=m+1N+nWji′′ Fnetj(t+2)F_{x_i}(t) = F_{\hat{Y}_{i-N}}(t) + \sum_{j=i+1}^{N+n} W_{ji}\, F_{\mathrm{net}_j}(t) + \sum_{j=m+1}^{N+n} W'_{ji}\, F_{\mathrm{net}_j}(t+1) + \sum_{j=m+1}^{N+n} W''_{ji}\, F_{\mathrm{net}_j}(t+2)
The backward recurrence in time (eq. 16) — This equation computes the feedback to neuron ii at time tt from four sources. The first is its own error, if it is an output. The second is what it fed to later neurons at the same moment. The third is what it fed to every neuron one step later, through W′W'. The fourth is what it fed two steps later, through W′′W''. Multiplying by the sigmoid's slope turns this into Fneti(t)F_{\mathrm{net}_i}(t) (eq. 11). The recurrent weights' gradients are then running sums over the whole sequence (eqs. 17–18): FWij′=∑tFneti(t+1) xj(t)F_{W'_{ij}} = \sum_t F_{\mathrm{net}_i}(t+1)\, x_j(t), and likewise for W′′W'' with t+2t+2. Feedback from beyond the end, at T+1T+1 and T+2T+2, is zero.
Backpropagation through time with lag-1 and lag-2 links (eqs. 15–18)python

Simplified to show the idea — not the real implementation.

import numpy as np

def s(z):
    return 1.0 / (1.0 + np.exp(-z))

def forward(X, W, W1, W2, m, n):
    # X: (T, m) inputs. Neurons 0..m-1 copy the inputs; the last n are outputs.
    T, K = len(X), W.shape[0]
    x = np.zeros((T + 2, K))        # rows 0,1 hold x(-1), x(0) = 0
    for t in range(T):
        r = t + 2
        x[r, :m] = X[t]
        for i in range(m, K):       # eq (15): same-time, lag-1 and lag-2 inputs
            net = W[i, :i] @ x[r, :i] + W1[i] @ x[r - 1] + W2[i] @ x[r - 2]
            x[r, i] = s(net)
    return x                        # every stored state, kept for the backward sweep

def backward(x, Y, W, W1, W2, m, n):
    T, K = len(Y), W.shape[0]
    F_net = np.zeros((T + 4, K))    # F_net(T+1), F_net(T+2) stay zero
    F_W, F_W1, F_W2 = (np.zeros_like(W) for _ in range(3))
    for t in reversed(range(T)):    # sweep backwards through time
        r, q = t + 2, t             # row in x, row in F_net
        F_x = np.zeros(K)
        F_x[K - n:] = x[r, K - n:] - Y[t]          # eq (9): error at this time
        for i in reversed(range(m, K)):
            F_x[i] += W[i + 1:, i] @ F_net[q, i + 1:]   # same-time paths
            F_x[i] += W1[m:, i] @ F_net[q + 1, m:]      # lag-1 paths, from t+1
            F_x[i] += W2[m:, i] @ F_net[q + 2, m:]      # lag-2 paths, from t+2
            F_net[q, i] = F_x[i] * x[r, i] * (1 - x[r, i])   # eq (11) with (13)
        # eqs (12), (17), (18): every time step adds to the SAME shared weights
        F_W += np.tril(np.outer(F_net[q], x[r]), -1)
        F_W1 += np.outer(F_net[q], x[r - 1])
        F_W2 += np.outer(F_net[q], x[r - 2])
    rows = np.arange(K)[:, None] >= m           # input neurons have no weights
    return F_W * rows, F_W1 * rows, F_W2 * rows

Getting it to train

The paper includes practical advice drawn from Werbos's own experience. BPTT fits naturally with . Derivatives only exist after a complete forward and backward pass, so the weights change once per sequence. The learning rate usually has to be much smaller than for ordinary backpropagation. It also helps to start with the memory weights W′W' fixed at zero, or at one to force memory, and free them gradually.

Not every moment's error has to count. In speech, for example, only the classification at the end of a phoneme may matter. Setting the output feedback to zero at other times handles that, and the paper notes that any other error criterion can be substituted just as easily. When the data come as many separate sequences, such as words or robot trials, runs the full forward and backward pass on one sequence, updates the weights, and moves on. Only one sequence needs to be stored at a time.

Then Werbos turns to . He argues they matter less than rumour suggests when there are many more training patterns than inputs. But he also shows how easily they can appear, with a training set of just three patterns and two weights.

Open in Lab
With square error selected, click near each corner of the dashed triangle, or drop 16 random starts. Every run ends at the same point. Switch to the 1.5-power or absolute error and repeat: the corners of the triangle become separate valleys, and where descent ends depends entirely on where it started.
The demo wakes as you arrive…

Each of the three patterns is fitted exactly along one straight line in weight space, and the three lines form a triangle. Werbos says the triangle's vertices correspond roughly to local minima. Rebuilding his example shows when that holds. With plain squared error and a sigmoid, the troughs are soft, and they merge into a single valley in the middle. With a sharper criterion, such as the 1.5 power of the error that the paper itself suggests, the troughs become steep, and each vertex traps descent. This is the paper's general warning in miniature: conflicting patterns can create minima, even in tiny problems.

On speed, Werbos is blunt. Steepest descent is inefficient. He cites heuristics that sped up convergence a hundredfold. Quasi-Newton methods only work for about a hundred weights. Polak–Ribière need batch learning and very careful line searches. Shanno's conjugate-gradient method worked best for him. He also notes that squared error is not sacred. The 1.5 power works just as well with all the equations above. Adding to a linear network approaches Kohonen's as the penalty grows, an approach some statisticians defended as forecasting by analogy with past cases.

Beyond classifiers — learning how a system moves

The same derivatives serve purposes beyond pattern recognition. In system identification, which Werbos calls neuroidentification, the aim is to learn a forecasting model of a dynamic system. At each step the network receives the observations X(t)X(t) and the actions u(t)u(t) that were under our control, and it is trained to predict X(t+1)X(t+1). Without memory the forecast can only use the present, which brings us back to the ball under the table. BPTT allows a model with a . Werbos lists the remaining weaknesses plainly. Forecasts may degrade over several steps. The method does not identify where the noise comes from. And it cannot adapt in real time.

The method also reaches well beyond neural networks. Any model written as a sequence of differentiable equations, such as an econometric model, can be adapted by building its dual. The backpropagation can even sit inside a statistics package, invisible to the user. Models whose equations must be solved simultaneously at each time step need more care. In network terms these are "doubly recurrent" networks, which Werbos later called a . Networks that settle to an equilibrium, like those of Pineda and Almeida, are special cases. Settling networks are a close relative of the Hopfield network.

Backpropagating utility through a model of the plant

In neurocontrol the target is no longer an error. It is a measure of performance, utility, summed over time. The paper's examples range from the energy a robot arm spends to the net profits of the gas industry. Two networks are involved. A predicts how the system responds. An action network looks at the state and chooses the control u(t)u(t). Only the action network is being trained.

The procedure is BPTT applied to the combined system. Starting from each initial state, run the action network and the model forward to time TT. Then sweep back from TT to 1 through the dual of the utility function, the dual of the model, and the dual of the action network. The sweep yields the derivative of total utility with respect to every action weight. The weights then move up that gradient, not down, because the goal is to maximise. As Werbos puts it, "backpropagation" names how the derivatives are computed. Nothing about the method requires an error or a classification. The approach is the one used by Nguyen and Widrow for their truck backer-upper and by Jordan.

Open in Lab
A toy 1-D truck, built for this page, not Nguyen and Widrow's experiment. Move the horizon slider to set how many steps back the gradient was propagated during training. With K = 1 the truck never moves, and with K = 2 it charges through the dock. Only from about K = 8 does it learn to brake in time. The trajectories were trained offline; nothing trains in your browser.
The demo wakes as you arrive…

The demo shows why the full backward sweep matters in control. Pressing the accelerator now changes the speed at once, but the position only later. The cost of arriving too fast shows up later still. A gradient that looks only one or two steps ahead cannot see those consequences, so it learns a controller that does nothing, or one that crashes. Backpropagating through the whole trajectory lets the effect of a late braking decision reach the weights that made it.

Werbos chose BPTT for his own natural-gas application because it is fast and exact. But he names its blind spot. It treats the model as deterministic, so it cannot account for noise in the process being controlled. For that, and for learning while the system is running, he points to the family. These methods learn to estimate future utility, in the style of approximate , and need no backward pass through time.

The price of exact gradients

BPTT's costs follow from its structure, and Werbos states them clearly. The method needs the whole forward history before it can compute anything. Memory therefore grows with the length of the sequence, and learning happens only after the sequence ends. Sparse connections reduce the storage, but they cannot remove it. This rules out true real-time learning, where each observation is used once and then discarded.

Exact derivatives can also be computed forward in time. The method keeps, at every step, how each neuron depends on each weight. This is the Williams–Zipser method, known today as real-time recurrent learning. The paper does not use that name. Werbos had already considered such forward perturbation equations in 1982 and rejected them for neural networks, because their cost grows with the square of the network's size. The approximate alternative is to recast memory problems as control problems and use adaptive critics. These are inexact and complex, but they run forward in time. Werbos's recommendation for the time being is to accept string learning and not pay that price.

Open in Lab
Move the network-size and sequence-length sliders. These are orders of growth, not measurements. The forward method saves memory only when the sequence is longer than n² steps, and it always costs about n² times more computation. The adaptive-critic row is qualitative, because the paper gives no cost for it.
The demo wakes as you arrive…

What it set in motion

  1. 1974

    Werbos's thesis

    Backpropagation first used in practice, to fit a dynamic model of nationalism and social communication.

  2. 1986

    Backpropagation goes mainstream

    Rumelhart, Hinton and Williams popularise it in Parallel Distributed Processing, acknowledging earlier work by Parker and LeCun.

  3. 1987

    Networks that settle

    Pineda and Almeida extend backpropagation to recurrent networks that relax to equilibrium.

  4. 1989

    Exact gradients forward in time

    Williams and Zipser's method, now called real-time recurrent learning, trades storage for much more computation.

  5. 1990

    This paper

    BPTT set out in full, with pseudocode, alongside its uses in identification and neurocontrol, such as the truck backer-upper.

  6. 1994

    Why long spans are hard

    Bengio, Simard and Frasconi show that gradients carried back over many steps tend to vanish or explode.

  7. 1997

    LSTM

    Hochreiter and Schmidhuber design gated memory so that error can flow across long spans.

What the paper settled was the procedure. Every recurrent neural network trained since uses the unroll-store-sweep procedure described here. It is usually truncated to a fixed window, which is the horizon trade-off from the docking demo, applied to data instead of control.

What the paper left open became the next chapter. It gives exact gradients through long sequences, but it says nothing about their size after a hundred steps. Bengio and colleagues showed that they usually shrink toward zero or blow up, which makes long-range dependencies hard to learn. LSTM was designed to fix that by giving the error a path through time that does not shrink. Both still rely on this paper's backward sweep to compute their gradients.

CitationWerbos. Backpropagation Through Time: What It Does and How to Do It. Proceedings of the IEEE, 1990.

Terms in this paper