Trong lĩnh vực trí tuệ nhân tạo, việc nhận diện chữ viết tay từ hình ảnh là một bài toán kinh điển và mang tính ứng dụng cao trong thực tế. Từ việc xử lý phiếu khảo sát, tự động hóa kiểm tra biểu mẫu, đến xây dựng hệ thống chấm điểm trắc nghiệm, khả năng nhận diện chính xác chữ viết tay giúp tiết kiệm thời gian và giảm thiểu sai sót. Một trong những bộ dữ liệu nổi tiếng nhất hỗ trợ giải quyết bài toán này là MNIST – tập dữ liệu gồm 70.000 ảnh chữ số viết tay được chuẩn hóa. Nếu bạn từng làm việc với các bài toán như phân loại hình ảnh đồ ăn bằng mô hình pre-trained hoặc tạo mô hình phân loại chó và mèo, thì chắc chắn sẽ thấy nhiều kỹ thuật quen thuộc trong bài toán MNIST này.
Bài viết này sẽ hướng dẫn bạn từng bước xây dựng mô hình nhận diện chữ viết tay bằng mạng nơ-ron tích chập (CNN). Từ tải dữ liệu, xử lý đầu vào, xây dựng kiến trúc mạng cho đến huấn luyện và đánh giá mô hình, tất cả đều được trình bày chi tiết để bạn có thể thực hành ngay. Đây là đồ án lý tưởng cho sinh viên công nghệ thông tin, người mới bắt đầu học Deep Learning hoặc những ai đang tìm kiếm một dự án thực tế để bổ sung vào portfolio.
Mô tả bài toán
Bài toán đặt ra là xây dựng một mô hình có thể tự động phân loại ảnh chữ số viết tay (0-9) từ tập dữ liệu MNIST. Mỗi ảnh là một ma trận 28×28 pixel, với độ xám từ 0 (đen hoàn toàn) đến 255 (trắng hoàn toàn). Mục tiêu của mô hình là đạt được độ chính xác cao nhất trên tập kiểm tra (test set) khi dự đoán chữ số.
Link tải dữ liệu MNIST
Bạn có thể tải trực tiếp MNIST từ TensorFlow datasets:
from tensorflow.keras.datasets import mnist (X_train, y_train), (X_test, y_test) = mnist.load_data()
Hoặc tải bộ dữ liệu dạng CSV từ Kaggle:
👉 MNIST in CSV (Kaggle)
Cài đặt môi trường và thư viện
Đảm bảo bạn có Python 3.7+ và cài đặt các thư viện cần thiết:
pip install tensorflow numpy matplotlib seaborn
Xây dựng mô hình CNN nhận diện chữ viết tay
Bước 1: Tiền xử lý dữ liệu
Chuẩn hóa dữ liệu và reshape về dạng phù hợp cho CNN:
import tensorflow as tf
from tensorflow.keras.utils import to_categorical
# Chuẩn hóa pixel về khoảng 0-1
X_train = X_train.reshape(-1, 28, 28, 1).astype("float32") / 255
X_test = X_test.reshape(-1, 28, 28, 1).astype("float32") / 255
# One-hot encode labels
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
Bước 2: Xây dựng kiến trúc CNN
Tạo mô hình CNN đơn giản với Keras:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),
Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])

