Xây dựng và huấn luyện một mô hình phân loại chữ số viết tay.

1725
0

Trong thế giới của học máy và trí tuệ nhân tạo, việc phân loại các hình ảnh chữ số viết tay từ 0 đến 9 là một bài toán cổ điển và thú vị. Đây là một thách thức quan trọng, thể hiện khả năng của máy tính trong việc nhận biết và phân loại dữ liệu hình ảnh.

Trước khi bắt đầu viết mã, tôi đã tìm hiểu về dự án. Mục tiêu của tôi là xây dựng một mô hình máy học đơn giản để phân loại các chữ số viết tay từ bộ dữ liệu MNIST. Dự án này sẽ sử dụng thư viện Keras, một thư viện mạnh mẽ cho việc phát triển mô hình neural network.

Bài viết này sẽ hướng dẫn bạn qua từng bước trong quá trình xây dựng mô hình.

Bước 1: Import Các Thư Viện Cần Thiết

Đầu tiên, tôi đã import các thư viện cần thiết cho dự án của mình. Điều này bao gồm Keras để xây dựng và huấn luyện mô hình, cũng như các thư viện khác để tiền xử lý dữ liệu và lưu trữ kết quả.

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import Adam
import csv

Bước 2: Load và Tiền Xử Lý Dữ Liệu

2.1. Load Dữ Liệu MNIST

Dự án của chúng ta sử dụng tập dữ liệu MNIST chứa các hình ảnh của các chữ số viết tay từ 0 đến 9. Hãy tải tập dữ liệu này và chia thành tập huấn luyện và tập kiểm tra.

(x_train, y_train), (x_test, y_test) = mnist.load_data()

2.2. Tiền Xử Lý Dữ Liệu

Sau khi có dữ liệu từ bộ dữ liệu MNIST, tôi đã tiến hành tiền xử lý. Điều này bao gồm việc biến đổi dữ liệu hình ảnh và chuẩn hóa nó để phù hợp với mô hình. Đồng thời, tôi đã biến đổi nhãn của các hình ảnh thành định dạng one-hot encoding để phục vụ cho việc huấn luyện mô hình.

Reshape và chuẩn hóa dữ liệu
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
One-hot encoding cho nhãn
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

Bước 3: Xây Dựng Mô Hình

Tiếp theo, tôi đã bắt đầu xây dựng mô hình máy học. Mô hình của tôi là một mạng neural network đơn giản với các lớp Convolutional, Pooling và Fully Connected. Tôi đã thiết lập kiến trúc mô hình theo cách tôi nghĩ sẽ phù hợp với bài toán phân loại chữ số viết tay.

model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

Để hiểu rõ hơn về việc xây dựng mô hình neural network trong bước 3, hãy đi vào chi tiết từng lớp của mô hình:

3.1. Lớp Convolutional 1:

– Sử dụng lớp Conv2D với 32 bộ lọc (filters).
– Kích thước mỗi bộ lọc là 5×5.
– Hàm kích hoạt (activation function) là ‘relu’.
– Lớp này nhận đầu vào từ hình ảnh và tạo ra các đặc trưng quan trọng từ hình ảnh bằng cách áp dụng các bộ lọc convolutional.

3.2. Lớp Max Pooling 1:

– Sử dụng lớp MaxPooling2D để giảm kích thước của đầu ra sau lớp Convolutional 1.
– Sử dụng pool_size=(2, 2) để giảm kích thước xuống còn một nửa.
– Max pooling giúp giảm số lượng thông tin không cần thiết và tạo ra sự trừu tượng từ hình ảnh.

3.3. Lớp Convolutional 2:

– Sử dụng lớp Conv2D với 64 bộ lọc.
– Kích thước mỗi bộ lọc là 3×3.
– Hàm kích hoạt là ‘relu’.
– Lớp này tiếp tục trích xuất các đặc trưng từ hình ảnh sau khi đã áp dụng lớp MaxPooling trước đó.

3.4. Lớp Max Pooling 2:

– Sử dụng lớp MaxPooling2D để giảm kích thước của đầu ra sau lớp Convolutional 2.
– Cũng sử dụng pool_size=(2, 2) để giảm kích thước xuống còn một nửa.

3.5. Lớp Flatten:

– Lớp này chuyển đổi đầu ra từ một ma trận 2D thành một vector 1D.
– Các giá trị đặc trưng được “đổ” vào một vector để có thể đưa vào các lớp Fully Connected sau này.

3.6. Lớp Fully Connected 1:

