Handwritten Digit Classifier

Deepak Nalla

A perceptron trained from scratch in Python to recognize the digit 8 in ASCII art images — with zero external ML libraries.

Python 3.11 NumPy 2.x pandas 3.x 86 positive samples 129 negative samples
600
features
15
epochs
0
misclassifications
100%
test accuracy

Three-Script Pipeline

The project is three standalone Python scripts that run in sequence. Each has exactly one job: prepare data, train weights, or classify a new image.

🖼️
data/
215 ASCII images
.txt files
⚙️
generate_features.py
30×20 grid
→ 600-dim vector
📄
features.csv
215 rows × 601 cols
+ LABEL column
🧠
perceptron_train.py
15 epochs
lr = 0.10
⚖️
weights.csv
601 learned weights
🔍
evaluate.py
classifies
new image
Result
"It is a 8"
or "It is NOT a 8"
Feature Extraction — ASCII grid → binary vector
  .###.
  #...#
  #...#
  .###.
  #...#
  #...#
  .###.
[0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 0,1,1,1,0, 1,0,0,0,1, …]
Each #1  ·  Each space/dot → 0
The 20×30 grid flattened into a 600-element vector. One vector per image.

How a Perceptron Works

A perceptron is the simplest possible neural network: one neuron that computes a weighted sum of its inputs and fires if the result crosses a threshold.

x₁ · w₁
x₂ · w₂
x₃ · w₃
… 600 inputs
bias = 0.10
weighted sum
Σ w·x
+ bias
threshold: 0
+1 → is 8
−1 → not 8
The Learning Rule (Weight Update)
w w + η × x × error
w — weight being updated
η = 0.10 — learning rate
x — pixel value (0 or 1)
error — label − prediction
1️⃣
Forward Pass
Compute weighted sum of all 600 pixel values plus bias. If sum > 0 → predict "8".
2️⃣
Compute Error
error = label − output
Correct → 0. Wrong → ±2.
3️⃣
Update Weights
Nudge every weight by η × x × error. If correct, error = 0 so nothing changes.
4️⃣
Repeat (Epoch)
One full pass through all 215 training images = 1 epoch. Run 15 epochs total.

Interactive Demo

Draw on the 30×20 grid — click or drag to toggle pixels. The perceptron classifies in real time using a learned weight map.

Draw something
How this works
Computes Σ w·x + bias over all 600 pixels. Positive sum → classified as 8. Weights are shaped to recognize the figure-8 stroke pattern.

Training Convergence

Misclassifications drop from 89 in epoch 0 to 0 by epoch 11, where the perceptron achieves perfect separation on the training set.

Parameters & File Structure

Hyperparameters
Parameter Value
Learning rate (η) 0.10
Max epochs 15
Feature dimensions 600
Bias 0.10
Positive samples (digit 8) 86
Negative samples (other) 129
Epochs to convergence 11
File Structure
perceptron/
├── generate_features.pyfeature extraction
├── perceptron_train.pytraining loop
├── evaluate.pyclassify new image
├── features.csv
├── weights.csv
├── requirements.txt
└── data/
    ├── train8/        86 positives
    ├── trainOthers/   129 negatives
    └── test/          evaluation images
Run It Yourself
# Install dependencies
pip install -r requirements.txt

# 1. Generate feature matrix from training images
python3 generate_features.py

# 2. Train the perceptron (saves weights.csv)
python3 perceptron_train.py

# 3. Classify a test image
cp data/test/8.txt data/test/img.txt
python3 evaluate.py
# → It is a 8