AI Engineering Learning Hub

Neural Networks & Backpropagation

Neural networks and backpropagation from scratch: how layers of simple neurons learn non-linear patterns like XOR, with runnable numpy code.

What it is

A single neuron computes sigmoid(weight * input + bias), which is exactly logistic regression. A neural network wires many of these neurons into layers: an input layer that holds the features, one or more hidden layers that transform them, and an output layer that produces the prediction. Each neuron in a layer connects to every neuron in the next, and every connection has its own weight.

The power comes from stacking. One neuron can only draw a straight boundary. A hidden layer lets the network bend that boundary, so it can solve problems like XOR where no single line separates the classes. Deeper networks compose simple curves into very complex functions, which is what image recognition and language models rely on.

Backpropagation is the algorithm that trains it. It takes the error at the output and pushes it backwards through the layers, using the chain rule, so each weight learns how much it contributed to the mistake.

Why it's needed

Most real problems are not linear. Pixel values do not add up to 'cat', and the meaning of a sentence is not a weighted sum of its words. Neural networks are the general tool for learning those relationships from data, and every modern deep learning system, including large language models, is built from the same forward-pass, loss, backward-pass loop.

Understanding backprop by hand also demystifies the frameworks. When PyTorch shows a vanishing gradient or a loss that explodes, you know which part of this loop went wrong.

How it works

  • Forward pass: hidden = sigmoid(X.dot(W1) + b1), output = sigmoid(hidden.dot(W2) + b2). Data flows layer by layer to a prediction.
  • Loss: compare the output with the target, for example mean squared error or cross-entropy.
  • Backward pass: compute the output error, multiply by the sigmoid derivative to get the gradient at the output layer, then send it back through W2 to get the hidden layer's gradient.
  • Update: every weight moves a small step against its gradient, scaled by the learning rate. Repeat for thousands of epochs.
  • Initialise weights randomly, never all zero, so each hidden neuron starts different and can learn a different feature.
  • Activation functions provide the non-linearity. Without them, stacked layers collapse into one big linear model.

Code example

import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

# XOR: no single straight line separates these two classes
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

rng = np.random.default_rng(42)
W1, b1 = rng.normal(size=(2, 4)), np.zeros((1, 4))   # 2 inputs -> 4 hidden neurons
W2, b2 = rng.normal(size=(4, 1)), np.zeros((1, 1))   # 4 hidden -> 1 output
learning_rate = 0.5

for epoch in range(10000):
    # Forward pass
    hidden = sigmoid(X.dot(W1) + b1)
    output = sigmoid(hidden.dot(W2) + b2)
    # Backward pass: output error, then push it back through W2
    d_output = (output - y) * output * (1 - output)
    d_hidden = d_output.dot(W2.T) * hidden * (1 - hidden)
    # Update every weight against its gradient
    W2 -= learning_rate * hidden.T.dot(d_output)
    b2 -= learning_rate * d_output.sum(axis=0)
    W1 -= learning_rate * X.T.dot(d_hidden)
    b1 -= learning_rate * d_hidden.sum(axis=0)

print("XOR predictions:", output.round(2).ravel())   # close to [0, 1, 1, 0]

Use cases

  • Image and speech recognition
  • Any problem with complex, non-linear relationships, XOR being the textbook example
  • Tabular problems where feature interactions matter and simpler models plateau
  • The foundation architecture behind deep learning and large language models

Common mistakes

  • Initialising all weights to zero, so every hidden neuron computes the same thing forever.
  • Stacking layers with no activation function and wondering why the network cannot learn XOR.
  • Using sigmoid in deep networks, where its tiny derivative makes gradients vanish; ReLU is the usual fix.
  • A learning rate that is too high, which makes the loss bounce around or blow up to NaN.
  • Not scaling inputs, so large raw values saturate the sigmoid and gradients drop to zero.

Interview questions

What does backpropagation actually do?
It computes how much each weight contributed to the final error, layer by layer from the output backwards, using the chain rule. The output layer's gradient is found first, then it is multiplied through the next layer's weights to get the hidden layer's gradient, and so on. Gradient descent then uses those numbers to update every weight. That is why it is called back-propagation.
Why do neural network weights start random instead of zero?
If every weight started at zero, every hidden neuron would receive the same gradient and learn exactly the same thing, which is called the symmetry problem. The network would behave like a single neuron no matter how wide it was. Random initialisation breaks the tie so each neuron can learn a different feature.
Why does a neural network need an activation function?
Without one, each layer is a matrix multiplication, and a chain of matrix multiplications is still one matrix multiplication. The whole network collapses to linear regression. Sigmoid, tanh or ReLU add the bend that lets the network represent curves and interactions.
What is the vanishing gradient problem?
The sigmoid derivative is at most 0.25, so each layer you backpropagate through multiplies the gradient by a number below 0.25. After several layers the gradient is close to zero and the early layers stop learning. ReLU activations, careful initialisation, batch normalisation and residual connections are the standard fixes.
What is the difference between an epoch, a batch and an iteration?
An epoch is one full pass over the training data. A batch is the subset of rows used for one gradient update, and an iteration is one such update. With 1,000 rows and a batch size of 100, one epoch is 10 iterations.
How is a neural network different from logistic regression?
Logistic regression is a single neuron, so it can only learn a linear decision boundary. A neural network adds hidden layers between input and output, and those layers learn intermediate features, which lets the boundary bend. XOR is the smallest problem that shows the difference: logistic regression cannot solve it, a network with one hidden layer can.
What does the learning rate do in backprop?
It scales each weight update. Too small and training takes forever; too large and the loss oscillates or diverges. For small networks I start somewhere between 0.01 and 0.5 and let a scheduler reduce it as training progresses.
Ask the AI assistant about this topic

Get new topics by email

One short, practical AI-engineering lesson whenever a new topic is published. No spam, unsubscribe any time.

Need this built for your product?

I build production RAG pipelines, LLM automations and voice agents. Open to freelance projects and full-time roles.