CS 601.471/671  ·  NLP: Self-supervised Models  ·  Fall 2026

Handout #3 — From Counting to Learning

Session 3 (Tue, Sept 8)  ·  Slides: Feedforward Nets  ·  Course page

Handout #2 ended at a wall: counting gives you an excellent estimate for contexts you have seen and nothing at all for the rest, and every repair was a rule someone designed by hand. This handout takes the way out. Stop counting; fit a function instead — and then work out what kind of function, and how you fit it.

Assigned papers
None. This handout is the reading for Session 3. §7 lists optional depth if you want it.
Time
50–70 minutes.
By the end you should be able to
  • reframe language modeling as supervised function fitting, and draw a fixed-window neural language model;
  • say what a neural network is in one sentence, and prove why the nonlinearity is not optional;
  • track shapes through a batched layer, and count what it costs;
  • write the gradient descent update, and derive when it diverges;
  • explain why we use minibatches instead of the true gradient.
Assumes
Handout #1 §1.1 (matrix products, shapes), §1.3 (gradients), §1.4 (cost), and Handout #2 §3.2 (sparsity — the problem this handout solves).
Note
Quiz #1 is the next session (Thu, Sept 10), covering everything up to that point — this handout included.

1Language modeling as a learning problem

Here is the reframing that opens the rest of the course. Everything so far treated estimation as counting. Treat it instead as fitting a function.

We want a function $f_\theta$ that maps a context to a distribution over the vocabulary. The training data is free — Handout #1 §2.1 — one example per position in the corpus. The loss is cross-entropy, which §5 just told us is the thing we want to minimize anyway. That is an ordinary supervised learning problem.

1.1  A fixed-window neural language model

The simplest version keeps the Markov assumption and changes only how the conditional is computed. Fix a window — say four words. Discard anything earlier. Look up a vector (an embedding) for each of the four words, hand the collection to a neural network with parameters $\Theta$, and have it emit a distribution over the whole vocabulary. Train $\Theta$ to put high probability on the word that actually came next.

blah blah blah discarded and our problems turning into context window of size 4 target word look up embeddings ○○○○○○ ○○○○○○ f( context , Θ ) neural network, trainable parameters probabilities over the vocabulary mat table into ant chair push this up
A fixed-window neural language model (Bengio et al., 2003). Same Markov assumption as a trigram; entirely different way of computing the conditional.

Note what has and has not changed. The window is still finite, so long-range dependencies are still invisible — this model does not solve Handout #2 §1.3's computer … crashed problem. What it solves is sparsity.

1.2  Why representations beat counting

IngredientCountingLearning
Input the previous $n-1$ words, as a table key the previous $n-1$ words, as vectors
Parameters $V^n$ counts, one per n-gram a fixed set of weights, independent of $V^n$
Fitting one pass; closed-form MLE gradient descent on cross-entropy
Unseen context zero — patched by hand-designed smoothing a prediction, from contexts the model considers similar

That last row is the whole argument. A count table has no notion that the dog slept resembles the cat slept: they are different keys, and what you learn about one tells you nothing about the other. Represent words as vectors and the context as a function of those vectors, and similarity comes for free — if dog and cat end up with nearby vectors because they occur in similar places, a prediction learned for one context transfers to the other automatically.

Generalization replaces smoothing. Not as a patch, but as a structural property. And notice the parameter count: a neural LM's size does not grow with $V^n$, so the exponential wall in Handout #2 §3.2 simply is not there. That is why the 2003 paper mattered, and why every model in this course descends from it.

One thing counting still does better Interpretability, completely. Every probability an n-gram model produces is a ratio of two integers you can look up, and if it is wrong you can see exactly which counts made it wrong. Nothing in the remainder of this course will be so transparent again. Keep the comparison in mind when we discuss interpretability later — n-grams are the baseline for what "understanding a model" could mean.

2What a neural network is

