Skip to main content

Tinh chỉnh mô hình - Phần 2: Huấn luyện

tags: tutorial, series, basic, training, beginning

Giới thiệu

Trong bài này chúng ta sẽ tiến hành huấn luyện mạng đã sử dụng ở Bài trước và đánh giá các kết quả mô hình sau khi huấn luyện. Quá trình huấn luyện chúng ta chỉ sử dụng dữ liệu huấn luyện. Dữ liệu kiểm tra giúp đánh giá khả năng hoạt động của thuật toán trong môi trường mới. Trong bài này chúng ta sẽ có ba phần chính:

  1. Training & Testing
  2. Evaluation

Training & testing

Trong quá trình tạo ra các "bộ não" nhân tạo thông minh thì huấn luyện và kiểm tra là hai giai đoạn quan trọng để hoàn thành bộ não này. Chúng ta sẽ tìm hiểu cách thực thi các dòng code đơn giản cho hai quá trình trong phần này.

Training

Để thuật toán có thể tốt thì việc huấn luyện mô hình là một điều quan trọng. Muốn huấn luyện một mô hình thì chúng ta cần sử dụng các thuật toán optimization như SGD, Adam hay RMSProp. Tùy từng thuật toán mà chúng ta sẽ có các siêu tham (hyperparameters) số khác nhau. Tuy nhiên, các siêu tham số như learning rate, batch size, epochs là những tham số bắt buộc và quan trọng trong quá trình huấn luyện.

Việc điều chỉnh hay chọn các siêu tham số không phù hợp sẽ dẫn đến kết quả không tốt. Để huấn luyện được mô hình tốt người ta cần nhiều thời gian và phương pháp để chọn ra các tham số phù hợp nhất có thể, quá trình này còn có trên gọi hyperparameter tuning. Ngoài ra, các siêu tham số này có thể được chọn theo cách an toàn, tuy không tốt bằng khi sử dụng hyperparameter tuning nhưng các kết quả đạt có thể đạt được ở mức chấp nhận.

Hyperparameter tuning hay hyperparameter optimization là một nhánh nghiên cứu trong meachine learning và toán tối ưu.

Chúng ta sẽ khởi tạo và định nghĩa trước các siêu tham số cho quá trình huấn luyện. Sử dụng thuật toán SGD của Tensorflow cho quá trình tối ưu hóa này như sau:

import tensorflow as tf
epochs = 2
learning_rate = 5e-8
batch_size = 64
sgd = tf.keras.optimizers.SGD(learning_rate=learning_rate)
new_net.compile(
optimizer=sgd,
loss=tf.keras.losses.mean_squared_error,
)

Giải thích code.

Dòng 2, 3, 4: khởi tạo các hyperparameters trước khi huấn luyện. Dòng 5, khởi tạo thuật toán SGD từ tensorflow với siêu tham số learning_rate định nghĩa trước đó. Dòng 6, biên dịch, mạng new_net với thuật toán tối ưu và hàm mất mát là MSE, sử dụng độ chính xác để làm độ đo đánh giá.

Như vậy chúng đã chuẩn bị xong tài liệu và trang thiết bị cho việc ôn tập trước kì thi rồi, giờ đến lúc học thôi. Chúng ta sẽ sử dụng hàm fit của TensorFlow để huấn luyện mạng.

new_net.fit(x_train, y_train_oh, epochs=epochs, batch_size=batch_size)

Kết quả xuất ra màn hình.

Epoch 1/2
782/782 [==============================] - 27s 34ms/step - loss: 168.5460
Epoch 2/2
782/782 [==============================] - 26s 33ms/step - loss: 28.8357
<tensorflow.python.keras.callbacks.History at 0x7f74ae07e358>

Trong Tensorflow có nhiều hàm hỗ trợ người sử dụng để có thể code một cách đơn giản như compile , evaluate, hay fit. Fit là một hàm hỗ trợ chúng ta huấn luyện mạng với đầu vào là dữ liệu (bao gồm x_train, y_train) và các siêu tham số (epochs , batch_size).

Khi chạy lệnh trên, màn hình sẽ in ra cho chúng ta thông tin trong quá trình huấn luyện như số lượng vòng lặp (iterations), thời gian và độ lỗi của mỗi epoch. Điều này giúp chúng ta hiểu được hướng đi của mô hình và từ đó có những điều chỉnh phù hợp.

Sau khi huấn luyện nếu muốn xem lại lịch sử bao gồm các thông số như độ lỗi hoặc metrics đánh giá trên từng epoch,... Các giá trị này đều lưu trong đối tượng history của mô hình mạng.

print(new_net.history.history)

Kết quả xuất ra màn hình.

{'loss': [92.3093032836914, 24.585634231567383]}

Chi tiết.

Kết quả trả về là một đối tượng thuộc dictionary. Đối tượng này lưu giữ các giá trị như độ lỗi và các thông số đánh giá của từng epochs. Với mỗi key là một loại thông tin và value là một danh sánh các giá trị tương ứng cho từng epoch.

Testing

Sau khi huấn luyện mô hình xong chúng ta sẽ đánh giá khả năng hoạt động của mô hình. Điều này giống như con người trong một cuộc thi, chúng ta sẽ có hai phần là học tập và kiểm tra. Bạn sẽ 'học tập' trước khi vào phòng thi, sau đó bạn sẽ được kiểm tra/đánh giá khả năng học của mình trong phòng thi và chắc chắn sẽ không có trường hợp nào gian lận như biết trước đề thi. Vậy dữ liệu kiểm tra và dữ liệu huấn luyện sẽ không trùng nhau và trong lúc bạn 'ôn tập' cho kì thi vì sẽ không biết đề thi chính thức (dữ liệu kiểm tra).

