AI Cho Mọi Người

AI Cho Mọi Người

Dùng tf.keras cho bài toán classification

 

 

Trong bài này, chúng ta sẽ tiếp tục dùng module keras trong Tensorflow cho bài toán classification. Chúng ta áp dụng mô hình phân loại softmax và MLP cho bộ dữ liệu MNIST để thấy được vấn đề underfitting và overfitting trong huấn luyện mô hình.

Bộ dữ liệu MNIST bao gồm 60000 mẫu cho training và 10000 mẫu cho testing, chia thành 10 loại dữ liệu (từ số 0 đến số 9). Chúng ta có thể dùng hàm có sẵn trong Tensorflow để đọc dữ liệu MNIST như sau

import tensorflow as tf

# load data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

# normalize
x_train, x_test = x_train / 255.0, x_test / 255.0
m_train = x_train.shape[0]

print(x_train.shape) # (60000, 28, 28)
print(y_train.shape) # (60000,)

Dữ liệu được đọc lên và normalize trước khi được dùng để huấn luyện mô hình. Chúng ta sẽ dùng MLP cho bài toán này. Đây là bài toán classification, nên hàm softmax được dùng để tính xác suất cho từng node output.

 

Dùng softmax classifier

Do input có shape là (28, 28), nên chúng ta cần thực hiện flatten (chuyển thành dữ liệu 1 chiều) trước khi đưa vào layer đầu tiên. Softmax classifier được thiết kế gồm 28×28 node trong input layer và và 10 note trong output layer.

Chúng ta sẽ dùng giải thuật Adam để cập nhật các trọng số, và sparse cross entropy để tính loss. Sparse cross entropy chỉ khác với cross entropy là không yêu cầu dữ liệu label y ở dạng one-hot encoding. Source code để xây dựng mô hình softmax classifier và huấn luyện như sau

# model construction
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(10, activation='softmax')
])

# compile and train
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

history = model.fit(x_train, y_train, validation_split=0.2, epochs=20, verbose=0)

Chúng ta huấn luyện model với 20 epoch và dùng 20% dữ liệu training cho validation. Trong code này, chúng ta dùng giá trị kiểu string để khai báo optimizer, loss và metric.

Sau khi huấn luyện mô hình xong, chúng ta dùng thông tin từ biến history để hiển thị quá trình mô hình học từ dữ liệu training và thực hiện việc phân loại từ dữ liệu validation.

import matplotlib.pyplot as plt
import numpy as np

plt.figure()
plt.xlabel('Epoch')
plt.ylabel('Mean Abs Error [1000$]')
plt.plot(history.epoch, np.array(history.history['accuracy']), label='Train accuracy')
plt.plot(history.epoch, np.array(history.history['val_accuracy']), label = 'Val accuracy')
plt.legend()

Độ chính xác của mô hình sau khi huấn luyện khoảng 93% cho cả dữ liệu training và validation.  Trước khi thảo luận tiếp, chúng ta sẽ  kiểm tra độ chính xác của MLP với bộ dữ liệu MNIST

 

Dùng MLP

MLP được thiết kế gồm 2 hidden layer, trong đó mỗi hidden layer có 64 node. Hàm activation ReLU được dùng trong 2 hidden layer này. Số node của input layer là 28×28 và của output layer là 10.

# model construction
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

# model compile and train
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
history = model.fit(x_train, y_train, validation_split=0.2, epochs=20, verbose=0)

Tương tự softmax classifier, chúng ta huấn luyện model với 20 epoch và dùng 20% dữ liệu training cho validation. quá trình mô hình học từ dữ liệu training và thực hiện việc phân loại từ dữ liệu validation được hiển thị ở hình sau

Với mô hình MLP, độ chính xác cho dữ liệu training và validation lần lượt là 99% và 97%. So với mô hình softmax, MLP cải thiện độ chính xác một cách đáng kể (khoảng 6% cho training và 4% cho validation).

Với dữ liệu MNIST, mô hình MLP với việc nhiều hơn số layer có khả năng học tốt hơn. Ở chiều ngược lại, mô hình softmax bão hòa ở độ chính xác 93% và không có khả năng học sâu hơn (tốt hơn) từ quá trình huấn luyện. Đây là hiện tượng underfitting, thường xảy ra khi chúng ta sử dụng mô hình chưa đủ mạnh để học thông tin từ dữ liệu training. Cách giải quyết cho trường hợp này là chọn mô hình mạnh hơn (thường với nhiều layer hơn khi dùng MLP, CNN, hay RNN).

Hiện tượng liên quan đến underfitting là hiện tượng overfitting. Overfitting xảy ra khi mô hình học tốt (độ chính xác cao) với dữ liệu training, nhưng hoạt động không tốt với dữ liệu validation hay testing. Cách giải quyết vấn đề overfitting hiệu quả nhất là tăng độ lớn của dữ liệu training.

Để thấy rõ hơn vấn đề overfitting, chúng ta huấn luyện lại mô hình MLP với dữ liệu training nhỏ hơn khoảng 10 như sau

# model construction
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

# model compile and train
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
history = model.fit(x_train, y_train, validation_split=0.9, epochs=20, verbose=0)

Ở đây, 90% dữ liệu training ban đầu được chia cho làm dữ liệu validation. Do đó, chỉ có 10% dữ liệu cho huấn luyện mô hình. Kết quả độ chính xác như sau

Lúc này, chúng ta thấy khoảng cách độ chính xác giữa dữ liệu training và validation tăng lên khoảng 6%, và hiện tượng overfitting trở lên rõ ràng hơn. Ví dụ minh họa này cũng chứng minh lập luận việc tăng dữ liệu training sẽ giải quyết vấn đề overfitting.