AI Cho Mọi Người

AI Cho Mọi Người

Áp dụng CNN cho MNist và Cifar-10 dataset

 

 

Trong phần này, chúng ta sẽ áp dụng kiến thức đã học về CNN và áp dụng cho bài toán phân loại số dùng bộ dữ liệu MNIST và phân loại ảnh dùng bộ dữ liệu Cifar-10.

 

Phân loại số dùng bộ dữ liệu MNIST

Ảnh từ MNIST là ảnh grayscale có kích thước là 28x28, nên input cho CNN có shape là 28x28x1. CNN có nhiệm vụ phân loại ảnh input từ 10 nhóm (từ số 0 đến số 9). Do đó, layer cuối cùng của CNN sẽ là tầng fully connected với 10 node và hàm activation softmax.

Chúng ta sẽ sử dụng kiến trúc CNN được mô tả ở hình sau cho bài toán này. Hàm activation ReLU được sử  dụng ở các tầng convolution và hai tầng fully connected đầu tiên.

Bài tập: Kiến trúc này rất giống với bài trước. Dựa vào source code của bài trước, các bạn hãy chỉnh sửa code để phù hợp với hình kiến trức CNN ở trên.

Ngoài việc xây dựng mô hình CNN, chúng ta cần xác định thêm một số thông tin nữa đề huấn luyện mô hình như

  • Chuẩn bị data. Phần này chúng ta đã làm rất nhiều lần qua các bài học trước. Các bạn nếu chưa nắm vững cách lấy dữ liệu MNIST từ Tensorflow hay đọc từ ổ cứng dung numpy thì xem lại các bài học trước để hiểu hơn.
  • Xác định optimizer.  Trong bài này, chúng ta sẽ dùng thuật toán Adam, là một bản cải tiến của thuật toán stochastic gradient descent. Để chỉ định việc huấn luyện CNN dùng Adam trong Tensorflow, chúng ta chỉ cần khai báo optimizer='adam'.
  • Cách tính loss. Chúng ta sẽ sử dụng cross entropy để tính giá trị loss. Tensorflow hỗ trợ cách tính cross entropy với giá trị y (label) ở dạng số (không ở dạng one-hot encoding) với cách khai báo loss='sparse_categorical_crossentropy'.
  • Cách tính độ chính xác của mô hình CNN cho training (và validation) data. Ở bài này, chúng ta sẽ dùng tiêu chuẩn accuracy (%) như sau metrics=['accuracy'].

 

Source code của chương trình cho bài toán phân loại số MNIST như sau

# CNN for mnist

import collections
import numpy as np
import matplotlib.pyplot as plt
import PIL
import tensorflow as tf

from tensorflow.keras.layers import Convolution2D, MaxPooling2D, Flatten, Dense

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

img_rows, img_cols = 28, 28
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)


# model architecture
model = tf.keras.models.Sequential([
     # 28x28x1
     Convolution2D(filters=6, kernel_size=(5,5), activation = 'relu', input_shape=input_shape),
     # 24x24x6
     MaxPooling2D(pool_size=(2, 2)),
     # 12x12x6
     Convolution2D(filters=16, kernel_size=(5,5), activation = 'relu'),
     # 8x8x16
     MaxPooling2D(pool_size=(2, 2)),
     # 4x4x16
     Flatten(),
     Dense(128, activation = 'relu'),
     Dense(84, activation = 'relu'),
     Dense(10, activation=tf.nn.softmax)])

model.summary()


# training
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=32, validation_split=0.2, epochs=100, verbose=1)

# testing
print(model.metrics_names)
print(model.evaluate(x_train, y_train, verbose=2))
print(model.evaluate(x_test, y_test, verbose=2))

 

Accuracy qua quá trình huấn luyện

 

Phân loại ảnh dùng bộ dữ liệu Cifar-10

Ảnh từ Cifar-10 là ảnh màu có kích thước là 32x32, nên input cho CNN có shape là 32x32x1. CNN có nhiệm vụ phân loại ảnh input từ 10 nhóm, nên layer cuối cùng của CNN sẽ là tầng fully connected với 10 node và hàm activation softmax.

Chúng ta sẽ sử dụng kiến trúc CNN được mô tả ở hình sau cho bài toán này. Hàm activation ReLU được sử  dụng ở các tầng convolution và hai tầng fully connected đầu tiên.

Cách chuẩn bị data, xác định optimizer, cách tính loss và tính độ chính xác của mô hình CNN cho training (và validation) data tương tự bài toán phân loại số MNIST.

 

Source code của chương trình cho bài toán phân loại số MNIST như sau

import collections
import numpy as np
import matplotlib.pyplot as plt
import PIL
import tensorflow as tf

from tensorflow.keras.layers import Convolution2D, MaxPooling2D, Flatten, Dense


# data preparation
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train),(x_test, y_test) = cifar10.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

img_rows, img_cols = 32, 32
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 3)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 3)
input_shape = (img_rows, img_cols, 3)


# model architecture
model = tf.keras.models.Sequential([
     # 32x32x3
     Convolution2D(filters=6, kernel_size=(5,5), activation = 'relu', input_shape=input_shape),
     # 28x28x6
     MaxPooling2D(pool_size=(2, 2)),
     # 14x14x6
     Convolution2D(filters=16, kernel_size=(5,5), activation = 'relu'),
     # 10x10x16
     MaxPooling2D(pool_size=(2, 2)),
     # 5x5x16
     Flatten(),
     Dense(128, activation = 'relu'),
     Dense(84, activation = 'relu'),
     Dense(10, activation=tf.nn.softmax)])

model.summary()


# training
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=32, validation_split=0.2, epochs=100, verbose=1)

# testing
print(model.metrics_names)
print(model.evaluate(x_train, y_train, verbose=2))
print(model.evaluate(x_test, y_test, verbose=2))

 

Accuracy qua quá trình huấn luyện

Hình mô tả quá trình huấn luyện ở trên mô tả độ chính xác của mô hình cho bộ dữ liệu training liên tục tăng, nhưng độ độ chính xác cho bộ dữ liệu validation bão hòa và có xu hướng giảm từ epoch thứ 20. Ở đây, vấn đề overfitting đã xuất hiện.

 

Bài tập 1: Tại sao mô hình CNN chúng ta thiết kế ở hai ví dụ trên chạy tốt cho MNIST, nhưng lại hoạt động kém cho Cifar-10.

Bài tập 2: Các bạn thử áp dụng các phương pháp thường dùng để giảm vấn đề overfitting như

  • Dùng các kỹ thuật để tăng data (data augmentation). Tăng training data có khả nằng giảm vấn đề overfitting
  • Dùng Dropout
  • Dùng Batch norm