DeepLearningのブームのきっかけとなったAlexNetを使用してcifar10の画像分類をしてみたので忘備録として記録を残します。
cifar10について知りたい人は以下の記事で使用方法などを書いているのでそちらをご覧ください。
AlexNetは2012年のILSVRCにおいて従来の画像分類手法に対して大差をつけて優勝した手法である。
AlexNetにより画像分類における深層学習の有効性が示され、深層学習のブームがおきた。
現在でも画像分類モデルのベースラインとして利用されることが多々ある。
AlexNetのモデルの構造は上手のようになっている、5層の畳み込み層、3層のプーリング層、3層の全結合層からできている。
AlexNetでは活性化関数が従来使用されてきたtanhではなくReLUが使用されている。ReLUを使用することでtanhに比べて学習を高速化することができている。
また、過学習を抑制するために隠れ層のニューロンを無効化するDropoutもAlexNetでは使用されている。
モデルは先ほどのAlexNetの図を参考に作成しました。
畳み込み層 ー>プーリング層 ー>畳み込み層 ー>プーリング層 ー>畳み込み層 ー>畳み込み層 ー>畳み込み層 ー>プーリング層 ー>全結合層 ー>全結合層という構成になっています。
100epoch学習させてみた結果以下のような結果になりました。
テストデータに対する精度は80%ほどまで向上しました。パラメータのチューニングをせずにここまでの精度が出るなんてさすがという感じです。
前回行ったLeNetでは精度が65%ほどでしたので、それと比べてもAlexNetの性能の良さが分かります。
最後に、今回作成したソースコードを以下にのせておきます。
cifar10について知りたい人は以下の記事で使用方法などを書いているのでそちらをご覧ください。
AlexNetとは
AlexNetは2012年のILSVRCにおいて従来の画像分類手法に対して大差をつけて優勝した手法である。
AlexNetにより画像分類における深層学習の有効性が示され、深層学習のブームがおきた。
現在でも画像分類モデルのベースラインとして利用されることが多々ある。
AlexNetのモデルの構造は上手のようになっている、5層の畳み込み層、3層のプーリング層、3層の全結合層からできている。
AlexNetでは活性化関数が従来使用されてきたtanhではなくReLUが使用されている。ReLUを使用することでtanhに比べて学習を高速化することができている。
また、過学習を抑制するために隠れ層のニューロンを無効化するDropoutもAlexNetでは使用されている。
実装
# AlexNetの論文を参考して作成したモデル
def CreateAlexNet(input_shape, num_classes):
model=Sequential()
model.add(Conv2D(filters=96, kernel_size=3, strides=(1, 1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='zeros'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=256, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=384, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='zeros'))
model.add(Conv2D(filters=384, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(Conv2D(filters=256, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(4096, activation='relu', bias_initializer='ones'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu', bias_initializer='ones'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
return model
モデルは先ほどのAlexNetの図を参考に作成しました。
畳み込み層 ー>プーリング層 ー>畳み込み層 ー>プーリング層 ー>畳み込み層 ー>畳み込み層 ー>畳み込み層 ー>プーリング層 ー>全結合層 ー>全結合層という構成になっています。
学習結果
100epoch学習させてみた結果以下のような結果になりました。
テストデータに対する精度は80%ほどまで向上しました。パラメータのチューニングをせずにここまでの精度が出るなんてさすがという感じです。
前回行ったLeNetでは精度が65%ほどでしたので、それと比べてもAlexNetの性能の良さが分かります。
最後に、今回作成したソースコードを以下にのせておきます。
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPool2D
from keras.layers.core import Dense, Flatten, Dropout
from keras.layers.normalization import BatchNormalization
from keras.datasets import cifar10
from keras.utils import np_utils
from keras import optimizers
import matplotlib.pyplot as plt
# AlexNetの論文を参考して作成したモデル
def CreateAlexNet(input_shape, num_classes):
model=Sequential()
model.add(Conv2D(filters=96, kernel_size=3, strides=(1, 1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='zeros'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=256, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=384, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='zeros'))
model.add(Conv2D(filters=384, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(Conv2D(filters=256, kernel_size=3, strides=(1,1), padding='same', input_shape=input_shape, activation='relu', bias_initializer='ones'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(4096, activation='relu', bias_initializer='ones'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu', bias_initializer='ones'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
return model
# 学習の様子を可視化
def ShowTrainData(history):
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.subplot(1,2,2)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
def main():
# cifer10をダウンロード
(x_train,y_train),(x_test,y_test)=cifar10.load_data() # 32×32×3の配列
# 画像を0から1の範囲で正規化
x_train = x_train.astype('float32') # float32に変換
x_train = x_train/255; # 0~1の値に変換するために255で割る(cifer10は0-255のRGBで表現されている)
x_test = x_test.astype('float32')
x_test = x_test/255;
# 正解ラベルをone-hot表現に変換
y_train = np_utils.to_categorical(y_train, 10)
y_test = np_utils.to_categorical(y_test, 10)
#モデルを構築
model = CreateAlexNet(x_train[0].shape, 10)
sgd = optimizers.SGD(lr=0.01)
model.compile(optimizer='SGD',loss='categorical_crossentropy',metrics=['accuracy'])
batch_size = 128;
epoch = 100;
history=model.fit(x_train,y_train,batch_size=batch_size,nb_epoch=epoch,verbose=1,validation_split=0.1)
ShowTrainData(history)
if __name__ == '__main__':
main()