§1 left a box in the diagram labelled "neural network" and an obligation to explain it. Strip away the mystique and the object is unglamorous: a neural network is a function built by alternating matrix multiplications with a simple nonlinear function. That is the whole definition. Everything else — depth, architecture, attention — is a choice about which matrices and in what order.

2.1  One unit

Start with a single unit. It takes a vector $x \in \mathbb{R}^d$, scores it against a weight vector $w$, adds a bias $b$, and passes the result through a nonlinear activation $\sigma$:

$$ a = \sigma\!\left(w^\top x + b\right) = \sigma\!\left(\sum_{i=1}^{d} w_i x_i + b\right). $$

The inner product is the operation from Handout #1 §1.1, doing exactly what §1.2 said an inner product does: measuring alignment. A unit asks "how much does this input look like the pattern $w$?", shifts the answer by $b$, and squashes it.

2.2  A layer is a matrix

Now put $m$ units side by side. Each has its own weight vector, so stack them as rows of a matrix $W \in \mathbb{R}^{m \times d}$, collect the biases into $b \in \mathbb{R}^m$, and all $m$ units compute at once:

$$ h = \sigma(Wx + b), \qquad W \in \mathbb{R}^{m \times d},\; x \in \mathbb{R}^{d},\; h \in \mathbb{R}^{m}. $$

This is why the whole field runs on matrix multiplication, and why Handout #1 §1.4 insisted you be able to count its cost: a layer is $O(md)$, and $\sigma$ is applied element-wise, so it is free by comparison. The hardware story in Handout #1 §4 is a story about making this one line fast.

A feedforward network (or multi-layer perceptron, MLP) is that line repeated, each layer feeding the next:

$$ h_1 = \sigma(W_1 x + b_1), \quad h_2 = \sigma(W_2 h_1 + b_2), \quad \ldots, \quad \hat{y} = W_L h_{L-1} + b_L. $$

Note the last layer usually has no activation — for language modeling its output is the logits, and softmax comes after. The vector $\theta = \{W_1, b_1, \ldots, W_L, b_L\}$ is everything the model has learned, and "a model with 7 billion parameters" is a statement about the total size of these matrices.

Why the nonlinearity is not optional Suppose we drop $\sigma$ and stack two linear layers. Then $$ h_2 = W_2(W_1 x + b_1) + b_2 = (W_2 W_1)x + (W_2 b_1 + b_2) = W' x + b', $$ which is a single linear layer. Composing linear maps gives a linear map, so without $\sigma$ a thousand-layer network has exactly the expressive power of one layer — and no linear function can separate points that are not linearly separable. The nonlinearity is the only reason depth buys anything. This is worth being able to derive on the spot; it uses nothing but the associativity of matrix multiplication from Handout #1 §1.1b.

2.3  The activations you will meet

NameDefinitionRangeWhere you see it
ReLU $\max(0, z)$ $[0, \infty)$ The default inside modern networks. Cheap, and its gradient is 1 or 0 — which is exactly why it does not suffer the vanishing-gradient problem the others do.
Sigmoid $\dfrac{1}{1+e^{-z}}$ $(0, 1)$ Historically the default; now mostly used to produce a single probability. You already differentiated it in Handout #1 §1.3a.
Tanh $\dfrac{e^{z}-e^{-z}}{e^{z}+e^{-z}}$ $(-1, 1)$ A zero-centred sigmoid. Standard inside recurrent networks (Sessions 8–9).
Softmax $\dfrac{e^{z_i}}{\sum_j e^{z_j}}$ simplex Not really an activation — it is the last step, turning logits into the distribution over the vocabulary that §1 needs. Vector in, vector out.
Sigmoid vs. softmax A common confusion. Sigmoid maps one number to one probability, and $k$ sigmoids give $k$ independent probabilities that need not sum to 1. Softmax maps a vector to a distribution that does. Use sigmoid for "is this true?", softmax for "which one of these?". Predicting the next word is emphatically the second.

3A brief history

