forward and accuracy — write them yourself
neuron and softmax work. For the two remaining functions there are no holes this time — only the skeleton.
Both are simple, and both put together what you already have.
forward
forward(x, W, b):
scores ← neuron(x, W, b) # [n, 784] @ [784, 10] + [10] → [n, 10]
return softmax(scores) # [n, 10], every row adds up to 1
One line — and that is exactly the whole "model". Pictures go in, probabilities come out.
accuracy
For every picture the model gives ten probabilities. Its answer is the class with the highest probability. Accuracy is the share of answers that match the label.
accuracy(probs, y):
answer ← the index of each row's largest probability # [n]
correct ← the number of places where answer == y
return correct / n (as a Python float)
Two things worth thinking about:
- the index of the largest value (
argmax), not the value itself — a class is a number, not a probability; - comparing with
ygives aTrue/Falsetensor. Its mean is the share of correct ones, but a bool is not a number: convert it to floating point formeanto work. And the result must be a plain Python number —.item().
Your job
neuron.py (right panel) has grown: two new skeletons at the bottom, forward and accuracy, with raise NotImplementedError. Above, your neuron, sigmoid, softmax.
The panel shows the skeleton: the
HOLEplaces are empty in it, in your copy they are filled in.
test_neuron.py grew too. If you run it before writing anything (with the holes filled in):
$ python -m unittest
EEEEE........
ERROR: test_all_right_and_all_wrong (...)
NotImplementedError
ERROR: test_half_right (...)
NotImplementedError
ERROR: test_returns_a_plain_float (...)
NotImplementedError
ERROR: test_forward_gives_probabilities_per_image (...)
NotImplementedError
ERROR: test_forward_picks_the_class_with_the_big_weight (...)
NotImplementedError
----------------------------------------------------------------------
Ran 13 tests in 0.010s
FAILED (errors=5)
Eight dots are the earlier tests, still passing.
When it does not pass
False is not truein theforwardtest — you returnedneuron(x, W, b)without the softmax. The shapes are right, but the rows do not add up to 1.tensor(1.) is not an instance of <class 'float'>— you forgot.item(). A tensor holding one number looks like a number, but is not one.The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 0—argmax(dim=0)instead ofdim=1. You got "which picture is best for this class" (3 numbers, one per class), not "which class for this picture" (4 numbers).0.0 != 0.5— you compare the largest probability (e.g.0.8) withy, not its index. A probability never equals a label.