DATASCI 447 Lecture 21: Sequences - The Old Ways

Kevin McAlister

March 31, 2026

Administrative Stuff

WHY SEQUENCES?

Last lecture we hit a wall: the VQ-VAE produces a grid of codebook indices, but generating those indices from scratch requires modeling their sequential dependencies.

\[P(s_1, s_2, \ldots, s_{16}) = \prod_i P(s_i \,|\, s_1, \ldots, s_{i-1})\]

But sequences go far beyond image tokens.

Language is a sequence of words. Speech is a sequence of audio frames. Video is a sequence of images. Music, DNA, stock prices — any data where order matters.

The tools we build over the next few lectures apply to all of them.

“FEEDFORWARD” NEURAL NETWORKS

Thus far, we have only seen deep learning architectures where information flows upward through the model

  • Inputs go through layers and yield hidden values
  • Hidden values to more hidden values

Feedforward in the sense that the only direct influence of a layer is to its child

  • In computational graphs, there is no complicated structure that creates feedback between units

“FEEDFORWARD” NEURAL NETWORKS

For tabular data and image analysis:

  • A single input relates to a single output
    • Classification \(\rightarrow\) Class
    • Image Segmentation Map \(\rightarrow\) Semantic Segmentation over \(H \times W\) image
  • A single input leads to two (or more) independent outputs
    • Regression \(\rightarrow\) (Mean, Variance)
    • Bounding Box \(\rightarrow\) (Class, Location)

THE FIVE PATTERNS

  • Image classification (One image to One Class)

THE FIVE PATTERNS

  • Image captioning (One image to a sequence of words)

THE FIVE PATTERNS

  • Video classification (Many images/frames to one video class)
  • Sentiment analysis (Sequence of words to one sentiment label)

THE FIVE PATTERNS

Not necessarily equal number of inputs and outputs

  • Machine translation (Sequence of words in English to Seq in French)
  • Sentence continuation (First part of sentence to second part)
  • Time series (Stock prices for last 10 years to prices for the next week)

THE FIVE PATTERNS

Equal number of outputs and inputs

  • Per-frame video classification (Seq of Images to Seq of Words)
  • Per-sentence sentiment analysis (Seq of sentences to Class)
  • Next-token prediction (Seq of codebook indices to Seq of next indices)

FEEDFORWARD NETWORKS CAN’T DO THIS

A feedforward network maps one fixed-size input to one fixed-size output. No memory. No sense of order.

We could concatenate the entire sequence into one long vector and feed it through an MLP. But sequences have variable length, and the model would need position-specific weights for every possible length.

No weight sharing across time. No generalization to new sequence lengths.

If the order of the input matters, we need an architecture that preserves it.

RECURRENT NEURAL NETWORKS

Recurrent Neural Networks (RNNs) are the backbone of sequence modeling

  • Inputs or outputs make sense temporally
  • Knowing what came before should inform what we predict now

Adds knowledge to the NN architecture

  • Units need to talk backwards in time — all of the previous values need to influence what I guess next!

If the order of the input matters, then we should preserve that information!

THE RECURRENCE FORMULA

We can process a sequence of vectors, \(\mathbf{x}\), by applying a recurrence formula at every time step:

\[\mathbf{h}_t = f_w(\mathbf{h}_{t-1}, \mathbf{x}_t)\]

  • \(\mathbf{h}_{t-1}\) is the old state (some vector of numbers)
  • \(\mathbf{x}_t\) is the input at time \(t\) (some vector - think an embedding of length 32)
  • \(f_w()\) is a function of some parameters, \(\mathbf{W}\) (some collection of weight matrices)
  • \(\mathbf{h}_t\) is the new state (some vector)

THE HIDDEN STATE AS LATENT REPRESENTATION

The hidden state vector contains latent information about the current state of the model

  • For language models, it could tell us about the gender of pronouns in the sentence
  • Or the passiveness of the tone
  • For image tokens, it could encode the spatial context seen so far

This information should persist throughout the sequence of predictions!

  • Create memory from one prediction to the next (passive tone should persist).

The hidden state is a latent vector — a compressed representation of the sequence, just like \(\mathbf{z}\) in the VAE is a compressed representation of an image.

