12

Sequences and memory

How does a network process something that happens in order, like a sentence?

10 min

Sequences and memory

With voice. You can pause and jump to any step.

Lesson complete

Subtitles

Look at this sentence: “The flowers I bought at the market are wilted.” To get “are” and not “is,” you have to remember “flowers,” which is six words back.

Voice

No voice: the lesson advances on its own with subtitles.

The voice for this lesson is being recorded: for now it advances on its own with subtitles.

0:00 / 0:00

What you will achieve

  • Explain how a recurrent network reads a sequence step by step and what its hidden state holds.
  • Predict what happens to the blame for the error when it travels back through many steps, and why it fades or turns erratic.
  • Describe what the gates of an LSTM do (forget, write, read) and which limits still stand.

Key ideas

  1. A sequence is data whose order matters and whose length varies. A recurrent network reads it step by step with the same cell and passes a hidden state, its memory, from one step to the next.
  2. Unrolled in time, an RNN is a deep network with one layer per step and the same weights in all of them. Training it means backpropagating through time.
  3. The blame for the error is multiplied by a factor at every step it travels back. With factors below one it vanishes and what is far away is not learned; with large weights it turns erratic and the state saturates.
  4. The LSTM adds a memory belt and three learned gates (forget, input, and output, with values between zero and one). With the forget gate near one, the blame travels almost intact along the belt.
  5. Even so, the LSTM runs in a line (steps are not computed at once), squeezes everything into one fixed-size vector, and its useful memory is still short: those limits motivate attention.

What many people believe

Common belief A recurrent network remembers the whole sentence word by word, like a notebook.

What is true It keeps a fixed-size summary, a handful of numbers rewritten at every step, and what came early fades. The LSTM stretches that memory with gates, but it stays short.

Check yourself

Four questions. No grade, no account: they just show whether the idea stuck.

ConceptA recurrent network reads a sentence word by word. What is its hidden state?
ConceptWhy does the gradient vanish in an RNN that reads long sequences?
CalculationAt each step the blame is multiplied by 0.8. How much is left after ten steps?
ApplicationA vendor proposes a recurrent network to review contracts hundreds of pages long and says it “remembers the whole document.” What should you ask for?

Under the hoodFor those who want the math and the code. You do not need it to follow the course.

The recurrent cell

Given an input xt∈RDx_t\in\mathbb{R}^{D} and a state ht−1∈RHh_{t-1}\in\mathbb{R}^{H}, Elman’s RNN computes

ht=tanh⁡ ⁣(Wx xt+Wh ht−1+b),h0=0,h_t=\tanh\!\left(W_x\,x_t+W_h\,h_{t-1}+b\right),\qquad h_0=\mathbf 0,

with Wx∈RH×DW_x\in\mathbb{R}^{H\times D}, Wh∈RH×HW_h\in\mathbb{R}^{H\times H}, and b∈RHb\in\mathbb{R}^{H}. That is H(H+D)+HH(H+D)+H parameters, the same at every step: they do not grow with the length of the sentence. To predict the next word, an output layer is added, y^t=softmax(Wyht)\hat y_t=\mathrm{softmax}(W_y h_t) (lesson 19). In the lesson, H=6H=6, D=4D=4, with no bias (6060 parameters) and random, untrained weights: only the mechanics are on display.

Blame through time

The total loss is L=∑tLtL=\sum_t L_t. The blame that reaches state hkh_k from step TT is the chain rule (lesson 8) applied along time:

∂LT∂hk=∂LT∂hT∏t=k+1T∂ht∂ht−1,∂ht∂ht−1=diag ⁣(1−ht2)Wh.\frac{\partial L_T}{\partial h_k}=\frac{\partial L_T}{\partial h_T}\prod_{t=k+1}^{T}\frac{\partial h_t}{\partial h_{t-1}},\qquad \frac{\partial h_t}{\partial h_{t-1}}=\mathrm{diag}\!\left(1-h_t^{2}\right)W_h .

