Code

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 y gives a True/False tensor. Its mean is the share of correct ones, but a bool is not a number: convert it to floating point for mean to 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 HOLE places 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 true in the forward test — you returned neuron(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 of dim=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) with y, not its index. A probability never equals a label.