Handout #1 §4 asked why, if neural networks are so old, almost everything happened recently. Here is the same story at closer range — and note the shape of it: two long winters, each ended by a technical fix that had been available for years.

WhenWhatWhy it mattered
1943 McCulloch & Pitts propose a mathematical model of a neuron. Establishes that a network of simple threshold units can compute logical functions. The unit in §2.1 is recognizably theirs.
1958 Rosenblatt's perceptron — a single unit, with a learning rule that provably converges when the data is linearly separable. The first system that learned its weights from examples rather than having them set by hand. Enormous excitement followed.
1969 Minsky & Papert show a single-layer perceptron cannot learn XOR. Correct, and widely over-read. The limitation is exactly the one in §2.2's callout — one linear boundary — and it does not apply to multi-layer networks. But nobody could train those yet, and funding collapsed. First AI winter.
1986 Rumelhart, Hinton & Williams popularize backpropagation. The missing piece: an efficient way to get gradients for every layer, so depth becomes trainable. (The underlying idea — reverse-mode differentiation — predates this by years in other fields.) This is Session 4.
1989–98 LeCun's convolutional networks read handwritten digits in production. Proof that deep networks work on real problems. Yet the field stayed narrow — data and compute were not there, and support-vector machines were easier to get working. Second winter.
2003 Bengio et al.: the neural language model of §1.1. The idea that distributed representations solve sparsity, stated cleanly. Ahead of the hardware that would vindicate it.
2012 AlexNet wins ImageNet by a wide margin, trained on two GPUs. The moment the field turned. Nothing in it would have surprised a 1986 researcher conceptually; what was new was the data and the GPUs, exactly as Handout #1 §4 argued.

The pattern worth extracting: twice, the ideas were sound and the field concluded they were not, because the surrounding conditions were missing. That is a reason to be careful about what you infer from a method's current failure — and equally, a reason not to assume every currently-failing method is merely waiting for more compute.

4Background: the algebra you will actually use

Handout #1 §1.1 covered the operations. This section is about the one thing that trips everyone up in practice: shapes.

4.1  Batching, and why everything has a leading dimension

§2.2 wrote a layer as $h = \sigma(Wx + b)$ for a single input $x$. You never do that. GPUs are efficient because they do the same operation to many inputs at once, so we stack $B$ examples into a matrix $X \in \mathbb{R}^{B \times d}$ and compute

$$ H = \sigma\!\left(X W^\top + b\right), \qquad X \in \mathbb{R}^{B \times d},\; W \in \mathbb{R}^{m \times d},\; H \in \mathbb{R}^{B \times m}. $$

Note the transpose, and note that $b \in \mathbb{R}^m$ is added to every row by broadcasting. In this course activations almost always carry the shape (batch, sequence, dim): $B$ independent documents, $T$ positions each, $d$ numbers per position.

import torch
import torch.nn as nn

B, T, d_in, d_out = 32, 128, 768, 3072

x = torch.randn(B, T, d_in)          # (32, 128, 768)
layer = nn.Linear(d_in, d_out)       # holds W: (3072, 768) and b: (3072,)
h = torch.relu(layer(x))             # (32, 128, 3072)

print(layer.weight.shape, layer.bias.shape, h.shape)
# nn.Linear applies to the LAST dimension and leaves the leading ones alone,
# so the same layer works for (d_in,), (B, d_in), or (B, T, d_in).
The bug you will actually write Broadcasting does not error when it should. Handout #1 §1.5 flagged this; here is the version that will cost you an afternoon:
scores = torch.randn(32, 128)     # (batch, sequence) -- one score per position
mask   = torch.randn(128)         # (sequence,)
scores + mask                     # fine: broadcasts over batch

bad = scores + torch.randn(32)    # RuntimeError -- 128 vs 32
worse = scores + torch.randn(32, 1)   # NO ERROR. Broadcast over sequence.
                                      # Every position in a document got the
                                      # same value. Trains, silently worse.

Print shapes. Assert them if it matters: assert h.shape == (B, T, d_out).

5Background: optimization

We have a function $f_\theta$ and a loss. Training means finding $\theta$ that makes the loss small. There is no closed form — unlike the counting in Handout #2 §3, where the answer was a ratio of integers — so we search, by repeatedly taking a small step downhill.

5.1  Gradient descent

The gradient $\nabla_\theta \mathcal{L}$ points in the direction of steepest increase. So step the other way:

$$ \theta \leftarrow \theta - \eta \, \nabla_\theta \mathcal{L}(\theta) $$

That single line is the whole algorithm, and $\eta$ — the learning rate — is the most consequential number you will choose. The widget below is a 1-D loss surface with one parameter, which is enough to see everything that matters.

Learning-rate explorer Drag the learning rate, then press Run. Find the value where descent stops converging.
Work through these
  1. Set $\eta = 0.04$ and press Run 25. It converges, but barely moves. A too-small learning rate does not fail — it just costs more steps than you can afford. At the scale of a real model, "more steps" means weeks of GPU time.
  2. Raise $\eta$ toward $1.0$. Convergence gets faster, then starts overshooting and zig-zagging across the minimum while still making progress.
  3. Now cross $\eta = 2$. The loss increases every step and runs away. For this surface, $\mathcal{L} = \tfrac{1}{2}\theta^2$, the update is $\theta \leftarrow \theta(1 - \eta)$, so the distance from the minimum is multiplied by $|1 - \eta|$ each step: convergent exactly when $|1-\eta| < 1$, i.e. $0 < \eta < 2$. Divergence is not bad luck; it is arithmetic. (Try to derive this before reading it again.)
  4. Switch to Two minima. Gradient descent finds a minimum — whichever one it happens to fall into. It has no way to know a better one exists elsewhere. Real loss surfaces have enormously many, which sounds fatal and turns out not to be; why is a question the field is still arguing about.

5.2  Stochastic gradient descent

One problem remains. $\mathcal{L}$ is a sum over the whole training set, so one exact gradient step requires a pass over every token you have. At web scale that is absurd — you would get a handful of steps per week.

The fix is to estimate the gradient from a random minibatch of $B$ examples instead of all $N$:

$$ \nabla_\theta \mathcal{L} \;\approx\; \frac{1}{B}\sum_{i \in \text{batch}} \nabla_\theta \ell_i(\theta). $$

This is the same Monte Carlo move as Handout #2 §5's cross-entropy question: replace an expectation with an average over a sample. The estimate is noisy, and that is an acceptable trade — a slightly wrong direction computed a thousand times faster wins easily. The noise even helps, by shaking the optimizer out of the shallow minima §5.1 warned about.

optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

for x_batch, y_batch in dataloader:      # each pass = one minibatch
    optimizer.zero_grad()                # .grad accumulates -- clear it first
    logits = model(x_batch)              # forward
    loss = F.cross_entropy(logits, y_batch)
    loss.backward()                      # gradients into every .grad  (Session 4)
    optimizer.step()                     # theta <- theta - lr * grad

Those five lines are the training loop for every model in this course. What changes later is the model, the optimizer (SGD becomes Adam), and the scale — never the shape of the loop. The one line not yet explained is loss.backward(), which is Session 4's entire subject.

6Check yourself

Quiz #1 is next session (Thu, Sept 10) It covers everything up to that point — Handouts #1, #2 and #3 included. The questions below are for this handout only; do not treat them as the scope.

Q1. A colleague builds a 20-layer network and uses no activation function, reasoning that ReLU "throws away information." What have they actually built, and what would you tell them?

Answer
A single linear layer, with 20 layers' worth of compute and memory. Composing linear maps yields a linear map: $W_{20}\cdots W_1 x + b'$ collapses to $W'x + b'$. So the network cannot represent anything a one-layer linear model cannot, while costing twenty times as much. ReLU does discard information — that is the point. Without some nonlinearity, depth is free of benefit and not free of cost.

