Neural Networks Explained
Neural Networks: Many Neurons, One Big Function
Like my other notes, this is my own understanding written in plain words. For the full picture, take a proper deep learning course. Think of this as a friendly map, not the textbook.
Series: Neurons, Weights and Bias Explained → Neural Networks (this note) → Activation Functions and GELU → Transformers Explained → Multi-Head Attention Explained.
In the last note we saw that one neuron can only draw a straight line. Real problems (faces, speech, language) are not separated by straight lines. The fix is beautifully simple: use lots of neurons, in layers.
Layers
A neural network is neurons arranged in columns called layers:
- Input layer: just holds your numbers (pixels, word vectors...).
- Hidden layers: neurons that find useful patterns. "Hidden" only means we don't directly see them.
- Output layer: the answer (a class, a number, the next word).
In a fully connected layer, every neuron takes input from every neuron in the previous layer.
This little network has 3 inputs, 4 hidden neurons and 2 outputs. Count the dials: the first layer has
The forward pass: it is just matrix multiplication
Here is the part that connects to Matrix Multiplication Explained. All the neurons in a layer do their weighted sum at the same time. Stack the weights of each neuron into a row, and the entire layer becomes one matrix multiplication:
Look at the shapes in the picture.
import numpy as np
def forward(x, W1, b1, W2, b2):
h = np.maximum(0, W1 @ x + b1) # layer 1: multiply, add, bend (ReLU)
return W2 @ h + b2 # layer 2: multiply, add
W1, b1 = np.random.randn(4, 3), np.zeros(4)
W2, b2 = np.random.randn(2, 4), np.zeros(2)
print(forward(np.array([1.0, 0.5, -1.0]), W1, b1, W2, b2))
And if you feed a whole batch of 1000 examples, the vectors become a
Why the bend matters
Look at the middle of each layer: the little f. That is the activation function, and it is not optional.
Without it, two layers give
The universal approximation theorem (Cybenko 1989, Hornik 1991) says a network with even one hidden layer, if wide enough, can approximate any reasonable continuous function. "Can" is doing a lot of work: it says the network exists, not that training will find it easily. Deeper networks tend to get there with far fewer neurons.
How a network learns
At the start, the weights are random, so the output is garbage. Learning is a loop of four steps:
- Forward pass: run the input through and get a guess.
- Loss: compare the guess to the right answer, and turn "how wrong" into a single number. For predicting numbers, mean squared error is common. For classes, cross-entropy is.
- Backward pass (backpropagation): use the chain rule from calculus to work out how much each weight contributed to the error. This is the blame step. It was popularized by Rumelhart, Hinton and Williams in 1986.
- Update: nudge every weight a little in the direction that shrinks the loss:
The
In practice you don't use all the data for each nudge. You use small random batches, and one pass over all the data is an epoch.
A complete tiny example
XOR is the classic problem one neuron cannot solve (no straight line separates it), but a tiny network can:
import torch, torch.nn as nn
X = torch.tensor([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])
y = torch.tensor([[0.], [1.], [1.], [0.]])
model = nn.Sequential(nn.Linear(2, 4), nn.Tanh(), nn.Linear(4, 1), nn.Sigmoid())
opt = torch.optim.Adam(model.parameters(), lr=0.05)
loss_fn = nn.BCELoss()
for epoch in range(500):
opt.zero_grad()
loss = loss_fn(model(X), y) # forward + loss
loss.backward() # backpropagation
opt.step() # update the weights
print(model(X).round()) # usually [[0],[1],[1],[0]]
Random starting weights mean this occasionally gets stuck. If it prints the wrong answer, run it again. That randomness is a real feature of training, not a bug in the code.
Things that go wrong
- Overfitting: the network memorizes the training examples instead of learning the pattern, and fails on new data. Fixes: more data, dropout, weight decay, stopping early.
- Vanishing gradients: in deep stacks, the blame signal can shrink to nothing on its way back, so early layers stop learning. This is a big reason activation functions and residual connections matter.
- Bad learning rate: loss goes to NaN (too large) or barely moves (too small).
The big picture
A neural network is layers of weighted sums with bends in between: one giant function with millions of adjustable numbers. Running it is matrix multiplication. Training it is repeating guess, measure, blame, nudge until the guesses get good.
Try it yourself
Next: Activation Functions and GELU
Related: Neurons, Weights and Bias Explained, Matrix Multiplication Explained, State Machines Explained