LoginSignup
45
45

More than 5 years have passed since last update.

無から始めるKeras 第5回

Last updated at Posted at 2017-07-23

無から始める 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 を扱って、上で示したものと性能比較をしようと思ったけれど、長くなってしまったので次回にすることにしました。次回こそやります。

45
45
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
45