– Sử dụng lớp Dense với 128 đơn vị (neurons).
– Hàm kích hoạt là ‘relu’.
– Lớp này là một lớp fully connected (hoàn toàn kết nối) và có nhiệm vụ học các mối quan hệ phức tạp giữa các đặc trưng từ hình ảnh.

3.7. Lớp Dropout 1:

– Sử dụng lớp Dropout với tỷ lệ dropout là 0.5.
– Lớp Dropout giúp ngăn chặn overfitting bằng cách tắt ngẫu nhiên một số đơn vị (neurons) trong quá trình huấn luyện.

3.8. Lớp Fully Connected 2:

– Sử dụng lớp Dense với 64 đơn vị.
– Hàm kích hoạt là ‘relu’.
– Lớp này tiếp tục học các mối quan hệ phức tạp từ các đặc trưng đã trích xuất.

3.9. Lớp Dropout 2:

– Sử dụng lớp Dropout thứ hai với tỷ lệ dropout là 0.5.

3.10. Lớp Fully Connected 3 (Lớp Output):

– Sử dụng lớp Dense cuối cùng với 10 đơn vị.
– Hàm kích hoạt là ‘softmax’.
– Lớp này cho ra đầu ra phân phối xác suất của 10 lớp, tương ứng với 10 chữ số từ 0 đến 9.

Tóm lại, mô hình này bao gồm việc trích xuất đặc trưng từ hình ảnh bằng các lớp Convolutional và Max Pooling, sau đó học các mối quan hệ phức tạp thông qua các lớp Fully Connected. Lớp Output đưa ra dự đoán xác suất cho từng lớp chữ số.

Bước 4: Biên Dịch Mô Hình

Sau khi xây dựng mô hình, tôi đã biên dịch nó bằng cách chọn hàm mất mát và thuật toán tối ưu hóa.

optimizer = Adam(learning_rate=0.001)
model.compile(loss=keras.losses.categorical_crossentropy, optimizer=optimizer, metrics=['accuracy'])

Bước 5: Huấn luyện Mô Hình

Tiếp theo, tôi đã bắt đầu quá trình huấn luyện mô hình trên tập dữ liệu huấn luyện bằng cách sử dụng phương thức fit.

batch_size = 128
epochs = 100

hist = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))
print("Mô hình đã được huấn luyện thành công")

Bước 6: Đánh Giá Mô Hình

Sau khi huấn luyện xong, tôi đã đánh giá mô hình trên tập kiểm tra để xem hiệu suất của nó trên dữ liệu mới.

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

Đồ thị biểu diễn kết quả thử nghiệm

Bước 7: Lưu Mô Hình và Nhật Ký Huấn Luyện

Cuối cùng, tôi đã lưu mô hình vào tệp mnist.h5 để sau này có thể sử dụng lại. Tôi cũng đã lưu lại nhật ký của quá trình huấn luyện vào tệp training_log.csv để theo dõi quá trình này.

model.save('mnist.h5')
print("Đã lưu mô hình thành công vào mnist.h5")

# Lưu nhật ký huấn luyện vào file CSV
with open('training_log.csv', 'w', newline='') as csvfile:
    fieldnames = ['epoch', 'loss', 'accuracy', 'val_loss', 'val_accuracy']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    
    for epoch in range(1, len(hist.history['accuracy']) + 1):
        row = {
            'epoch': epoch,
            'loss': hist.history['loss'][epoch - 1],
            'accuracy': hist.history['accuracy'][epoch - 1],
            'val_loss': hist.history['val_loss'][epoch - 1],
            'val_accuracy': hist.history['val_accuracy'][epoch - 1]
        }
        writer.writerow(row)
        
print("Nhật ký huấn luyện đã được lưu vào training_log.csv")

Quá trình xây dựng mã này đã bao gồm nhiều bước quan trọng, từ tiền xử lý dữ liệu đến việc xây dựng và huấn luyện mô hình. Đây là một ví dụ cụ thể về cách tôi đã thực hiện một dự án máy học từ đầu đến cuối, và cách sử dụng Keras để giúp tôi đạt được mục tiêu của dự án này.

Mã nguồn mô hình và GUI

Tôi cũng đã xây dựng một chương trình giao diện người dùng sử dụng mô hình đã huấn luyện trên để nhận dạng chữ số do người dùng vẽ trực tiếp. Mã nguồn chương trình các bạn có thể tham khảo trong liên kết dưới đây:

https://github.com/tadneits/Handwritten-digit-recognition

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *