Foundations — Building models with nn.Module
Before you can read the parent note Building models with nn.Module, you must own every symbol it throws at you. Below, each symbol is built from nothing: plain words → the picture → why the topic needs it. Read top to bottom; each item leans on the one above it.
1. A number, a vector, a matrix — the raw material
Everything a network touches is a grid of numbers. We need three names for three shapes of grid.
Why the topic needs this: The parent note writes torch.randn(32, 784) — that is a matrix with 32 rows and 784 columns. A network's job is to turn one grid of numbers into another grid of numbers, so we must be fluent in reading grid shapes.
2. The @ symbol — matrix multiplication
The parent's naive layer is x @ w + b. The @ is not "email at" — it means matrix multiply.
Suppose one input row is and the weight grid is Then
Why the topic needs this: A nn.Linear layer is the operation . Everything else — ReLU, residual blocks — is decoration around this core.
3. The + b bias — a shiftable floor
Why the topic needs this: Without a bias, every layer is forced to pass through zero when the input is zero. Bias lets the network say "even when nothing comes in, output should be ." In the parent, nn.Linear(in, out) secretly carries a bias of size out — that is where the "+128" and "+1" in the parameter count come from.
4. The activation — bending a straight line
If we only ever did , stacking layers would collapse into one big multiply (a straight line composed with a straight line is still a straight line). We need a bend.
Why the topic needs this: The parent stores self.relu = nn.ReLU() and calls self.relu(self.fc1(x)). ReLU is stateless (no dials to learn) but still lives inside the module for a consistent pattern.
5. The function-stack notation
The parent opens with this. Read it inside-out.
Why the topic needs this: A network's forward() method is literally this line spelled out:
x = self.layer1(x) # f1
x = self.activation(x) # bend
x = self.layer2(x) # f2Understanding "output of one becomes input of next" is the entire mental model of forward.
6. Parameters vs. inputs — the two kinds of numbers
This is the distinction that motivates nn.Module existing at all.
Why the topic needs this: In the naive function my_layer(x, w, b) you must hand-carry w and b everywhere. nn.Parameter lets the module hold onto its own weights so you never pass them by hand — and so PyTorch can auto-collect them via .parameters().
7. The gradient — the "which way to nudge" arrow
The residual-block section is full of . Here is what it means with zero calculus background.
Why the topic needs this: The parent's residual argument says the skip connection adds a guaranteed "" to the slope, so the downhill signal never fades to zero in deep networks. You don't need to compute this — you need to read it as "the keeps the training signal alive."
8. The parameter-count arithmetic
The parent asserts 117121 parameters. Now every symbol above lets you verify it.
How the foundations feed the topic
Equipment checklist
Test yourself — say the answer out loud before revealing.
What shape does torch.randn(32, 784) describe?
What does the @ symbol do in x @ w?
For x @ W to work, which numbers must match?
x must equal the rows of W (the inner numbers).What does the bias b do after the weighted sum?
In words, what is ReLU(z)?
z if positive, otherwise output 0 — a flat floor plus a 45° ramp.Why do we need ReLU between linear layers?
What is the difference between an input and a parameter?
How do you compute the parameter count of nn.Linear(in, out)?
in*out + out (weight matrix plus bias vector).What does ∂L/∂x mean in plain words?
x slightly — the slope of the loss hill.Why does a skip connection add a +1 to the gradient?
x through unchanged, so its slope is 1, keeping the training signal from vanishing.