AI - Machine Learning cơ bản

Bài 15: Xử lý ảnh sử dụng Neural Network

Trong bài trước chúng ta vừa triển khai một mô hình mạng neural network đơn giản học từ các điểm dữ liệu (x, y) để tìm mô hình mối quan hệ giữa x và y, mô hình này sau đó được sử dụng để tìm y khi cho x. Chắc tới đây các bạn cũng đã nhận thấy sự khác biệt giữa mô hình lập trình theo giải thuật và mô hình lập trình học máy. Mô hình xây dựng ở bài trước khá đơn giản nhưng đây là nền tảng để xử lý những bài toán phức tạp hơn như x có thể là một bức ảnh, y là nhãn của bức ảnh đó ví dụ như giày, quần hay áo,... Các thao tác nhận dạng ảnh với con người thực sự rất đơn giản nhưng với máy tính thì thực sự rất phức tạp. Máy tính sẽ phải nhìn vào tất cả các điểm ảnh, và từ các điểm ảnh đó đưa ra kết quả đầu ra, việc định nghĩa sẵn luật để nhận dạng hiệu quả gần như là bất khả thi. Trong bài này, chúng ta sẽ cùng nhau giải quyết bài toán nhận dạng ảnh đồ vật sử dụng neural network.
Nhận dạng ảnh là một trong những bài toán con trong lĩnh vực Computer Vision, đây là lĩnh vực giúp máy tính hiểu nội dung của ảnh. Nhìn vào hình 1, bạn có thể dễ dàng phân biệt các đồ vật cũng như tên gọi của chúng, tuy nhiên làm thế nào để dạy một em bé 2 tuổi nói đâu là đồ vật gì? Một cách thực tế nhất đó là đưa em bé thật nhiều ảnh của các đồ vật này và nói tên của những đồ vật đó. Đây cũng chính là các mà ta sẽ dạy máy.
Tập dữ liệu có tên Fashion MNIST cung cấp cho chúng ta 70k ảnh của 10 đồ vật khác nhau . Mỗi ảnh có kích thước 28*28 pixels. Mỗi điểm ảnh có giá trị màu từ 0 tới 255. Tổng cộng cần 784 bytes để biểu diễn mỗi ảnh. 
Tensorflow cung cấp sẵn hàm để đơn giản hoá việc load tập dữ liệu này. Hàm load_data() trả về tập các list gồm ảnh và nhãn của các ảnh đó. Để ý ở đây hàm load_data trả về hai loại dữ liệu là train và test. Trong machine learning, một chiến lược để huấn luyện mô hình đó là chia tập dữ liệu làm hai phần là train và test. Tập trainn được sử dụng để huấn luyện mô hình, test là để kiểm tra mô hình với những dữ liệu mà mô hình chưa từng được nhìn thấy. Kết quả của mô hình đánh giá trên tập test sẽ mang tính khách quan và chính xác hơn. 
from tensorflow import keras
fashion_mnist = keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = fashion_mnist.load_data()
Hiển thị một điểm dữ liệu trong tập dữ liệu này. Nhãn của điểm dữ liệu này có giá trị là 9.
plt.imshow(train_images[0])
print(training_images[0])
print("Label id:", training_labels[0])
Để quá trình huấn luyện mô hình được nhanh hơn, các thao tác chuẩn hoá lại dữ liệu thường được áp dụng. Một trong những thao tác chuẩn hoá phổ biến được áp dụng trong xử lý ảnh là đưa toàn bộ giá trị điểm ảnh về khoảng 0 -> 1.
training_images  = training_images / 255.0
test_images = test_images / 255.0
Mô hình sử dụng để nhận dạng ảnh bao gồm các thành phần sau:
Sequenntial: Giúp định nghĩa các layer cho mạng neural. Dữ liệu sẽ lần lượt được đưa qua và biến đổi trong các layer này
Flatten: Giúp biến dữ liệu dạng ma trận thành vector. Ví dụ các ảnh hai chiều (28*28) ở đây sau khi đi qua Flatten sẽ biến thành dữ vector 784 chiều
Dense: Một tầng ẩn chứa các node hay còn gọi là các neuron, các neuron này kết nối tới toàn bộ các node ở tầng phía trước. Ví dụ ở đây là 128 neuron, mỗi neuron kết nối tới 784 giá trị điểm ảnh ở tầng phía trước là Flatten. Mỗi neuron có một hàm gọi là activation hay còn gọi là hàm kích hoạt. Hiểu đơn giản là nếu giá trị input vượt quá một giá trị ngưỡng nào đó, hàm này sẽ ouput tín hiệu kích hoạt và ngược lại.
Relu là một hàm kích hoạt có công thức y = max(0, x). Hàm này chỉ cho phép tín hiệu được truyền qua nếu giá trị truyền vào lớn hơn 0.
Softmax hàm kích hoạt nhận đầu vào là chuỗi các giá trị, hàm này sẽ biến đổi chuỗi để tăng sự khác biệt giữa các phần tử trong chuỗi đầu vào. Giá trị nào cao vẫn cao, thấp vẫn thấp, nhưng cộng tổng lại bằng 1. Hàm tác động này rất hay được sử dụng trong các bài toán phân loại.
model  = tf.keras.models.Sequential(
[
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

model.compile(optimizer=tf.optimizers.Adam(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy']
)
Huấn luyện mô hình
model.fit(training_images, training_labels, epochs=5)

Epoch 1/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4938 - accuracy: 0.8246
Epoch 2/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3737 - accuracy: 0.8661
Epoch 3/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3353 - accuracy: 0.8779
Epoch 4/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3126 - accuracy: 0.8856
Epoch 5/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.2953 - accuracy: 0.8909
Mô hình huấn luyện đạt được độ chính xác trên tập train là 89%. Tuy đây không phải là kết quả thực sự tốt nhưng chỉ với một mô hình thực sự rất đơn giản và chỉ mất 5 lần duyệt qua dữ liệu thì đây là kết quả có thể chấp nhận được
Sau khi đã huấn luyện mô hình, ta có thể đánh giá chất lượng sử dụng tập test
model.evaluate(test_images, test_labels)

313/313 [==============================] - 0s 1ms/step - loss: 0.3541 - accuracy: 0.8697
[0.35407450795173645, 0.869700014591217]
Mô hình đạt độ chính xác trên tập test là 86%, thấp hơn một chút so với tập train. Đây là điều hoàn toàn hợp lý. Độ chính xác trên tập train cao hơn vì mô hình đã nhìn thấy những điểm dữ liệu đó, còn trên tập test là những điểm dữ liệu mới mà mô hình chưa từng nhìn thấy.
Sử dụng mô hình để dự đoán nhãn của một ảnh trong tập test
predict_result = model.predict(np.array([test_images[11]]))
print("Label image: ", test_labels[11])
print(predict_result)

#Label image: 5
#[[1.6722430e-05 4.4020371e-08 5.3876643e-06 4.0128889e-08 5.6786785e-06 9.9806458e-01 5.0837298e-05 1.0092560e-03 8.7840099e-06 8.3871983e-04]]
Các bạn có thể thấy giá trị output trông khá lạ. Thực ra nhìn kỹ các bạn sẽ thấy đây là một mảng gồm 10 giá trị. Những giá trị này chính là phân phối xác suất của 10 nhãn. Giá trị xác suất nào cao nhất thì nhãn dự đoán chính ở vị trí đó. Trong ví dụ này thì vị trí có giá trị xác suất cao nhất là 5.  Và giá trị này cũng trùng khớp với nhãn thực tế của ảnh. Mô hình đã dự đoán đúng.
Trong bài này, các bạn đã học được cách sử dụng neural network để nhận dạng các vật thể. Mô hình này thực ra khá giống với mô hình triển khai ở bài trước, nhưng được nâng cấp hơn về số lượng neron ở tầng ẩn. Các bạn có thể thực hành tăng kích thước tầng ẩn hoặc thậm chí tăng số lượng tầng ẩn để thấy được sự tác động của kích thước mô hình tới chất lượng của dự đoán.
Các bạn có thể chạy code của toàn bộ bài này qua link google colab này. Happy learning!