Section 06

The Code

First Learning Machine The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain 1958

The Code

Build a Perceptron from scratch in Python

This code implements the complete Perceptron — forward pass + learning rule — in under 25 lines, using only NumPy. No machine learning libraries. No magic. Every line is exactly what the mathematics in Section 5 described.

We train it on the OR gate and watch the weights update in real time.

# What this code does: Implements the Perceptron learning rule from scratch
# Paper: The Perceptron — Frank Rosenblatt (1958)
# Run free at: https://colab.research.google.com/

import numpy as np

# --- Training data: the OR gate ---
# Each row is one training example [input1, input2]
X = np.array([[0, 0],
              [0, 1],
              [1, 0],
              [1, 1]])
y = np.array([0, 1, 1, 1])  # correct answers (OR gate: 1 if any input is 1)

# --- Initialise weights and settings ---
np.random.seed(42)
weights = np.zeros(2)   # start both weights at 0
threshold = 0.5         # fire if weighted sum >= 0.5
learning_rate = 0.1     # how much to adjust weights on each mistake
epochs = 10             # how many times to cycle through all training examples

# --- The Perceptron: forward pass ---
def predict(x, weights, threshold):
    weighted_sum = np.dot(weights, x)  # dot product: w1*x1 + w2*x2
    return 1 if weighted_sum >= threshold else 0   # apply threshold

# --- Training loop ---
print(f"{'Epoch':>5} {'Example':>8} {'Prediction':>11} {'Correct':>8} {'Error':>6} {'w1':>8} {'w2':>8}")
print("-" * 60)

for epoch in range(epochs):
    errors_this_epoch = 0

    for i in range(len(X)):
        prediction = predict(X[i], weights, threshold)   # make a guess
        error = y[i] - prediction                         # how wrong were we?

        if error != 0:                                    # only update on mistakes
            weights += learning_rate * error * X[i]      # the Perceptron learning rule
            errors_this_epoch += 1

        print(f"{epoch+1:>5} {i+1:>8} {prediction:>11} {y[i]:>8} {error:>+6.0f} {weights[0]:>8.3f} {weights[1]:>8.3f}")

    if errors_this_epoch == 0:
        print(f"\nConverged after epoch {epoch+1}! All predictions correct.")
        break

# --- Test the trained Perceptron ---
print("\nFinal weights:", weights)
print("\nTesting trained Perceptron on OR gate:")
for i in range(len(X)):
    pred = predict(X[i], weights, threshold)
    print(f"  Input {X[i]} → Predicted: {pred}, Correct: {y[i]}  {'✓' if pred == y[i] else '✗'}")

What you should see when you run this:

A table showing each training example, the prediction made, the error, and the updated weights. You will see the weights start at 0 and gradually grow as the Perceptron learns. After a few epochs, the error column will be all zeros — the Perceptron has learned the OR gate perfectly.


What to change to experiment:

  1. Try the AND gate: Change y = np.array([0, 0, 0, 1]) and run again. The Perceptron still converges — both AND and OR are linearly separable.

  2. Try the XOR gate: Change y = np.array([0, 1, 1, 0]) and run again. Watch the Perceptron fail to converge — it will keep making mistakes no matter how many epochs you run. This is the famous XOR problem, and it is what ended the first era of neural network research. (We cover this fully in Limitations →)

  3. Change the learning rate: Try learning_rate = 0.5 and then learning_rate = 0.01. A high learning rate converges faster but can overshoot. A low learning rate is more stable but slower. Watch the difference in the weight updates.