Nhận diện chữ số viết tay là một trong những bài toán nền tảng của thị giác máy tính, với nhiều ứng dụng thực tế trong lĩnh vực ngân hàng, bưu điện, và giáo dục. Từ việc tự động đọc số trên phong bì thư, xử lý hóa đơn, đến chấm điểm bài thi trắc nghiệm, công nghệ này giúp tiết kiệm thời gian và giảm thiểu sai sót so với phương pháp thủ công.
Với sự phát triển của học sâu, đặc biệt là mạng nơ-ron tích chập (Convolutional Neural Networks – CNN), việc nhận diện chữ số viết tay đã đạt độ chính xác vượt trội. Trong bài viết này, chúng ta sẽ xây dựng một mô hình CNN đơn giản để nhận diện chữ số viết tay từ tập dữ liệu MNIST, từng bước giải thích để người mới có thể hiểu và thực hành.
Mô tả bài toán
Bài toán đặt ra là: xây dựng một mô hình học sâu có khả năng nhận diện chính xác chữ số (0–9) viết tay từ ảnh grayscale kích thước 28×28 pixel.
Pipeline xử lý sẽ gồm các bước:
- Tải và tiền xử lý dữ liệu MNIST.
- Xây dựng mô hình CNN.
- Huấn luyện và đánh giá mô hình.
- Dự đoán chữ số từ ảnh mới.
- Lưu mô hình để sử dụng sau.
Tải và tiền xử lý dữ liệu MNIST
Trước khi huấn luyện, chúng ta cần một bộ dữ liệu tiêu chuẩn để đảm bảo mô hình được học từ những mẫu đa dạng. MNIST là tập dữ liệu gồm 60.000 ảnh chữ số viết tay cho huấn luyện và 10.000 ảnh cho kiểm tra, được sử dụng rộng rãi như benchmark trong lĩnh vực thị giác máy tính.
Việc tiền xử lý dữ liệu bao gồm việc chuẩn hóa pixel về khoảng [0,1], định dạng lại dữ liệu để phù hợp với đầu vào của mạng CNN, và chuyển nhãn thành dạng one-hot vector.
Chúng ta sử dụng API của TensorFlow để tải MNIST trực tiếp. Ảnh được chia tỷ lệ và reshape về định dạng (28,28,1) để tương thích với CNN.
import tensorflow as tf # Tải dữ liệu MNIST (X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data() # Chuẩn hóa pixel về khoảng [0,1] X_train = X_train / 255.0 X_test = X_test / 255.0 # Thêm kênh để phù hợp CNN (28x28x1) X_train = X_train.reshape(-1, 28, 28, 1) X_test = X_test.reshape(-1, 28, 28, 1) # Chuyển nhãn thành one-hot y_train = tf.keras.utils.to_categorical(y_train, 10) y_test = tf.keras.utils.to_categorical(y_test, 10)
Xây dựng mô hình CNN
CNN được thiết kế để xử lý dữ liệu dạng lưới như ảnh, giúp tự động học ra các đặc trưng hình ảnh quan trọng. Với bài toán nhận diện chữ số, CNN giúp phân biệt các nét cong, đường thẳng đặc trưng của từng số.
Kiến trúc CNN gồm các lớp tích chập (Convolution), lớp gộp (Pooling) để giảm chiều dữ liệu, và lớp fully connected để đưa ra dự đoán.
Chúng ta xây dựng một mạng gồm 2 lớp Conv2D, mỗi lớp theo sau là MaxPooling2D, rồi Flatten và Dense để dự đoán xác suất 10 lớp.
from tensorflow.keras import layers, models
model = models.Sequential([
layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# Compile mô hình
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
Huấn luyện và đánh giá mô hình
Huấn luyện giúp mô hình điều chỉnh trọng số để giảm thiểu sai số dự đoán. Đánh giá trên tập test đảm bảo mô hình không bị overfitting và hoạt động tốt trên dữ liệu chưa từng thấy.
Thông qua việc theo dõi độ chính xác và loss, chúng ta có thể điều chỉnh hyperparameter để đạt kết quả tốt hơn.
Huấn luyện trong 5 epochs với batch size 64 và đánh giá độ chính xác trên tập test.
# Huấn luyện mô hình
model.fit(X_train, y_train, epochs=5, batch_size=64, validation_data=(X_test, y_test))
# Đánh giá
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"Độ chính xác trên tập test: {test_acc:.2f}")
Dự đoán chữ số từ ảnh mới
Sau khi huấn luyện, bạn cần kiểm tra mô hình trên ảnh mới để xác định khả năng tổng quát hóa. Việc này quan trọng trong ứng dụng thực tế, nơi dữ liệu đầu vào không giống hệt dữ liệu huấn luyện.
Chúng ta chọn một ảnh từ tập test, hiển thị nó và để mô hình dự đoán.
import numpy as np
import matplotlib.pyplot as plt
# Chọn 1 ảnh
img = X_test[0]
plt.imshow(img.reshape(28,28), cmap='gray')
plt.title("Ảnh thử nghiệm")
plt.axis('off')
plt.show()
# Dự đoán
pred = model.predict(np.expand_dims(img, axis=0))
print(f"Chữ số dự đoán: {np.argmax(pred)}")
Lưu mô hình để sử dụng sau
Lưu mô hình giúp tái sử dụng mà không cần huấn luyện lại, tiết kiệm thời gian và tài nguyên. Đây là bước quan trọng khi triển khai hệ thống vào môi trường thực tế.
Sử dụng phương thức save() của Keras để lưu toàn bộ kiến trúc và trọng số.
model.save('mnist_cnn_model.h5')
Kết luận
Nhận diện chữ số viết tay là một trong những ứng dụng nền tảng của học sâu, và qua bài viết này bạn đã học cách xây dựng một mô hình CNN để thực hiện nhiệm vụ đó. Mô hình đã đạt được độ chính xác cao trên tập dữ liệu MNIST, chứng minh sức mạnh của CNN trong xử lý ảnh.
Tiếp theo, bạn có thể cải thiện mô hình bằng cách sử dụng các kỹ thuật augmentation (Augmentation ảnh để huấn luyện tốt hơn) hoặc triển khai mô hình thành API (Hướng dẫn xây dựng API dự đoán bằng Flask + ML model) để tích hợp vào ứng dụng thực tế.

