Fashion-MNISTをCNNで学習させて精度を上げてみた

Fashion-MNISTをCNNモデルで学習

こんにちは。

AI coordinatorの清水秀樹です。

前回の記事「TensorFlowでFashion-MNISTを試してみた」で学習モデルを作成した結果、簡単に過学習を起こしていたので、精度を上げるためにCNNで作成した学習モデルで検証してみたので、その結果をソースコードと合わせて紹介したいと思います。

 

開発環境

iMac (27-inch, Late 2012)

プロセッサ 2.9 GHz intel Core i5

macOS Sierra バージョン 10.12.4

Anaconda3-4.2.0-MacOSX-x86_64

python 3.5.2

tensorflow 1.0.0

keras 1.2.2

 

前回の結果との比較

以下、前回のモデル。

多層パーセプトロンでモデルを実装。

def build_model():
    # モデルの作成
    model = Sequential()
    model.add(Dense(512, input_shape=(784,)))
    model.add(Activation('relu'))
    model.add(Dropout(0.2))
 
    model.add(Dense(512))
    model.add(Activation('relu'))
    model.add(Dropout(0.2))
 
    model.add(Dense(10))
    model.add(Activation('softmax'))
 
    # 損失関数の定義
    model.compile(
        loss='categorical_crossentropy',
        optimizer=Adam(),
        metrics=['accuracy'])
    
    return model

その結果は、

 

そして今回作成したCNNモデルは、

def build_model():
    model = Sequential()
    
    #畳み込み層の作成
    #1層目の追加  1024個の層を最初に作り、フィルター3*3のフィルターを32個作成
    model.add(Convolution2D(32, 3, 3, border_mode="same", input_shape=in_shape)) 
    model.add(Activation("relu"))
    
    #2層目の畳み込み層
    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
     #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    
    #Dropoutとは過学習を防ぐためのもの 0.25は次のニューロンへのパスをランダムに1/4にするという意味
    model.add(Dropout(0.5))
    
    #3層目の作成
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #4層目の作成
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    
    #5層目
    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #6層目
    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    
    #平坦化
    model.add(Flatten())
    
    #7 全結合層 FC
    model.add(Dense(100))
    model.add(Activation("relu"))
    
    #Dropout
    model.add(Dropout(0.5))
    
    #8層目 引数nub_classesとは分類の数を定義する。
    model.add(Dense(nub_classes))
    model.add(Activation('softmax'))
    
    #ここまででモデルの層完成
    
    #lossは損失関数を定義するところ
    model.compile(loss="categorical_crossentropy", 
        metrics   = ["accuracy"], 
        optimizer = "adam"
    )
    
    return model

その結果、

うまく学習できているみたい。

 

ソースコード全容

以下、ソースコードの紹介です。

import mnist_reader
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import Adam 
from keras.utils import np_utils

from keras.layers.core import Dense, Activation, Flatten, Dropout
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D

from keras.utils.visualize_util import plot
import matplotlib.pyplot as plt

def build_model():
    model = Sequential()
    
    #畳み込み層の作成
    #1層目の追加  1024個の層を最初に作り、フィルター3*3のフィルターを32個作成
    model.add(Convolution2D(32, 3, 3, border_mode="same", input_shape=in_shape)) 
    model.add(Activation("relu"))
    
    #2層目の畳み込み層
    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
     #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    
    #Dropoutとは過学習を防ぐためのもの 0.25は次のニューロンへのパスをランダムに1/4にするという意味
    model.add(Dropout(0.5))
    
    #3層目の作成
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #4層目の作成
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    
    #5層目
    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #6層目
    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    
    #プーリング層
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    
    #平坦化
    model.add(Flatten())
    
    #7 全結合層 FC
    model.add(Dense(100))
    model.add(Activation("relu"))
    
    #Dropout
    model.add(Dropout(0.5))
    
    #8層目 引数nub_classesとは分類の数を定義する。
    model.add(Dense(nub_classes))
    model.add(Activation('softmax'))
    
    #ここまででモデルの層完成
    
    #lossは損失関数を定義するところ
    model.compile(loss="categorical_crossentropy", 
        metrics   = ["accuracy"], 
        optimizer = "adam"
    )
    
    return model

def plot_history(history):
    # 精度の履歴をプロット
    plt.plot(history.history['acc'],"o-",label="accuracy")
    plt.plot(history.history['val_acc'],"o-",label="val_acc")
    plt.title('model accuracy')
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.legend(loc="lower right")
    plt.show()
 
    # 損失の履歴をプロット
    plt.plot(history.history['loss'],"o-",label="loss",)
    plt.plot(history.history['val_loss'],"o-",label="val_loss")
    plt.title('model loss')
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.legend(loc='lower right')
    plt.show()

if __name__ == "__main__":
    # Fashion-MNISTのデータの読み込み
    # 訓練データ6万件、テストデータ1万件
    # 28ピクセル × 28ピクセル
    X_train, y_train = mnist_reader.load_mnist('data/fashion', kind='train')
    X_test, y_test = mnist_reader.load_mnist('data/fashion', kind='t10k')
    
    X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32')
    X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype('float32')
    in_shape = (28, 28, 1)
    nub_classes = 10

    X_train /= 255
    X_test  /= 255

    # 10次元配列に変換 //数字の5ならこんな感じ[0,0,0,0,1,0,0,0,0,0]
    y_train = np_utils.to_categorical(y_train, 10)
    y_test  = np_utils.to_categorical(y_test, 10)
    
    print('X_train shape:', X_train.shape)
    print(X_train.shape[0], 'train samples')
    print(X_test.shape[0], 'test samples')

    # データで訓練 今回は時間省略のため2回で学習する
    model = build_model()
    history = model.fit(X_train, y_train, 
        nb_epoch=50, #学習させる回数 今回は2 回数はお好みで pytyonのnb_epochとはrangeの繰り返しのこと
        batch_size=128, #無作為に128画像取得している。数字はなんでも良い
        validation_data=(X_test, y_test)
    )

    #学習モデルの保存
    json_string = model.to_json()
    #モデルのファイル名 拡張子.json
    open('mnist.json', 'w').write(json_string)
    #重みファイルの保存 拡張子がhdf5
    model.save_weights('mnist.hdf5')

    # モデルの評価を行う
    score = model.evaluate(X_test, y_test, verbose=1)

    print('loss=', score[0])
    print('accuracy=', score[1])
    
    # modelに学習させた時の変化の様子をplot
    plot_history(history)

 

nb_epoch = 50 で学習しています。

以下、結果です。

Epoch 48/50
60000/60000 [==============================] - 252s - loss: 0.2053 - acc: 0.9248 - val_loss: 0.1781 - val_acc: 0.9341
Epoch 49/50
60000/60000 [==============================] - 253s - loss: 0.2050 - acc: 0.9249 - val_loss: 0.1797 - val_acc: 0.9340
Epoch 50/50
60000/60000 [==============================] - 252s - loss: 0.2046 - acc: 0.9254 - val_loss: 0.1794 - val_acc: 0.9377
 9984/10000 [============================>.] - ETA: 0sloss= 0.17943021461
accuracy= 0.9377

前回よりは良いようです。

もっと良い学習モデルがあれば是非教えてください。

 

また、これからDeep Learningの勉強をするなら、こちらで紹介する書籍も参考になりますので一読してみることをオススメします。

 

 

それではまた。

あなたにオススメの記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

PAGE TOP