無から始めるKeras 第5回

無から始める Keras のもくじは[こちら](http://qiita.com/Ishotihadus/items/6ecf5684c2cbaaa6a5ef)

今回から Keras のバージョンが 2.0.5 になったけど多分何も問題ないはず。

# 前回までのおさらい

[前回](http://qiita.com/Ishotihadus/items/ca8cc2e7b5b14ed51a2f)までは Keras を使って 2 クラス分類をした。

# MNIST

機械学習を触ったことがある人なら誰でも聞いたことがあるデータセット。
Modified National Institute of Standards and Technology database の略。

モノクロ画像に 0 から 9 の数字が書いてあって、画像からどの数字かを認識するのが目的。

28×28 pixel、8bit モノクロ。当然ラベル付き。
訓練データは 60000 個、テストデータは 10000 個。

公式サイトは[ここ](http://yann.lecun.com/exdb/mnist/)。各手法によるエラーレートの記録も載っている。
これを見るとニューラルネットワークが別に特別すごいわけではないと感じるよな。

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()` をするときにデータをダウンロードするかもしれない。

```py3
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 層と数える。なので入力層は層と数えない。

```py3
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 にする。
こうすることで過学習を防ぐ効果がある。

## 学習

```py3
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 エポックあたりのパラメータ更新回数が増えるので、収束も速くなる。
ただし、バッチサイズを小さくしすぎるとパラメータが暴れてしまうという欠点がある。
したがって、バッチサイズはいい感じに選ぶ必要がある。

ちなみにバッチサイズを指定しないときは、全データの数になる。

## テスト

```py3
predict = model.predict_classes(x_test)
print(sum(predict == y_test) / 10000.0)
```

98% くらいの正解率が出るはず。

`predict_classes` はクラス予測をするやつ。

# 今回のプログラムまとめ

ドロップアウト率やバッチサイズなどのパラメータもいじってみてね。

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