Q2. A fixed-window neural LM with window 4 and a trigram model both condition on a bounded context. Why is the neural one not just a slower trigram?

Answer
Because of how it stores what it learns. A trigram model keeps one independent number per context; the dog slept and the cat slept are unrelated table keys, so evidence about one says nothing about the other. The neural model represents words as vectors and computes the conditional as a function of them, so if dog and cat acquire similar vectors, a prediction learned for one context transfers to the other for free. Same Markov assumption, entirely different generalization behaviour — §1.2's table, in one sentence.

Q3. For $\mathcal{L}(\theta) = \tfrac{1}{2}\theta^2$ starting at $\theta_0 = 4$, write the value after $k$ steps of gradient descent with learning rate $\eta$. For which $\eta$ does it converge?

Answer

$\nabla \mathcal{L} = \theta$, so the update is $\theta \leftarrow \theta - \eta\theta = (1-\eta)\theta$, giving

$$\theta_k = 4\,(1-\eta)^k.$$

This tends to 0 exactly when $|1-\eta| < 1$, i.e. $0 < \eta < 2$. At $\eta = 1$ it lands on the minimum in a single step; at $\eta = 2$ it oscillates between $\pm 4$ forever; above 2 it diverges geometrically. Two things to take away: there is a hard upper bound on the usable learning rate, and it is a property of the surface (here its curvature), not of your patience.

Q4. Minibatch gradients are noisy estimates of the true gradient. Name one way that hurts and one way it helps.

Answer
Hurts: each step points in a slightly wrong direction, so the path to a minimum is longer and less direct than true gradient descent's, and near a minimum the noise prevents settling exactly. Helps: the same noise can push the optimizer out of a poor local minimum or a saddle point that exact gradient descent would sit in forever — and, far more importantly, it makes each step cheap enough that you can take millions of them. The decisive argument is throughput, not the noise's regularizing effect.

Q5. You write h = torch.relu(layer(x)) with x of shape (32, 128, 768) and layer = nn.Linear(768, 3072). What shape is h, and how many multiply-accumulates did that cost?

Answer

Shape (32, 128, 3072)nn.Linear maps the last dimension and leaves the leading ones untouched.

Cost: one $768 \to 3072$ mat-vec per position, which is $768 \times 3072$ multiply-accumulates, times $32 \times 128$ positions: $$32 \times 128 \times 768 \times 3072 \approx 9.7 \times 10^{9}.$$ Ten billion operations for one layer, one batch, forward only. This is Handout #1 §1.4's $O(B\,T\,d_{\text{in}}\,d_{\text{out}})$ with numbers in it, and it is why the compute story in Handout #1 §4 is not a footnote.

Q6. Minsky and Papert's XOR result was correct. Why did it not actually refute neural networks?

Answer
Because it is a theorem about a single-layer perceptron, whose decision boundary is one hyperplane, and XOR is not linearly separable. A two-layer network with a nonlinearity represents XOR without difficulty. The result was read as a verdict on the approach rather than on one instance of it — partly because the means to train multi-layer networks (backpropagation, §3) was not yet in general use. The transferable lesson: check whether a negative result constrains the class of models or just the member someone happened to test.

Q7. A neural LM needs no smoothing. What replaces it, and what has been given up?

Answer
Learned representations replace it. Because words and contexts are vectors, similar contexts produce similar predictions automatically, so an unseen context still gets a sensible distribution — generalization is structural rather than patched on. A softmax also cannot output an exact zero, so the catastrophic-zero problem disappears outright. What is given up is transparency and guarantees: you can no longer point at the counts that produced a probability, the model may generalize in ways you did not intend, and fitting now requires an optimization procedure that can fail. We traded an interpretable model that could not generalize for a generalizing model we cannot interpret.

7Optional further reading

Strictly optional — nothing here is assumed in class or on a quiz.