The artificial neuron
22 min read
A vector can't decide anything on its own. Eight lessons of tokenising, counting and fitting have turned text into coordinates, which settles the input side, but something is still missing: the object that actually reads those coordinates and makes a decision. So far you only know its type (, set out back in the lesson on the problem of representing language and left at that), and a type by itself computes nothing. This lesson builds the unit is made of, and it turns out that a single one is already enough to decide.
Here's a concrete case. Ten one-line movie reviews and a vocabulary of eight entries; each review becomes its bag of words, the vector that counts how many times each entry appears, exactly as in the lesson on the bag of words. So good movie i recommend it and bad movie very slow are two points in , and for each one you want the same thing: does the review speak well of the movie, or badly? Only two possible answers.
Each of those ten reviews is an example: a vector going in, paired with the answer you want out. That answer is its label, a number that's if the review is positive and if it's negative. A person set all ten labels by reading the reviews alone; they don't come from any calculation, and without them there would be no way to say an answer is wrong. Between the input and the answer, for now, there is nothing at all.
The simplest thing you could put in between is a vote. Each coordinate of the review's vector counts for or against the verdict depending on its value, and how strongly it counts is fixed by a number attached to that coordinate. Add up every contribution and out comes a single number, which then gets compared against a threshold: above it, one answer; below it, the other. And that's the whole object. There is nothing more to it.
That sum has a geometric picture worth seeing before writing anything down. With two coordinates per point, the most a drawing can show, the set of points where the sum exactly equals the threshold is a line, and what the object does is check which side of that line you landed on.
The line moves on its own because the explorable corrects its numbers every time a point lands on the wrong side; where those numbers actually come from is the business of much of this block, and for now you only need to watch it arrive. Once the two groups are separated, it arrives and stops. Notice how many different lines would work: if there's slack between the groups, a whole range of positions make zero errors, and the explorable keeps the first one it finds. Now drag a green point across into the other group: the notice below changes the instant no line can handle the split any more.
What a neuron computes
Start with the input: a vector , a column, like every vector in this course. A neuron is made of two things: a vector of weights , one per coordinate of the input, and a scalar called the bias. Together they compute a number,
the pre-activation, and the neuron feeds it through an activation function to get
which is what the neuron actually returns. Both and are scalars: no matter what vector a neuron looks at, it always returns a single number. The type set out at the start of the course called for output numbers, and one neuron is enough to decide between two answers; the other come from adding more neurons alongside it, each with its own weights, and that's where this block heads next.
is still up for grabs, and for now I'll fix it by decree, using the oldest choice of all, the step:
With that, the neuron returns a or a and nothing in between. A neuron built around a step has had its own name since 1958, the perceptron, and it's the one that gives this block its title. There are other candidates for , and the choice matters, as you'll see shortly; the step is used here because it keeps the geometry in plain view.
It's worth reading carefully when the input is a bag of words, because then each coordinate of counts occurrences of a vocabulary entry, and each weight is the neuron's opinion of that entry: one number, positive or negative, nothing more. Because is a sum, those opinions stack up without interfering with each other (two occurrences of good contribute exactly twice what one does), and word order plays no part in any of it, since it was already thrown away by the representation. What the neuron adds on top of the bag of words is the verdict; whatever the bag had already lost stays lost.
The bias isn't anyone's opinion of a word. It's what the neuron thinks before it's read anything at all. It sets where the threshold falls, since comparing against zero is the same as comparing the sum of the opinions against . And in the picture, it's what frees the line from having to pass through the origin.
The word neuron is borrowed from biology, and it's best not to stretch the metaphor too far. A nerve cell integrates signals and fires once they cross a certain threshold, and that's where the resemblance ends. What you've read is a weighted sum followed by a comparison, and that's the whole of what the name is defending.
The boundary that separates, and how far from it you fall
doesn't actually look at , only at its sign. So everything the neuron can tell apart comes down to the set of points where changes sign, its decision boundary:
With and , solving that equation gives
which is exactly the line in the explorable above, as long as ; if it's zero, the line is vertical, and the original equation describes it equally well. In the same set is a plane, and in it's a hyperplane: an object of dimension that splits the space into two halves. For the reviews below, ; with a real vocabulary it would be tens of thousands. You can't draw the hyperplane at that point, but it's the same object all the same.
The weights don't only place that boundary, they're perpendicular to it. Take any two points and that lie on it. Both make the equation equal zero, so subtracting one from the other cancels the bias and leaves
where is any direction lying within the boundary. Its dot product with is always zero, which means points perpendicular to the boundary, towards the side where is positive.
The bias is what shifts it. With , the zero vector satisfies the equation, so the boundary is forced through the origin and can't pass anywhere else; the moment , it moves away. Without a bias, the answer depends only on the direction of ; with one, it also depends on where actually is.
What's still missing is what makes worth more than its sign alone. The signed distance from any point to the boundary, positive on one side and negative on the other, is
which means is that distance, scaled by . Its magnitude tells you how much margin the decision had, and the step keeps only the sign, throwing the rest away.
The signed distance, step by step
Let be any point and the closest point to it on the boundary. The segment joining them is perpendicular to the boundary, and we already know the perpendicular direction: it's that of . So write
where has length , so is exactly the signed distance we're after. Multiply both sides by and add :
The first term on the right is zero, since being on the boundary is exactly what makes it zero. In the second, by definition of the norm, so that term reduces to . The left side is , so and
A neuron that scores reviews in NumPy
The cell builds the whole case from scratch: ten reviews, eight vocabulary entries, the bag-of-words vector for each, and a neuron on top. I've set the weights by hand ( for entries that count in favour, for those that count against, for the ones with no opinion), since this lesson doesn't yet give you a way to choose them. Run it and pay attention to three things: the column of values, what happens when you multiply the weights by ten, and what happens when you nudge the bias down by half a point.
# --- Ten one-line reviews, with what a person would say about each.
reviews = [
("the movie is fun and i recommend it", 1),
("the movie is slow and boring", 0),
("good movie i recommend it", 1),
("bad movie very slow", 0),
("fun and good", 1),
("the movie is bad", 0),
("boring and slow", 0),
("i recommend it", 1),
("good movie but slow", 0),
("fun and i recommend it", 1),
]
# Eight entries. Anything not in the vocabulary never reaches the vector.
V = ["bad", "boring", "fun", "good", "movie", "recommend", "slow", "the"]
pos = {e: i for i, e in enumerate(V)}
X = np.zeros((len(reviews), len(V)))
for f, (text, _) in enumerate(reviews):
for token in text.split():
if token in pos:
X[f, pos[token]] += 1.0
y = np.array([label for _, label in reviews])
print("X has shape", X.shape, "with one row per review and", len(V), "columns")
print(" ", " ".join(e.rjust(10) for e in V))
print("x1: ", " ".join(str(int(v)).rjust(10) for v in X[0]))
print()
# I set the weights by hand: +1 counts in favour, -1 counts against, 0 no opinion.
w = np.array([-1.0, -1.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0])
b = 0.0
print("w: ", " ".join(("%+d" % v).rjust(10) for v in w), " b =", b)
print()
def decide(X, w, b):
z = X @ w + b
return z, (z >= 0).astype(int) # step: 1 if z >= 0, else 0
z, a = decide(X, w, b)
print("review".ljust(37), "z".rjust(5), " decision".ljust(12), "label")
for f, (text, label) in enumerate(reviews):
print(text.ljust(37), ("%.1f" % z[f]).rjust(5),
(" positive" if a[f] else " negative").ljust(12),
"positive" if label else "negative")
print()
print("correct:", int((a == y).sum()), "of", len(y))
print()
# 1. Scaling (w, b) by ten scales every z and moves not a single decision.
z10, a10 = decide(X, 10 * w, 10 * b)
print("with (10w, 10b) z =", np.round(z10, 1))
print(" same decisions:", bool(np.array_equal(a, a10)))
print()
# 2. The bias slides the boundary: the review that sat right on it flips sides.
z05, a05 = decide(X, w, -0.5)
changed = [reviews[f][0] for f in np.nonzero(a != a05)[0]]
print("with b = -0.5 flips sides:", changed)
print(" correct:", int((a05 == y).sum()), "of", len(y))
print()
# 3. How far from the boundary each review falls: z over the norm of w.
norm = float(np.linalg.norm(w))
print("norm of w =", round(norm, 3))
for f in [0, 5, 8]:
print(" ", reviews[f][0].ljust(37), "distance", round(float(z[f]) / norm, 3))
The first run downloads the Python interpreter (~15 MB). After that it stays in the browser cache and is reused across every lesson.
Nine out of ten correct, and the one it misses is exactly the one you'd expect. good movie but slow adds for good and for slow, so its comes out to exactly , right on the boundary. The step breaks the tie upward and sends it to the positive side, but the label says negative.
The next two experiments are really the point of the lesson. Multiplying and by ten multiplies every pre-activation by ten too ( becomes , becomes ), but it doesn't change a single decision: the boundary is the set where is zero, and which points are zero doesn't depend on the scale. Moving the bias to , on the other hand, slides the boundary half a point: the review sitting right on it falls to the other side, and the score climbs to ten out of ten.
The last few lines print the distance. With , the first review lands from the boundary, while the movie is bad sits at : half as far, on the other side. That difference is right there in , but none of it makes it through to .
Test your intuition
Three questions: what a pre-activation is actually worth, what gets lost when you remove the bias, and what holds true about the boundary.
A neuron with weights and bias receives the input . What is its pre-activation ?
A margin of ±0.01 is accepted.
What does a neuron lose if you take away its bias, that is, if you fix ?
About the decision boundary of a neuron with a step, tick everything that is true.
Select every correct option. This is graded all-or-nothing: there is no partial credit.
Two things are still left open, and they're not equally urgent. I wrote those eight weights above by eyeballing the reviews myself, and that trick won't work with a vocabulary of fifty thousand entries: getting a neuron to find its own weights from examples is what takes up most of the rest of this block. The other loose end is closer at hand. The geometry gave the magnitude of real meaning (the distance to the boundary, scaled by ), and the step throws all of that away: it hands out the same to a review that falls at and to one that barely grazes the boundary.
was fixed by decree, and there are plenty of other functions to choose from. Some preserve that distance instead of crushing it; others change, at the root, what becomes computable once you start stacking neurons together. Which function to assign to , and what each choice gains and loses, is the subject of the next lesson, on activation functions and non-linearity.