Có hai hàm trong TensorFlow có thể để thực hiện việc kiểm tra là evaluatepredict . Về bản chất thì hai hàm này như nhau nhưng đối tượng và tham số truyền vào là khác nhau. Trong bài trước chúng ta cũng dùng hàm predict như sau:

y_test_pred = new_net.predict(x_test, 64)
loss = tf.keras.losses.mean_squared_error(y_test_oh, y_test_pred).numpy().mean()
print(loss)

Giải thích chi tiết.

Dòng 1, chúng ta sử dụng predict để lấy kết quả dự đoán trên tập ảnh x_test, 64 là batch size của quá trình dự đoán này (mặc định của hàm này batch size là 32). Dòng 2, chúng ta tính độ lỗi giữa nhãn dữ liệu và kết quả dự đoán, tương ứng là y_test_ohy_test_pred. Ở đây hàm mean_squared_error chỉ tính trung bình giữa ở kênh C của dữ liệu, tức là tính độ lỗi trung bình giữa các class, sử dụng thêm hàm mean để ra một giá trị số thực là độ lỗi trung bình giữa các class và các đối tượng (instances). Nếu không dùng hàm mean thì kết quả trả về là một vector có kích thước là (10000,), do có 10000 ảnh/instance trong dữ liệu kiểm tra.

Giá trị in ra màn hình là độ lỗi của nhãn dữ liệu so với kết quả dự đoán. Tuy nhiên khác với predict, đối tượng trả về của evaluate không phải là giá trị dự doán của mô hình mà là một đối tượng chứa các thông tin đánh giá của mô hình. Do đó, hàm evaluate ngoài nhận giá trị x_test thì nó còn có một tham số bắt buộc là y_test_oh. Xem đoạn code bên dưới để hiểu thêm.

result = new_net.evaluate(x_test, y_test_oh, batch_size=batch_size)
print(result)

Kết quả xuất ra màn hình là giá trị độ giữa kết quả dự đoán trên x_train và nhãn dữ liệu y_test_oh.

Evaluation

Đánh giá bằng số liệu

Chúng ta tạo ra các mô hình máy học cũng nhằm mục đích là phục vụ cho con người. Tuy nhiên, nếu muốn ứng dụng được các thuật toán vào đời sống thì chúng ta cần phải đánh giá nó trong một môi trường tương tự như trong đời thực. Cụ thể hơn, trong bài toán phân loại ảnh thì dữ liệu chúng ta muốn phân loại là ảnh thực trong đời sống và ảnh đó chưa gán nhãn. "Vậy làm sao để biết thuật toán sẽ hoạt động tốt trên dữ liệu chưa biết?". Câu trả lời đã có từ phần 1, chúng ta chia dữ liệu làm hai phần (huấn luyện/kiểm tra). Vì dữ liệu kiểm tra là dữ liệu "chưa biết" nên khi đánh giá thuật toán trên dữ liệu này thì chúng ta sẽ tin tưởng thuật toán cũng sẽ hoạt động tương tự trên dữ liệu thật.

Ở những đoạn code trước chúng ta chỉ dùng giá trị độ lỗi để so sánh kết quả dự đoán và nhãn dữ liệu. Tuy nhiên, cách này rất khó cho con người hiểu được khả năng hoạt động của thuật toán. Chúng ta chỉ tin rằng độ lỗi càng thấp thì mô hình càng tốt. Do đó, ngoài độ lỗi chúng ta còn có thể đánh giá thuật toán dự trên độ đo đánh giá (metrics) khác.

Tùy từng bài toán mà có nhiều cách đánh giá, nhiều loại metrics khác nhau. Với bài toán phân loại ảnh thì độ đo thường dùng là độ chính xác (accuracy). Công thức độ chính xác như sau:

Acc=NcNtotalAcc = \frac{N_c}{N_{total}}

Trong đó NcN_c là số lượng mẫu dự đoán đúng và NtotalN_{total} là tổng số lượng mẫu. Ở đâu một mẫu hay một instance là một cặp ảnh và nhãn. Chúng ta có thể sử dụng các hàm hỗ trợ của TensorFlow để đánh giá. Chúng ta sẽ sử dụng biến y_test_pred (kết quả dự đoán từ tập kiểm tra) trong bài trước để đánh giá độ chính trước khi huấn luyện.

m = tf.keras.metrics.CategoricalAccuracy()
m.update_state(y_test_oh, y_test_pred)
print(m.result().numpy())

Kết quả trả về là một con số x[0,1]x \in [0,1] cho biết độ chính xác của dự đoán. Nếu kết quả trả về có thể là 0.110.11 - nghĩa là mô hình có độ chính xác là 11%11\%, giả sử có 100 ảnh chưa biết nhãn của thì mô hình có khả năng dự đoán đúng 11 ảnh trong đó.

Tùy vào độ đo mà giá trị có thể nằm trong một khoảng nhất định. Có độ do giá trị càng cao càng tốt, nhưng cũng có độ đo ngược lại. Các độ đo thường dùng để đánh giá mô hình thay vì sử dụng như hàm mất mát. Thông thường độ do và hàm đánh giá không tuyến tính với nhau.