MLP(多層パーセプトロン)のアルゴリズムを利用してMNISTの分類
# MLPでMNISTの分類問題に挑戦
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
from keras.datasets import mnist
import matplotlib.pyplot as plt
# 入力と出力を指定
in_size = 28 * 28
out_size = 10
# MNISTのデータを読み込み --- (*1)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# データを28*28=784の一次元配列に変換
X_train = X_train.reshape(-1, 784).astype('float32') / 255
X_test = X_test.reshape(-1, 784).astype('float32') / 255
# ラベルデータをone-hotベクトルに直す
y_train = keras.utils.to_categorical(y_train.astype('int32'),10)
y_test = keras.utils.to_categorical(y_test.astype('int32'),10)
# MLPモデル構造を定義 --- (*2)
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(out_size, activation='softmax'))
# モデルをコンパイル --- (*3)
model.compile(
loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
# 学習を実行 --- (*4)
hist = model.fit(X_train, y_train,
batch_size=128,
epochs=50,
verbose=1,
validation_data=(X_test, y_test))
# モデルを評価 --- (*5)
score = model.evaluate(X_test, y_test, verbose=1)
print('正解率=', score[1], 'loss=', score[0])
# 学習の様子をグラフへ描画 --- (*6)
# 正解率の推移をプロット
plt.title('Accuracy')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# ロスの推移をプロット
plt.title('Loss')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
実行結果
MLPとは
MLPとは多層パーセプトロン(multilayer perceptron)のことで、特徴としては入力層からデータを入力した後、複数の隠れ層を経て出力層に出力される。これをkerasで表すと
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(out_size, activation='softmax'))
model.add()メソッドを用いて、複数の隠れ層を追加していくことでMLPの特徴を反映している。
MNISTデータの読み込みと一次元の配列に変換
in_size = 28 * 28
out_size = 10
# MNISTのデータを読み込み --- (*1)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# データを28*28=784の一次元配列に変換
X_train = X_train.reshape(-1, 784).astype('float32') / 255
X_test = X_test.reshape(-1, 784).astype('float32') / 255
# ラベルデータをone-hotベクトルに直す
y_train = keras.utils.to_categorical(y_train.astype('int32'),10)
y_test = keras.utils.to_categorical(y_test.astype('int32'),10)
モデルの構造を定義
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(out_size, activation='softmax'))
今回ではmodel.add()でDropout()関数を使用していて、これはドロップアウト処理を加えるもの。ドロップアウトというのは入力値のうちいくらかをランダムに0にセットする機能。つまり、覚えたことを忘れることを意味するが、これにより過学習を防ぐことができる。そして、学習精度が上がる。Dropout(0.2)では20%の出力値がランダムに0に置き換わる。
モデルコンパイル
model.compile(
loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
optimizer(最適化関数)にはRMSprop()を指定しているが、Dropout()関数を使用するときはこれを使った方がいいのかな?わからなかった。
学習の実行
hist = model.fit(X_train, y_train,
batch_size=128,
epochs=50,
verbose=1,
validation_data=(X_test, y_test))
model.fitのパラメーターにvalidation_dataという配列で評価データを与えるとmodel.fitの返り値のhistoryオブジェクトにepoch毎の訓練データでの評価とvalidation_dataでの評価とそれぞれの結果を残してくれる。
モデル評価
score = model.evaluate(X_test, y_test, verbose=1)
print('正解率=', score[1], 'loss=', score[0])
正解率の推移をプロット
plt.title('Accuracy')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
ロスの推移をプロット
plt.title('Loss')
plt.legend(['train', 'test'], loc='upper left')
plt.show()