Skip to content

[Keras] 使用 CNN 建立 Cifar-10 的分類器 (實戰篇)

Last Updated on 2021-04-11 by Clay

Cifar-10 與 MNIST 相同,是一個有著 60000 張圖片的資料集(MNIST 的部份可以參考《使用 CNN 進行 MNIST 的手寫數字辨識 —— by Keras (實戰篇)》,與這篇的程式碼應該是大同小異。)

不同之處在於 Cifar-10 是 32 x 32 大小的 RGB 彩色圖片,訓練分類器比起 MNIST 更是難上不少。目前世界紀錄似乎才96.53 %,比 MNIST 明顯來得低,模型也更複雜。

同樣地,分成 50000 張 Training data、以及 10000 張 Test data。

當然,這不會是最難的 Toy dataset。事實上,光是擁有 100 種分類物件的 Cifar-100 便難上不少。

廢話不多說,馬上來看看程式碼吧!


事前準備

如果是沒有 GPU 的人,可以考慮使用 Google 免費提供的 GPU 線上平台 Google Colab。(使用 GPU 的教學請看這篇:《如何使用 Google Colab 提供的免費 GPU》


程式碼

import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

from keras.models import Sequential, load_model
from keras.datasets import cifar10
from keras.utils import np_utils,plot_model
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D


首先,老樣子,import 進所有我們會用到的套件。

(X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
x_train = X_train.astype('float32')/255
x_test = X_test.astype('float32')/255
y_train = np_utils.to_categorical(Y_train)
y_test = np_utils.to_categorical(Y_test)


這裡是資料集的準備,在這裡同樣使用 keras.datasets 底下直接收錄的 Cifar-10 資料集。前處理的方式與 MNIST 相仿,同樣分成 Training data 以及 Test data,然後圖片的資訊以及 Label 也分開,分別傳入四個變數。

model = Sequential()
model.add(Conv2D(filters=64, kernel_size=3, input_shape=(32, 32, 3), activation='relu', padding='same'))
model.add(Conv2D(filters=64, kernel_size=3, input_shape=(32, 32, 3), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=2))

model.add(Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'))
model.add(Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=2))

model.add(Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'))
model.add(Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=2))

model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(rate=0.25))
model.add(Dense(10, activation='softmax'))


模型比 MNIST 時複雜不少。在這裡我們使用了多層的 CNN,其實也是 Try,然後碰巧發現這個簡單的模型可以獲得相對好一點的效果。

如果使用複雜的模型可以獲得較好的 Accuracy,大家不妨自己研究一下,任意地使用自己想用的模型層。

print(model.summary())


指令可以印出現在我們訂製好的模型層概覽,大致上長這樣:

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10, batch_size=64, verbose=1)


然後,我們開始訓練這個模型。

loss, accuracy = model.evaluate(x_test, y_test)
print('Test:')
print('Loss:', loss)
print('Accuracy:', accuracy)


測試模型的效果。我的模型顯示出:

10000/10000 [==============================] - 3s 259us/step
Test:
Loss: 0.8153500760555268
Accuracy: 0.7908

我的 Accuracy 與你的不同是很正常的。不同的 start point 找到不同的 local optimal。


補述

『保存模型』、『讀取模型』、『顯示圖片』等等的功能可以參閱我之前所撰寫的 《使用 CNN 進行 MNIST 的手寫數字辨識 —— by Keras (實戰篇)》 ,使用方法基本上都是一樣的,在此便不再贅述了。

希望大家都能有好的訓練結果、不只這個 Toy dataset、任何模型都是!

Leave a Reply