UNROLLING THE RNN

Start with an initial state, \(\mathbf{h}_0\)

THE VANILLA UPDATE

\[\underset{(m \times 1)}{\mathbf{h}_t} = \text{tanh}\left(\underset{(m \times m)}{\mathbf{W}_{hh}} \underset{(m \times 1)}{\mathbf{h}_{t-1}} + \underset{(m \times P)}{\mathbf{W}_{xh}} \underset{(P \times 1)}{\mathbf{x}_t} + \underset{(m \times 1)}{\mathbf{b}_h}\right)\]

  • \(\mathbf{h}_t\) and \(\mathbf{h}_{t-1}\) are hidden vectors of size \(m\)
  • \(\mathbf{W}_{hh}\) is a \(m \times m\) matrix that controls the mapping of one hidden state to the next
  • \(\mathbf{W}_{xh}\) is a \(m \times P\) matrix that controls the mapping of the input to the hidden state
  • \(\mathbf{b}_h\) is a vector of bias terms
  • \(\text{tanh}()\) is a nonlinear activation function that elementwise maps values between -1 and 1

THE VANILLA UPDATE

\[\underset{(m \times 1)}{\mathbf{h}_t} = \text{tanh}\left(\underset{(m \times m)}{\mathbf{W}_{hh}} \underset{(m \times 1)}{\mathbf{h}_{t-1}} + \underset{(m \times P)}{\mathbf{W}_{xh}} \underset{(P \times 1)}{\mathbf{x}_t} + \underset{(m \times 1)}{\mathbf{b}_h}\right)\]

Drawing some parallels to what we’ve seen before:

  • \(\mathbf{h}_t\) is like a higher level of hidden values — a function of the previous hidden values passed through an activation
  • \(\mathbf{W}_{hh}\) maps these two hidden layers to one another
  • \(\mathbf{W}_{xh}\) grounds the new hidden state to its input

A FCNN with a twist!

THE OUTPUT AT EACH STEP

Note that \(\mathbf{x}_1\) only relates to \(\mathbf{y}_1\) through \(\mathbf{h}_1\)!

Given a hidden state, we say that \(\mathbf{y}_t\) is determined as:

\[\underset{(G \times 1)}{\mathbf{y}_t} = g\left(\underset{(G \times m)}{\mathbf{W}_{hy}} \underset{(m \times 1)}{\mathbf{h}_t} + \underset{(G \times 1)}{\mathbf{b}_y}\right)\]

  • \(g()\) maps the linear predictor to the scale of the output (softmax for classes, identity for regression)

WEIGHT SHARING ACROSS TIME

The part that is so simple that it’s kinda dumb

  • But works amazingly

Use the same \(\mathbf{W}_{hh}\), \(\mathbf{W}_{xh}\), and \(\mathbf{W}_{hy}\) at all time points

HOW \(\mathbf{y}_2\) SEES THE WHOLE HISTORY

Let’s think about how \(\mathbf{y}_2\) is computed.

  • \(\mathbf{y}_2\) is a function of \(\mathbf{h}_2\)
  • \(\mathbf{h}_2\) is a function of \(\mathbf{h}_1\) and \(\mathbf{x}_2\)
  • \(\mathbf{h}_1\) is a function of \(\mathbf{h}_0\) and \(\mathbf{x}_1\)

Let \(\xi()\) be the \(\text{tanh}\) activation. Dropping bias terms:

\[\mathbf{y}_2 = \mathbf{W}_{hy} \xi(\mathbf{W}_{hh} \xi(\mathbf{W}_{hh} \mathbf{h}_0 + \mathbf{W}_{xh} \mathbf{x}_1) + \mathbf{W}_{xh} \mathbf{x}_2)\]

Every output sees the full history through the chain of hidden states.

A SIMPLE LANGUAGE MODEL

Let’s look at an aligned many-to-many model!

Goal: Given input characters, build a model to predict the next character!

A SIMPLE LANGUAGE MODEL

A SIMPLE LANGUAGE MODEL

A SIMPLE LANGUAGE MODEL

A SIMPLE LANGUAGE MODEL