It is a product of T−kT-k matrices. The scene shows the size of that product, ∥∂hT/∂hk∥F/H\|\partial h_T/\partial h_k\|_F/\sqrt{H} (the typical gain for a nudge in a random direction; 11 = nothing is lost). Since ∣1−h2∣≤1|1-h^2|\le 1, if the norm of WhW_h (its largest singular value) is g<1g<1, the product falls like an exponential: ∥∂hT/∂hk∥≤g T−k\|\partial h_T/\partial h_k\|\le g^{\,T-k}. With a sigmoid the ceiling of the derivative is 1/41/4 and everything falls faster (lesson 8). In general, Pascanu, Mikolov, and Bengio (2013) show, for a nonlinearity with ∣σ′∣≤γ|\sigma'|\le\gamma (γ=1\gamma=1 for tanh, 14\tfrac14 for sigmoid), that λ1<1/γ\lambda_1<1/\gamma is **sufficient** for the far contribution to vanish, and that λ1>1/γ\lambda_1>1/\gamma is necessary for it to explode (λ1\lambda_1: the largest eigenvalue of WhW_h in absolute value).

With λ1>1/γ\lambda_1>1/\gamma an explosion is not guaranteed: tanh saturates (1−h2≈01-h^2\approx0) and switches units off, as the scene shows, where with large weights the blame turns erratic, huge in some sentences and nearly zero in others. Two classic remedies: clip the gradient norm against explosion (Pascanu et al., 2013) and redesign the cell against vanishing. Bengio, Simard, and Frasconi (1994) add a dilemma: to store a datum stably against noise the dynamics must contract, and that makes long-term gradients vanish.

The LSTM

With gates ft,it,ot∈(0,1)Hf_t,i_t,o_t\in(0,1)^H, a candidate c~t\tilde c_t, and the elementwise product ⊙\odot:

ft=σ(Wf[ht−1,xt]+bf),it=σ(Wi[ht−1,xt]+bi),ot=σ(Wo[ht−1,xt]+bo),c~t=tanh⁡(Wc[ht−1,xt]+bc),ct=ft⊙ct−1+it⊙c~t,ht=ot⊙tanh⁡(ct).\begin{aligned} f_t&=\sigma(W_f[h_{t-1},x_t]+b_f), & i_t&=\sigma(W_i[h_{t-1},x_t]+b_i),\\ o_t&=\sigma(W_o[h_{t-1},x_t]+b_o), & \tilde c_t&=\tanh(W_c[h_{t-1},x_t]+b_c),\\ c_t&=f_t\odot c_{t-1}+i_t\odot\tilde c_t, & h_t&=o_t\odot\tanh(c_t). \end{aligned}

The belt ctc_t is updated by addition, not by rewriting. Along it, ∂ct/∂ct−1=diag(ft)\partial c_t/\partial c_{t-1}=\mathrm{diag}(f_t) (plus indirect paths through hh), so the blame is multiplied only by the forget gate: with f≈1f\approx1 it arrives nearly intact, the “constant error carousel” of the 1997 paper. The original LSTM had input and output gates; the forget gate was added by Gers, Schmidhuber, and Cummins (2000). A practical trick: initialize the bias bfb_f near 11 so the belt starts open (Jozefowicz et al., 2015). A layer has 4H(H+D)+4H4H(H+D)+4H parameters: four times those of the RNN. With H=D=1000H=D=1000 that is 8,004,0008{,}004{,}000. Stacked LSTMs went far: Google’s neural machine translation system (Wu et al., 2016) used eight LSTM layers in the encoder and eight in the decoder, with attention and residual connections.

