The model as an nn.Module — write it yourself
The training loop works with any nn.Module. Now you write your own model and
the function that wires everything together. This time with no gaps: empty
skeletons.
fitin the panel still showspasswhere your two lines are — the panel shows the skeleton, not your file. In your copy they are already filled in; leave them.
nn.Module — how it is written
A model is a class that inherits from nn.Module and has two methods:
class Something(nn.Module):
def __init__(self, ...):
super().__init__() # first — always
self.layer = nn.Linear(...) # layers live as attributes
def forward(self, x):
return ... # what the model does with its input
Three rules worth knowing before you write:
super().__init__()is the first line. Without it Python raisesAttributeError: cannot assign module before Module.__init__() call.- Assign the layer to
self.something = .... Only then does it show up inmodel.parameters()— and so in the optimizer. A layer that lives only in a local variable will not be trained. forwardmustreturn. Without it the model returnsNoneand the loss complains:argument 'input' (position 1) must be Tensor, not NoneType.
You call a model like a function: model(x) calls forward(x) inside.
Why the model does not return probabilities
In lesson 4 forward ended with softmax. Here it does not. The model returns
raw scores (logits) and nn.CrossEntropyLoss applies softmax itself, inside. If
you applied softmax twice there would be no error — just somewhat worse learning. You
will see the numbers in the next step, "When the loop lies".
Your job
1. model.py (a new file) — the class LinearClassifier. The contract is in
the comments. It must be the same 10 neurons from lesson 4, now as one object:
scores = x @ W + b.
in_featurespixels in,num_classesscores out;- one
nn.Linearinside — the default model owns exactly 7 850 numbers; forwardreturns raw scores.
2. train.py has grown: import lines and main() — an empty skeleton. Its
docstring spells out exactly what to do and in what order (seed 42, 10 000 images,
batch 64, 10 epochs, lr=0.1).
main has no unit test — its "test" is the next step: you run it and see whether
you get what lesson 4 led you to expect.
3. test_train.py has grown: a TestLinearClassifier class. It checks the
shape [N, 784] → [N, 10], 7 850 numbers, that it is an nn.Module, that raw
scores come back (not probabilities), other sizes (LinearClassifier(2, 3)), and
that fit trains this model.
Run python -m unittest. While you write, the test tells you what is wrong — the same
kind of messages as in the previous step. Until the model is written you will see
NotImplementedError.