A SIMPLE LANGUAGE MODEL

A SIMPLE LANGUAGE MODEL

GENERATION FROM A LANGUAGE MODEL

For test-time, generate new text

  • Suppose we just have an “h” and want to see what the RNN will generate

GENERATION FROM A LANGUAGE MODEL

GENERATION FROM A LANGUAGE MODEL

GENERATION FROM A LANGUAGE MODEL

This is autoregressive generation — the same process we need for VQ-VAE codebook indices. Predict the next token, feed it back, predict the next.

TEXT EMBEDDINGS

Right now, a basic one-hot encoded character vector.

What if we want to see something that was not necessarily used to train the model?

Text embeddings are used to pre-process text (an inherently discrete variable) into a lower dimensional continuous space

Same idea as the categorical embeddings we used for breed and color in the VQ-VAE!

self.embed = nn.Embedding(vocab_size, embed_dim)
# "h" → learned 32-dim vector
# "e" → different learned 32-dim vector
  • Can be pre-trained on large corpora — more on this when we get to transformers

THE MANY ARCHITECTURES

Many-to-One:

  • \(\mathbf{W}_{hy}\) is only used for the single output

THE MANY ARCHITECTURES

One-to-Many:

SEQ2SEQ: THE ENCODER-DECODER RNN

Pre-GPT, the seq2seq model was a main approach for question/answer and translation models

SEQ2SEQ: THE ENCODER-DECODER RNN

This is another example of an encoder/decoder architecture:

  • Use weights to determine the mapping of the inputs to a final hidden state
  • Use that hidden state as the beginning of a new mapping to the outcome

“The cat sat on the mat” \(\to\) encoder \(\to\) \(\mathbf{h}_6\) \(\to\) decoder \(\to\) “That durn cat is sittin on the rug”

The entire input sentence — every word, every grammatical relationship — must be compressed into a single vector \(\mathbf{h}_T\).

Sound familiar? This is the same information bottleneck as the VAE’s flat vector.

WHY TANH?

WHY TANH?

Tanh is used here over ReLU for a number of reasons:

  • RNNs aren’t going to promote sparsity since there isn’t a meaningful way to map hidden units to input features
  • RNNs have a really serious vanishing gradient problem (more to come)
  • Unlike CNNs, RNNs have a really serious exploding gradient problem!
  • Squish values to \([-1, 1]\) — prevents the hidden state from growing without bound since \(\mathbf{W}_{hh}\) is applied multiplicatively at every step

But tanh has a problem we’re about to see.

TRAINING: BACKPROPAGATION THROUGH TIME

Given \(\mathbf{X}\) and \(\mathbf{Y}\), we need to learn \(\mathbf{W}_{hh}\), \(\mathbf{W}_{xh}\), and \(\mathbf{W}_{hy}\)

  • The hidden states \(\{\mathbf{h}_1, \ldots, \mathbf{h}_T\}\) are just a function of these values

The loss sums over all time steps:

\[\mathcal{L}(\hat{\mathbf{Y}}, \mathbf{Y}) = \sum_{t=1}^{T} \mathcal{L}(\hat{\mathbf{y}}_t, \mathbf{y}_t)\]

THE GRADIENT CHAIN

The gradient for \(\mathbf{W}_{hh}\):

\[\frac{\partial \mathcal{L}}{\partial \mathbf{W}_{hh}} = \frac{\partial \mathcal{L}}{\partial \mathbf{h}_T}\frac{\partial \mathbf{h}_T}{\partial \mathbf{h}_{T-1}}\frac{\partial \mathbf{h}_{T-1}}{\partial \mathbf{h}_{T-2}} \cdots \frac{\partial \mathbf{h}_1}{\partial \mathbf{W}_{hh}}\]

Assuming tanh activation:

