こんにちは!
サラリーマンブロガーのみやしんです。
今の世の中、Pythonをはじめプログラミングがとても注目を集めているのは言うまでもない事実と思います。私もプログラミングはちょこちょこやるのですが、折角なのでやったことをブログに残して誰かのお役に立てたらいいな~と思うようになりました。
MLP(Multilayer perceptron:多層パーセプトロン)を用いて、FashionMNISTの分類器を実装しました。
通常、テストデータで大体Accuracy0.880くらいにはなると思うのですが、Accuracy 0.912とまずまずの結果を残せましたので、メモの意味も込めてブログに残しておきたいと思います。
学校の課題などでFashionMNISTを学習することがある方など、ご参考にしていただけたらと思います。
色々なパラメータを振ったりして120通りの検証を行い、一番Accuracyが良かったものをご紹介します。
以下、コードになります。
Code (FashionMNIST MLPにて学習)
%matplotlib inline
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import layers
import matplotlib.pyplot as plt
from tensorflow.keras.layers import PReLU
from tensorflow.keras.initializers import Constant
# データの読み込み用(特に変更する必要はありません)
def load_mnist():
# 学習データ
をload
x_train = np.load('/***/*****/****/****/****/****/x_train.npy')
y_train = np.load('/***/*****/****/****/****/****/y_train.npy')
# テストデータ
をload
x_test = np.load('/***/*****/****/****/****/****/x_test.npy')
# グレースケール画像(0~255)を最小値0、最大値1に正規化する
x_train = x_train / 255.
x_test = x_test / 255.
return (x_train, x_test, y_train)
x_train, x_test, y_train = load_mnist()
# データの水増し
# 0.9を掛けて色味を濃くする
x_train_deep = x_train * 0.9
# 0.1を足して1.1で割ることで全体的に白みのかかった画像にする
x_train_light = (x_train + 0.1) / 1.1
# 画像を反転する
x_train_reverse = x_train[:,:,::-1]
# モデルの「容器」を作成
model = tf.keras.models.Sequential()
# 「容器」へ各layer(Flatten, Dense, Activation)を積み重ねていく(追加した順に配置されるので注意)
# 最初のlayerはinput_shapeを指定して、入力するデータの次元を与える必要がある
model.add(layers.Flatten(input_shape=(28, 28)))
model.add(layers.Dense(units=512, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dense(units=256, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dense(units=128, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dense(units=64, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dropout(0.3))
model.add(layers.Dense(units=48, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dropout(0.3))
model.add(layers.Dense(units=32, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dense(units=10))
model.add(layers.Activation('softmax'))
# amsgradを使って学習
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0, amsgrad=True), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 変わったやり方
# 水増し画像と通常の学習画像を順番に学習させた。
# EarlyStoppingを掛けているがepoch=1なのでストップしない。検証用に入れている。
for i in range(19):
if i<=18:
print("N=",i+1,"回目")
history = model.fit(x_train_deep, y_train, batch_size= 4, epochs=1, validation_split=0.01, shuffle=True, callbacks=tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto'))
history = model.fit(x_train_light, y_train, batch_size= 4, epochs=1, validation_split=0.01, shuffle=True, callbacks=tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto'))
history = model.fit(x_train_reverse, y_train, batch_size= 4, epochs=1, validation_split=0.01, shuffle=True, callbacks=tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto'))
history = model.fit(x_train, y_train, batch_size= 4, epochs=1, validation_split=0.01, shuffle=False, callbacks=tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto'))
# テストデータの予測
y_pred = model.predict(x_test)
# 予測結果を確率値から0-9のラベルに変換
y_pred = np.argmax(y_pred, axis=1)
# pandas形式に変換
submission = pd.Series(y_pred, name='label')
# csvファイルの出力先は適宜変更
submission.to_csv('/***/*****/****/****/****/****/*****.csv', header=True, index_label='id')
Optimizerの検証
今回、Optimizerがどれを選べば良いのかトライ&エラーで検証した結果、Amsgradが最もAccuracyが高い結果となりました。検証したOptimizerはこんな感じです。
Optimizer | Accuracy |
Amsgrad | 0.901 |
Adam | 0.885 |
Adamax | 0.887 |
Nadam | 0.893 |
Adabound | 0.895 |
検証した中ではAmsgradが最もよかったです。Adaboundが一番新しい手法なので期待していましたが、思ったほど良くなかったです。
活性化関数の検証
活性化関数はReLUとPReLUを試しました。やはりこの2つだとPReLUの方が僅かですが良い結果となりました。
活性化関数 | Accuracy |
ReLU | 0.901 |
PReLU | 0.904 |
白黒を反転
白黒を反転させたらどうなるか検証しました。(x_train – 255) * (-1)のような感じで白黒を逆にしました。
色 | Accuracy |
そのまま | 0.904 |
白黒反転 | 0.895 |
色を反転するとAccuracyが下がりましたので、そのままにすることにしました。
一層追加
MLP構造を一層追加してみるとAccuracyが良くなりました。追加した層は下記の層です。model.add(layers.Dense(units=48, kernel_initializer='he_normal'))
model.add(PReLU(alpha_initializer=Constant(value=0.25)))
model.add(layers.Dropout(0.3))
何となく過学習気味な気がしていたので、Dropoutも一緒に加えています。
こうすることで、
MLP構造 | Accuracy |
そのまま(7層) | 0.904 |
一層追加(8層) | 0.912 |
のようにAccuracyを良くすることができました。
その他の検証
その他にも下記のパラメータを色々振ってみて、トライ&エラーした中で最も良い数字を置いています。
- 学習率 = 0.001
- batch_size = 4
- Dropout率 = 0.3
- validation_split = 0.01
- epsilon = 1e-08
- beta_1 = 0.9
- beta_2 = 0.999
- decay = 0.0
以上となります。
最後まで読んで頂き、ありがとうございました!
コメント