無から始める Keras のもくじはこちら
今回から Keras のバージョンが 2.0.5 になったけど多分何も問題ないはず。
前回までのおさらい
前回までは Keras を使って 2 クラス分類をした。
MNIST
機械学習を触ったことがある人なら誰でも聞いたことがあるデータセット。
Modified National Institute of Standards and Technology database の略。
モノクロ画像に 0 から 9 の数字が書いてあって、画像からどの数字かを認識するのが目的。
28×28 pixel、8bit モノクロ。当然ラベル付き。
訓練データは 60000 個、テストデータは 10000 個。
公式サイトはここ。各手法によるエラーレートの記録も載っている。
これを見るとニューラルネットワークが別に特別すごいわけではないと感じるよな。
Keras にはデフォルトでこの MNIST が使えるようになっている。便利。
MNIST を認識してみる
とりあえず普通のネットワークで学習してみよう。
データの読み込み
Keras の MNIST データは、各ピクセルが 0 以上 255 以下の整数になっている。
これだと扱いにくいので、255.0 で割って 0 から 1 の間に収める。
また 2 次元データ(データ方向を含めれば 3 次元)になっているので、reshape によってそれぞれ 1 次元(データ方向を含めれば 2 次元)にしている。
reshape はデータの順番と総数をそのままに、配列の形だけ変える関数。
ラベルの方は 0 から 9 までの整数の配列になっているが、こちらもワンホットになるように変形する。
たとえば 7
であれば [0,0,0,0,0,0,0,1,0,0]
になるようにする。
なお y_test
はそれをする必要がないので省略。
mnist.load_data()
をするときにデータをダウンロードするかもしれない。
from keras.datasets import mnist
from keras.utils import np_utils
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784) / 255.0
x_test = x_test.reshape(10000, 784) / 255.0
y_train = np_utils.to_categorical(y_train, num_classes=10)
モデルの設定
ネットワークのモデルを作る。ここでは 784-1300-10 の 2 層ニューラルネットワークを作る。
層の数え方は色々な流派があるが、無 Keras では「前の層からのデータを受け取って何らかの処理(活性化関数をかけるなど)をする」ところまでを 1 層と数える。なので入力層は層と数えない。
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
model = Sequential([
Dense(1300, input_dim=784, activation='relu'),
Dropout(0.4),
Dense(10, activation='softmax')
])
model.compile('adam', 'categorical_crossentropy', metrics=['accuracy'])
Dropout はドロップアウトレイヤー。
Keras では、1 つ前のレイヤー(今回であればノードが 1300 ある Dense レイヤー)のノードのうち、指定した割合(今回であれば 40%)のノードをランダムに選んで出力を 0 にする。
こうすることで過学習を防ぐ効果がある。
学習
from keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_acc')
model.fit(x_train, y_train, batch_size=100, validation_split=0.2, callbacks=[es])
EarlyStopping
ここでは新しく EarlyStopping というものを用いる。
適当なところで学習を自動で止めて過学習を防止できる。
monitor には何を観測対象とするかを指定する。
val_acc
(バリデーションの正確性)を選んでいるが、val_loss
(バリデーションの損失)の方が一般的(?)。
バッチサイズ
上の fit
の引数にある batch_size
の値。
バッチサイズとは 1 回に計算するデータの数のこと。
全学習データ数と等しい、つまりこの例では 48000 個でも構わない(バリデーションで 20% が切られている)。
バッチサイズを小さくする、たとえば 100 個とかにすると、1 回の計算で 100 個しか扱わないので、全体でこの場合 480 回計算することになる。この 480 回の計算 1 まとまりのことをエポックと呼んでいる。またデータ数よりもバッチサイズがかなり小さい場合はミニバッチ(学習)と呼ぶ。
ちなみにバッチサイズが 1 のときは stochastic と呼んでいる(日本ではあまり馴染みのない言い方みたい)。
バッチサイズを小さくすることで、使用するメモリ量が少なくなる。
また 1 エポックあたりのパラメータ更新回数が増えるので、収束も速くなる。
ただし、バッチサイズを小さくしすぎるとパラメータが暴れてしまうという欠点がある。
したがって、バッチサイズはいい感じに選ぶ必要がある。
ちなみにバッチサイズを指定しないときは、全データの数になる。
テスト
predict = model.predict_classes(x_test)
print(sum(predict == y_test) / 10000.0)
98% くらいの正解率が出るはず。
predict_classes
はクラス予測をするやつ。
今回のプログラムまとめ
ドロップアウト率やバッチサイズなどのパラメータもいじってみてね。
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.callbacks import EarlyStopping
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784) / 255.0
x_test = x_test.reshape(10000, 784) / 255.0
y_train = np_utils.to_categorical(y_train, num_classes=10)
model = Sequential([
Dense(1300, input_dim=784, activation='relu'),
Dropout(0.4),
Dense(10, activation='softmax')
])
model.compile('adam', 'categorical_crossentropy', metrics=['accuracy'])
es = EarlyStopping(monitor='val_acc')
model.fit(x_train, y_train, batch_size=100, validation_split=0.2, callbacks=[es])
predict = model.predict_classes(x_test)
print(sum(predict == y_test) / 10000.0)
本当は今回 CNN を扱って、上で示したものと性能比較をしようと思ったけれど、長くなってしまったので次回にすることにしました。次回こそやります。