C n n Image Classification

Xây dựng CNN model phân loại với tập dữ liệu MNIST

Xây dựng CNN model phân loại với tập dữ liệu MNIST

Trong bài trước, chúng ta đã sử dụng các lớp FC để xây dựng model phân loại các sản phẩm trong tập MNIST thành 10 nhóm khác nhau.

Việc phân loại hình ảnh (trong thực tế)là một nhìệm vụ tương đối phức tạp, nó yêu cầu phải xây dựng các NN model với nhiều lớp. Nếu chỉ sử dụng hoàn toàn FC layer thì sẽ không hiệu quả về cả độ chính xác cũng như hiệu năng của model. Thay vào đó, các lớp CONV, POOL, … được sử dụng thường xuyên hơn.

Yêu cầu cần giải quyết ở bài này vẫn giống như bài trước, chỉ có điều ta sẽ sử dụng các lớp CONV, POOL, … trong thư viện tensorflow xây dựng model phân loại các sản phẩm trong tập MNIST. Môi trường thực hành vẫn giống như các bài trước.

Đầu tiên, như thường lệ ta sẽ import thư viện tensorflow:

import tensorflow as tf

Tiếp đến là hàm callback:

class MyCallback(keras.callbacks.Callback):
   def on_epoch_end(self, epoch, logs={}):
       if logs.get('acc') > 0.99:
           print('Reached to 99%, stop training!')
           self.model.stop_training = True

Nhắc lại là hàm này sẽ được gọi tại thời điểm kết thúc mỗi epoch trong quá trình train model. Nó làm nhiệm vụ kiểm tra độ chính xác của model tại thời điểm đó. Nếu độ chính xác đạt đến 99% thì kết thúc quá trình train.

Hàm load dữ liệu MNIST từ trong tensorflow:

def load_data():
    (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
    x_train = x_train.reshape(-1, 28, 28, 1)
    x_train = x_train/255
    return x_train, y_train

Giờ đến lúc quan trọng nhất của bài này, đó là tạo CNN model:

def create_model():
    model = keras.models.Sequential([
        keras.layers.Conv2D(128, (3,3), activation='relu', padding='same', input_shape=(28,28,1)),
        keras.layers.MaxPooling2D(2,2),
        keras.layers.Conv2D(64, (3,3), activation='relu'),
        keras.layers.MaxPooling2D(2,2),
        keras.layers.Flatten(),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(10, activation='softmax')        
    ])
    model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['acc'])
    return model

CNN model được tạo thành từ các layers: CONV2D, MaxPooling2D, Flatten, Dense, … Tùy thuộc mức độ phức tạp của dữ liệu và yêu cầu của bài toán mà ta sử dụng số lượng và cách thức kết hợp các layers này theo những cách khác nhau. Chi tiết về các common pattern, các rules và các tham số sử dụng khi xây dựng mạng CNN, các bạn có thể đọc thêm tại bài viết trước của mình tại đây.

Ở bài này, chúng tạo một mạng CNN đơn giản theo kiến trúc: [CONV2D => MaxPooling2D]x2 => FLATTEN => DENSEx2.

CNN model sau đó được compile sử dụng thuật toán RMSprop 9cùng với SGD, Adam và RMSprop là 2 thuật toán tối ưu cũng thường hay được sử dụng khi train DL model. Mình dự định sẽ có các bài viết chi tiết về 2 thuật toán này. Mời các bạn đón đọc), hàm loss là sparse_categorical_crossentropy, và metric là accuracy trên tập train.

Có model rồi, đã đến lúc tiến hành train model:

x_train, y_train = load_data()
model = create_model()
history = model.fit(x_train, y_train, epochs=100, callbacks=[MyCallback()], verbose=1)

Model sẽ được train tối đa 100 epochs, hàm callback được truyền vào như 1 tham số để kểm tra điều kiện dừng train của model sau mỗi epoch.

Output:

Epoch 1/100
1875/1875 [==============================] - 14s 7ms/step - loss: 0.1141 - acc: 0.9652
Epoch 2/100
1875/1875 [==============================] - 14s 7ms/step - loss: 0.0406 - acc: 0.9877
Epoch 3/100
1875/1875 [==============================] - ETA: 0s - loss: 0.0318 - acc: 0.9913Reached to 99%, stop training!
1875/1875 [==============================] - 14s 7ms/step - loss: 0.0318 - acc: 0.9913

Rất nhanh, model đạt đến độ chính xác 99% chỉ sau 3 epochs, so với 7 epochs nếu sử dụng hoàn toàn FC layer như bài trước. Với bộ dữ liêu đơn giản như MNIST, 3 epochs hay 7 epochs không có sự khác biệt nhiều về thời gian cũng như độ chính xác. Nhưng nếu dữ liệu rất lớn thì sự khác nhau đó sẽ trở nên rất rõ rệt.

Nếu khi gọi hàm fit() để train model mà gặp lỗi:

UnknownError:  Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
	 [[node sequential/conv2d/Conv2D (defined at <ipython-input-6-04cbaae553c1>:1) ]] [Op:__inference_train_function_856]

thì bạn hãy thêm 3 dòng bên dưới ngay sau khi import tensorflow.

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.InteractiveSession(config=config)

Nguyên nhân lỗi ở đây là do xung đột giữa 2 phiên bản 1.x và 2.x của tensorflow.

Ok, như vậy là chúng ta đã hoàn thành việc xây dựng CNN model để phân loại hình ảnh trong tập dữ liệu MNIST. Tuy đơn giản nhưng đây sẽ là bước đầu để dần dần bạn có thể tự tin tạo ra các CNN model phức tạp hơn, với các tập dữ liệu lớn hơn.

Source code của bài này, các bạn có thể tham khảo trên github cá nhân của mình tại đây.

Trong bài sau, chúng ta sẽ xây dựng một CNN model khác với dữ liệu thực tế hơn. Hãy đón đọc!

Tham khảo