28th JANUARY, 2026
Table of Contents:
Lately I've been looking for a simple intro to machine learning. Something that would involve the fundamental computation but skip all the jargon that often confuses beginners. What you see below is a single neuron neural networkA neural network is a computing system inspired by how the brain works. It consists of layers of connected "neurons" (simple math units) that process information. that can classify these Tetris shapes. The network learns the patterns and can "guess" which one it's looking at thanks to the weightsWeights are numbers that determine how important each input is to the final decision. that were tuned during training.
We'll use these images to train the network. However, we can't work with images directly. We need numbers. Fortunately that's easy. We can describe each as a binary array:
Now the network needs answers. We don't want to upload the picture and get answer yes/no. We want to upload the picture and get the probability of what that shape could be. Let's have the answer to be between 0 and 1. We’ll refer to these as labelsLabels are the correct answers you give the network during training.. So we have input - our shapes, and labels - one for each shape.
Three more things we need before training.
Weights: These are the values we will be adjusting and tweaking during the training. We start with completely random numbers. The weights you see defined below mean nothing, completely random. We just need something to get started. We will adjust these numbers many times during training and eventually the network will find "learn" combination that can describe these shapes. That final combination becomes our model.
So I said we will be adjusting weights. But by how much? That's exactly what Learning Rate is. After each prediction, we get a number, check it agains our labels and draw conclusion. If it's off it needs to adjust its weights - the learning rate controls the size of that adjustment. And then recalculate everything with these new, adjusted weights.
How many times will it recalculate? That what epochs specifies. We use 1000 training rounds. Each round processes all five shapes. By the end, it'll have learned the patterns.
Each epoch follows the same pattern. During Epoch, we process all five shapes, one at a time. So we process one shape, get tweaked weights, then we use those weights for the next shape etc. Once we've processed all five shapes, that's one epoch complete.
You will be surprised how simple the math is. First step: we take each pixel from our input and multiply it with its corresponding weight. We do that for all 9 pixels and sum them together:
What about bias? Bias is an extra adjustable value that shifts the output. Normally you would add it to your weighted sum. Our example works without it (bias = 0), but many problems need it.
Now we use the weighted sum and run it through an activation functionAn activation function is a mathematical operation applied to each neuron's output in a neural network that determines whether and how strongly that neuron should "fire" or pass information forward. It introduces non-linearity into the network, enabling it to learn complex patterns rather than just linear relationships between inputs and outputs. which is just a fancy name for a function that clamps the result into a predictable range of numbers that are not linear. For now it's just important to remember there are many functions that can do that. We are using sigmoidThe sigmoid function (also known as the logistic function) takes any real number and outputs a value between 0 and 1. in this example.
Then we calculate error. We take the label of the shape we're currently processing and subtract the prediction. This tells us how far off we were.
Based on that error, we calculate the adjustment.
Lastly we add adjustment to weights.
All steps visualised:
We will code everything in Python and won't use any external libraries. However just as an intro here are a few most commonly used in machine learning. PyTorch, TensorFlow, Pandas and Matplotlib
import math
STRAIGHT = [0, 0, 0, 1, 1, 1, 0, 0, 0]
SQUARE = [0, 0, 0, 0, 1, 1, 0, 1, 1]
T_SHAPE = [0, 0, 0, 1, 1, 1, 0, 1, 0]
L_SHAPE = [1, 0, 0, 1, 0, 0, 1, 1, 0]
SKEW = [0, 0, 0, 0, 1, 1, 1, 1, 0]
LABELS = [0, 0.25, 0.5, 0.75, 1]
DATASET = [STRAIGHT, SQUARE, T_SHAPE, L_SHAPE, SKEW]
H = 0.1
W_SEED = [0.08, 0.11, -0.18, 0.17, 0.09, 0.01, -0.12, 0.15, 0.04]
EPOCHS = 1000
def sigmoid(x):
return 1 / (1 + math.exp(-x))
def train_step(data, label, w):
weighted_sum = sum(data[i] * w[i] for i in range(len(data)))
prediction = sigmoid(weighted_sum)
error = label - prediction
adjustments = [H * error * data[i] for i in range(len(w))]
weights = [w[i] + adjustments[i] for i in range(len(w))]
return weights
def main():
w = W_SEED[:]
for epoch in range(1, EPOCHS + 1):
for i in range(len(DATASET)):
w = train_step(DATASET[i], LABELS[i], w)
print("TRAINING COMPLETE!")
print(f"FINAL WEIGHTS: {w}")
if __name__ == "__main__":
main()
Running the above code outputs the final weights:
Now the inference code. We will use a library called pillow to convert *.png file into an array of pixels. So if you don't have it, simply run "pip install pillow"
import math
from PIL import Image
WEIGHTS = [-1.936, 0.11, -0.18, -2.794, -0.517, -0.597, 2.021, 3.842, -3.776]
SHAPES = [
(0.125, "straight"),
(0.375, "square"),
(0.625, "t_shape"),
(0.875, "l_shape"),
]
def sigmoid(x):
return 1 / (1 + math.exp(-x))
def image_to_pixels(image_path):
img = Image.open(image_path).convert('L')
return [1 if pixel > 128 else 0 for pixel in img.getdata()]
def predict(pixels, weights):
weighted_sum = sum(p * w for p, w in zip(pixels, weights))
return sigmoid(weighted_sum)
def classify(value):
for threshold, name in SHAPES:
if value < threshold:
return name
return "skew"
def main():
image_path = input("Drag your image here: ").strip().strip('"').strip(''')
pixels = image_to_pixels(image_path)
guess = predict(pixels, WEIGHTS)
shape = classify(guess)
print(f"Prediction: {guess:.4f}")
print(f"Shape: {shape}")
if __name__ == "__main__":
main()
Now when you drag and drop an image from our training set, you should get the correct prediction. That means the shape patterns were successfully encoded into weights.
We’re testing on training data. The network has memorised these specific shapes, not learned to generalise. Proper evaluation needs unseen test data.
Single-layer architecture. This can only learn simple, linearly separable patterns. Complex problems need hidden layers.
Tiny dataset. Five shapes isn't enough for real generalisation. Real ML uses thousands or millions of examples.