\[\frac{\partial \mathbf{h}_t}{\partial \mathbf{h}_{t-1}} = \text{tanh}'(\mathbf{W}_{hh}\mathbf{h}_{t-1} + \mathbf{W}_{xh}\mathbf{x}_t) \cdot \mathbf{W}_{hh}\]

A product of \(T\) terms, each involving \(\text{tanh}'\) and \(\mathbf{W}_{hh}\).

THE DERIVATIVE OF TANH

The derivative of tanh w.r.t its input is always between 0 and 1!

THE VANISHING GRADIENT PROBLEM

\[\frac{\partial \mathcal{L}}{\partial \mathbf{W}_{hh}} = \frac{\partial \mathcal{L}}{\partial \mathbf{h}_T} \frac{\partial \mathbf{h}_1}{\partial \mathbf{W}_{hh}} \mathbf{W}_{hh}^{T-1} \prod_{t=2}^{T} \text{tanh}'(\mathbf{W}_{hh}\mathbf{h}_{t-1} + \mathbf{W}_{xh}\mathbf{x}_t)\]

Double trouble:

  • \(\text{tanh}'\) is between 0 and 1 \(\to\) product shrinks exponentially
  • \(\lim_{t \to \infty} \mathbf{W}_{hh}^t\) depends on the largest singular value of the matrix
    • If greater than 1 \(\to\) goes to \(\infty\) (exploding)
    • If less than 1 \(\to\) goes to zero (vanishing)

There’s no escape…

VISUALIZING THE PROBLEM

Assuming linear activation functions:

\[\mathbf{y}_2 = \mathbf{W}_{hy} \mathbf{W}_{hh} \mathbf{W}_{hh} \mathbf{h}_0 + \mathbf{W}_{hy} \mathbf{W}_{hh} \mathbf{W}_{xh} \mathbf{x}_1 + \mathbf{W}_{hy} \mathbf{W}_{xh} \mathbf{x}_2\]

\[\mathbf{y}_3 = \mathbf{W}_{hy} \mathbf{W}_{xh} \mathbf{x}_3 + \mathbf{W}_{hy} \mathbf{W}_{hh} \mathbf{W}_{xh} \mathbf{x}_2 + \mathbf{W}_{hy} \mathbf{W}_{hh}^2 \mathbf{W}_{xh} \mathbf{x}_1 + \mathbf{W}_{hy} \mathbf{W}_{hh}^3 \mathbf{h}_0\]

The influence of \(\mathbf{x}_1\) on \(\mathbf{y}_3\) goes through \(\mathbf{W}_{hh}^2\). On \(\mathbf{y}_{100}\) it goes through \(\mathbf{W}_{hh}^{99}\).

Small times small equals smaller!

THE SEQ2SEQ BOTTLENECK

This is also why Seq2Seq struggles with long sequences.

The entire input sentence — every word, every grammatical relationship — must be compressed into a single vector \(\mathbf{h}_T\).

For a 50-word paragraph, \(\mathbf{h}_T\) is the same size as for a 5-word sentence. Information loss is inevitable.

This is the same information bottleneck as the VAE’s flat vector. And the fix will be analogous — instead of compressing everything into one vector, let the decoder access the full sequence of encoder states.

That fix is called attention — next lecture.

THE SEQ2SEQ BOTTLENECK

THE LSTM: A CLEVER FIX

A clever solution to the vanishing gradient problem — The Long Short-Term Memory model (LSTM)

There’s a lot going on here. Let’s take it step-by-step.

LSTM: THE CELL STATE

LSTMs alter the RNN model by having two concurrently running hidden units — the hidden state and the cell state

The cell state runs straight down the chain with only some minor linear interactions

  • The gradient is easy to compute and doesn’t change exponentially!

LSTM: GATES CONTROL INFORMATION FLOW

The hidden state can add or remove information from the cell state through gates

A sigmoid layer (which maps a value between 0 and 1) determines when and how much the hidden state should influence the next one!

LSTMs have 3 of these gates to protect and control the cell state.

LSTM: THE FORGET GATE

The forget gate controls how we lose information from the previous memory

  • In a language model, maybe the hidden state encodes the gender of the subject
  • The subject changes and uses different pronouns?
  • It’s not worthwhile to remember the gender state in this case.

The sigmoid activation is applied element-wise — some parts of the vector might be more useful to remember than others.

LSTM: THE INPUT GATE

Two weight matrices — the input weights and the candidate gate

  • A candidate hidden vector \(\tilde{\mathbf{C}}_t\) is created using the standard update with a tanh activation
  • The input gate applies a value between 0 and 1 to each element — how much of the new information should be added?

LSTM: THE CELL STATE UPDATE

The new cell state is a linear combination of the old cell state and the candidate, weighted by the forget gate and the input gate:

\[\mathbf{C}_t = \mathbf{f}_t \odot \mathbf{C}_{t-1} + \mathbf{i}_t \odot \tilde{\mathbf{C}}_t\]

The gradient:

\[\frac{\partial \mathbf{C}_t}{\partial \mathbf{C}_{t-1}} = \mathbf{f}_t\]

No matrix multiplication. No tanh derivative. Just the forget gate — a sigmoid between 0 and 1. A gradient highway through time.

LSTM: THE OUTPUT GATE

The output gate creates a filtered version of the cell state

  • Sigmoid activation determines which parts of the state are relevant for the next prediction
  • Cell state is pushed through tanh and multiplied by the output gate

LSTM: THE GRADIENT HIGHWAY

What does this accomplish for gradients?

  • \(\mathbf{C}_t\) only connects to \(\mathbf{C}_{t-1}\) through \(\mathbf{f}_t\) — no direct interaction with \(\mathbf{W}\) or tanh!
  • The cell state is a smooth version of the hidden state — updated with small perturbations at each time step

This is the same principle as ResNets: create a highway for gradients that bypasses the nonlinear transformations.

  • ResNets add skip connections across layers (depth)
  • LSTMs add skip connections across time steps (sequence length)

LSTMs are the default — not a special case. Most RNN architectures use LSTM cells as they are much easier to train.

GRU: THE SIMPLIFIED VERSION

The Gated Recurrent Unit (Cho et al., 2014) achieves similar performance with fewer parameters.

Two gates instead of three:

  • Reset gate \(\mathbf{r}_t\): how much of the previous hidden state to forget when computing the candidate
  • Update gate \(\mathbf{z}_t\): how much to keep of the old state vs the new candidate

\[\tilde{\mathbf{h}}_t = \tanh(\mathbf{W}_{xh}\mathbf{x}_t + \mathbf{W}_{hh}(\mathbf{r}_t \odot \mathbf{h}_{t-1}))\] \[\mathbf{h}_t = \mathbf{z}_t \odot \mathbf{h}_{t-1} + (1 - \mathbf{z}_t) \odot \tilde{\mathbf{h}}_t\]

No separate cell state. The update gate interpolates between old and new directly. Simpler, faster, often works just as well.

GRU: THE SIMPLIFIED VERSION

THE FUNDAMENTAL LIMITATION

LSTMs and GRUs mitigate vanishing gradients but don’t solve the fundamental problem:

The hidden state is still a fixed-size vector. At step 1000, the entire sequence history must fit in the same 256 or 512 dimensions that step 2 used for just one input.

Information gets overwritten. The Seq2Seq bottleneck persists — long sequences lose early information regardless of gating.

And training is sequential. \(\mathbf{h}_t\) depends on \(\mathbf{h}_{t-1}\) — you can’t parallelize across time steps. Long sequences are slow.

WHAT WE NEED

Two problems to solve:

  1. The bottleneck: the decoder should access all encoder states, not just the final summary
  2. The parallelism: we shouldn’t have to process the sequence one step at a time

Both problems are solved by attention — a mechanism that lets any position directly attend to any other position, bypassing the sequential hidden state chain entirely.

Next lecture: how attention works, and why it replaces recurrence.

SUMMARY

  • Sequences are everywhere — language, audio, video, image tokens
  • RNNs add memory through a recurrent hidden state with shared weights across time
  • The hidden state is a latent representation — the same concept as \(\mathbf{z}\) in a VAE
  • Backpropagation through time creates vanishing/exploding gradients — the product of \(T\) matrices shrinks or grows exponentially
  • LSTMs add a cell state with additive updates — gradient highways through time, same principle as ResNets
  • GRUs simplify to two gates and no cell state — similar performance, fewer parameters
  • The fundamental limitation: fixed-size hidden state, sequential processing, information bottleneck
  • Next: attention solves both the bottleneck and the parallelism problem