[Keras/TensorFlow] KerasでMINSTの学習と予測

# 目的
ゼロからKerasとTensorFlow(TF)を自由自在に動かせるようになる。
そのための、End to Endの作業ログ(備忘録)を残す。
※環境はMacだが、他のOSでの汎用性を保つように意識。
※アジャイルで執筆しており、精度を逐次高めていく予定。


# 環境
- Mac: 10.12.3
- Python: 3.6
- TensorFlow: 1.0.1
- Keras: 2.0.2


# To Do
[Keras(Tensorflow)の環境構築](http://qiita.com/agumon/items/4d7826c2c39d0af868bd)
[KerasでMINSTの学習と予測](http://qiita.com/agumon/items/4c6ff24bfd77a5c8101d)<---いまココ
[KerasでTensorBoardの利用](http://qiita.com/agumon/items/114da6921c5dc4f7d7f9) 
[Kerasで重みファイルの保存/読み込み](http://qiita.com/agumon/items/91f897b7f260f6aeca95)
[Kerasで自前データの学習と予測](http://qiita.com/agumon/items/ab2de98a3783e0a93e66) 
[Kerasで転移学習](http://qiita.com/f2um2326/items/60f7bcc8ae26b5004a3a#_reference-5d15f52415912c9c2182)


# 流れ
Kerasのサンプルにあるmnist_mlp.pyを利用してpredictionの練習、結果を混同行列で表示。


# 予測用のスクリプト作成
Kerasのサンプルにあるmnist_mlp.pyを利用。こちらは学習までしか実行しない。
https://github.com/fchollet/keras/blob/master/examples/mnist_mlp.py
そのため、予測の部分を追加する。

以下の予測部分をmnist_mlp.pyの末尾に追加。今回はテスト用データ10個をそのまま予測データとして利用。`model.predict_classes`が肝となるメソッドである。
`true_classes = np.argmax(y_test[1:10],1)`は正解データy_testは[0,1,0...,0]のような形に変換されているため、こちらを0~9の番号に変換し直す。

```py3
# Prediction
import numpy as np
from sklearn.metrics import confusion_matrix

predict_classes = model.predict_classes(x_test[1:10,], batch_size=32)
true_classes = np.argmax(y_test[1:10],1)
print(confusion_matrix(true_classes, predict_classes))
```




予測結果を評価するために混同行列を表示する。

```py3
from sklearn.metrics import confusion_matrix
print(confusion_matrix(true_classes, predict_classes))
```


以下、完全な実行ファイル。実行時間短縮のために`epochs = 2`に変更する。

```py:mnist_mlp_prediction.py
from __future__ import print_function

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop


batch_size = 128
num_classes = 10
epochs = 2

# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))

model.summary()

model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    
                    ## add 1 line
                    callbacks=cbks,
                    
                    validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

# Prediction
import numpy as np
from sklearn.metrics import confusion_matrix

predict_classes = model.predict_classes(x_test[1:10,], batch_size=32)
true_classes = np.argmax(y_test[1:10],1)
print(confusion_matrix(true_classes, predict_classes))

```


# 学習と予測

作成したファイルを実行する。

```
python mnist_mlp_prediction.py
```

学習の実行結果：精度は0.9712とそこそこ良い。

```
Using TensorFlow backend.
60000 train samples
10000 test samples
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 512)               401920    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                5130      
=================================================================
Total params: 669,706.0
Trainable params: 669,706.0
Non-trainable params: 0.0
_________________________________________________________________
Train on 60000 samples, validate on 10000 samples
 
Epoch 1/2
60000/60000 [==============================] - 15s - loss: 0.2423 - acc: 0.9254 - val_loss: 0.1300 - val_acc: 0.9597
Epoch 2/2
60000/60000 [==============================] - 14s - loss: 0.1018 - acc: 0.9691 - val_loss: 0.0975 - val_acc: 0.9693
Test loss: 0.0937810097523
Test accuracy: 0.9712
```

予測の実行結果：すべて正解していることが確認できる。

```
9/9 [==============================] - 0s
[[1 0 0 0 0 0]
 [0 2 0 0 0 0]
 [0 0 1 0 0 0]
 [0 0 0 2 0 0]
 [0 0 0 0 1 0]
 [0 0 0 0 0 2]]
```


# 様々な予測メソッド
今回は`model.predict_classes`を利用したが、Kerasの日本語公式ドキュメントを見ると、他にも種類がある。
https://keras.io/ja/models/sequential/

- predict: 予測値を返す
- predict_classes: クラス(カテゴリ)を返す
- predict_proba: クラス確率を返す


# End