Mathew K Analytics

Lesson 38 · Data Science Projects

Building and Training Handwritten Digit Recognition Models with Scikit Learn

This lesson will help you understand how computers can recognize handwritten digits using Python. You will see every step from loading real world data to…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Recognizing HandWritten Digits in Scikit Learn#

  • This lesson will help you understand how computers can recognize handwritten digits using Python.
  • You will see every step from loading real world data to creating and evaluating a simple machine learning model.
  • We use the Digits dataset built into scikit learn, a standard tool for this kind of problem.
  • Almost anyone can relate to digits, so it is a friendly way to get into data mining and machine learning.
  • Even if you have never used Python before, you will follow along and get results by the end.
  • If you are finding this useful, remember to like and subscribe for more beginner friendly videos.
# Suppress warnings for a clean notebook
import warnings; warnings.filterwarnings("ignore")
import numpy as np
np.random.seed(42)

Data setup#

  • We use the built in Digits dataset from scikit learn.
  • Each digit is an image with 8 by 8 pixels.
  • The problem is to predict which digit is shown in an image.
  • All data is small, free to use, and needs no download.
# Load the digits dataset from sklearn
from sklearn.datasets import load_digits
digits = load_digits()
X, y = digits.data, digits.target
print(X.shape)
print(y.shape)
(1797, 64)
(1797,)
# Display the first 5 rows of data
import pandas as pd
df = pd.DataFrame(X)
print(df.head())
    0    1    2     3     4     5    6    7    8    9   ...   54   55   56  \
0  0.0  0.0  5.0  13.0   9.0   1.0  0.0  0.0  0.0  0.0  ...  0.0  0.0  0.0   
1  0.0  0.0  0.0  12.0  13.0   5.0  0.0  0.0  0.0  0.0  ...  0.0  0.0  0.0   
2  0.0  0.0  0.0   4.0  15.0  12.0  0.0  0.0  0.0  0.0  ...  5.0  0.0  0.0   
3  0.0  0.0  7.0  15.0  13.0   1.0  0.0  0.0  0.0  8.0  ...  9.0  0.0  0.0   
4  0.0  0.0  0.0   1.0  11.0   0.0  0.0  0.0  0.0  0.0  ...  0.0  0.0  0.0   

    57   58    59    60    61   62   63  
0  0.0  6.0  13.0  10.0   0.0  0.0  0.0  
1  0.0  0.0  11.0  16.0  10.0  0.0  0.0  
2  0.0  0.0   3.0  11.0  16.0  9.0  0.0  
3  0.0  7.0  13.0  13.0   9.0  0.0  0.0  
4  0.0  0.0   2.0  16.0   4.0  0.0  0.0  

[5 rows x 64 columns]
# Visualize some sample digit images
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 5, figsize=(10, 3))
for i, ax in enumerate(axes):
    ax.imshow(digits.images[i], cmap="gray_r")
    ax.set_title(f"Label: {digits.target[i]}")
    ax.axis("off")
plt.show()
No description has been provided for this image

Why recognize digits?#

  • Digit recognition is a classic problem in data science and artificial intelligence.
  • It connects to real world things like sorting post, bank checks, or reading utility meters.
  • Successful digit recognition is the first step towards reading handwriting or even documents.
  • Machine learning is the tool we use to teach computers to spot digit patterns.
# Check for missing data
import numpy as np
missing = np.isnan(X).sum()
print(f"Total missing values: {missing}")
Total missing values: 0
# Split the data into train and test sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(X_train.shape, X_test.shape)
(1437, 64) (360, 64)
# Look at the label distribution in the training set
unique, counts = np.unique(y_train, return_counts=True)
for value, count in zip(unique, counts):
    print(f"Digit {value}: {count} samples")
Digit 0: 145 samples
Digit 1: 154 samples
Digit 2: 144 samples
Digit 3: 149 samples
Digit 4: 135 samples
Digit 5: 135 samples
Digit 6: 146 samples
Digit 7: 145 samples
Digit 8: 144 samples
Digit 9: 140 samples
# Scale the features for better model performance
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

Building your first digit classifier#

  • The most basic classifier is called logistic regression.
  • It is a simple algorithm that learns boundaries between groups.
  • Logistic regression works for digits because it can handle numbers as categories.
  • The steps below will fit a model to the training digits.
# Train a logistic regression model
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(max_iter=1000, solver="lbfgs", multi_class="auto", random_state=42)
clf.fit(X_train_scaled, y_train)
LogisticRegression(max_iter=1000, multi_class='auto', random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
# Predict on the test set
y_pred = clf.predict(X_test_scaled)
print(y_pred[:10])
[6 9 3 7 2 1 5 2 5 2]
# Measure model accuracy
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_test, y_pred)
print(f"Accuracy: {acc:.2f}")
Accuracy: 0.97
# Show model performance for each digit
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        33
           1       0.97      1.00      0.98        28
           2       1.00      1.00      1.00        33
           3       0.97      0.97      0.97        34
           4       1.00      0.98      0.99        46
           5       0.94      0.94      0.94        47
           6       0.97      0.97      0.97        35
           7       1.00      0.97      0.99        34
           8       0.97      0.97      0.97        30
           9       0.93      0.95      0.94        40

    accuracy                           0.97       360
   macro avg       0.97      0.97      0.97       360
weighted avg       0.97      0.97      0.97       360

# Visualize results: show predictions vs actuals
fig, axes = plt.subplots(2, 5, figsize=(12, 5))
for i, ax in enumerate(axes.flat):
    idx = i
    ax.imshow(X_test[idx].reshape(8,8), cmap="gray_r")
    ax.set_title(f"Pred:{y_pred[idx]}, True:{y_test[idx]}")
    ax.axis("off")
plt.tight_layout()
plt.show()
No description has been provided for this image

Bonus: Try your own digit#

  • Did you know you can predict your own data if it matches the digits format?
  • Just reshape your 8 by 8 gray pixel image to a 64 element array.
  • Feed it through the scaler and model, and see what comes back.
  • This is a mini project you can try for practice after the video.
  • If you want more beginner friendly projects, do not forget to subscribe.
# Confusion matrix: where does the model get confused?
import seaborn as sns
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8,6))
sns.heatmap(cm, annot=True, fmt="d", cmap="YlGnBu")
plt.xlabel("Predicted")
plt.ylabel("True")
plt.title("Confusion Matrix")
plt.show()
No description has been provided for this image
# Try a different model: K Nearest Neighbors
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train_scaled, y_train)
knn_pred = knn.predict(X_test_scaled)
knn_acc = accuracy_score(y_test, knn_pred)
print(f"KNN Accuracy: {knn_acc:.2f}")
KNN Accuracy: 0.97
# Time series: visualize digit counts over index
import matplotlib.pyplot as plt
digits_per_index = pd.Series(y).value_counts().sort_index()
plt.figure(figsize=(8,4))
plt.plot(digits_per_index.index, digits_per_index.values, marker="o")
plt.title("Sample Count By Digit Value")
plt.xlabel("Digit")
plt.ylabel("Count")
plt.show()
No description has been provided for this image

Congratulations! You built a digit recognizer.#

  • You saw practical machine learning from start to finish.
  • Using scikit learn, you loaded, visualized, split, scaled, and modeled data.
  • You picked a model and verified its predictions.
  • You learned about confusion matrices, model accuracy, and alternative algorithms.
  • This is a foundation for all kinds of pattern recognition tasks.
  • Do not forget to practice and try tweaks.
  • See the YouTube video description for more exercises and helpful resources.

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.