In the lesson the gates are fixed numbers and there is a single cell: ct=f ct−1+ittanh⁡(vt)c_t=f\,c_{t-1}+i_t\tanh(v_t), ht=otanh⁡(ct)h_t=o\tanh(c_t), where vtv_t are illustrative grammatical-number cues (plural for “flowers,” singular for “market”) and it=1i_t=1 at the key word. A trained network computes ftf_t and iti_t from the word and the state. In 2019, Lakretz et al. found that, in an LSTM trained as a language model, long-distance number information is largely managed by two “number units,” just what our toy cell does.

In code

import numpy as np

def influence(g, steps):
    """How much of a nudge to the initial state survives after `steps` steps (2-unit RNN with tanh)."""
    c, s = np.cos(0.8), np.sin(0.8)
    Wh = g * np.array([[c, -s], [s, c]])        # a 0.8 rad rotation, scaled by g
    x = np.array([0.5, -0.3])                   # the “word” that arrives at every step
    h, P = np.zeros(2), np.eye(2)
    for _ in range(steps):
        h = np.tanh(Wh @ h + x)
        P = ((1 - h**2)[:, None] * Wh) @ P      # P = J_t · P, with J_t = diag(1 − h²) · Wh
    return np.linalg.norm(P) / np.sqrt(2)

for g in (0.5, 0.9, 1.5, 2.0):
    print(g, [round(float(influence(g, n)), 4) for n in (1, 5, 10, 20)])
# 0.5 [0.4266, 0.0083, 0.0001, 0.0]
# 0.9 [0.7679, 0.0989, 0.0152, 0.0004]
# 1.5 [1.2798, 0.8562, 1.218, 1.154]
# 2.0 [1.7064, 2.2703, 2.4696, 1.3574]

With g=0.5g=0.5 or 0.90.9 the nudge dies out; with g=2g=2 it is amplified; around g=1.5g=1.5 and with this fixed input there is a narrow window where it holds. A small move takes you out of it.

import math

cues = [0, 1.2, 0.3, -0.5, 0.2, -0.1, -0.9]      # number cue for each word (illustrative)

def cell(f, i, o):
    c = 0.0
    for t, v in enumerate(cues, start=1):
        gate_in = 1.0 if t == 2 else i               # “flowers” opens the input gate
        c = f * c + gate_in * math.tanh(v)           # the belt: forget a little, write a little
    return o * math.tanh(c)                          # what is read at the end (positive = plural)

print(round(cell(0.6, 0.8, 1.0), 3))    # -0.5   (the cue is lost and “market” wins: singular)
print(round(cell(1.0, 0.1, 1.0), 3))    # 0.638  (plural)
print(round(0.97 ** 5, 2))               # 0.86   (blame reaching “flowers” along the belt)

What comes next

The RNN and the LSTM read in a line and squeeze everything into one vector; attention (lesson 21) lets each word look directly at the others, in parallel. Before that, lesson 13 tells why deep learning took off around 2012: data, GPUs, and a few tricks, among them residual connections, which in depth play a role similar to the LSTM’s belt.

Decision lens

What this idea means if your job is to decide, not to code.

  • Theoretical memory is not useful memory. When a vendor says its model “remembers the whole context,” ask for a test with texts as long as yours: LSTM language models were measured using only about two hundred words of context.
  • What runs in a line costs time. A recurrent architecture processes the steps of a sequence one after another: training and response time grow with the length of the text, and the GPU is poorly used. Ask how latency scales with length.
  • Sequence models remain reasonable for small problems: short time series, sensors, low-compute devices. If someone proposes an LSTM, ask why that one and not another architecture, and what data it was compared on.
  • The symptom of a short memory is getting the recent right and missing what depended on something far away: agreement, references, a clause from the beginning. Design tests that put the key fact far from the question.

Terms in this lesson

Full transcript
CommentsThis lesson’s public conversation: questions, facts to check, ideas.

Comments live in GitHub Discussions, in the course’s public repository; writing one requires a GitHub account. They load from giscus.app when you open this section. The course reviewers read them, and if a change is accepted, it is applied in both languages. Open the thread on GitHub

Sources