Python + Keras で復習するディープラーニング 

# はじめに
業務では半年程度・プライベートな開発に至って一年ほど、Pythonと機械学習から離れていました。
そして久しぶりにプライベートな開発でディープラーニングを組み込んだアプリケーションを開発しようと思いたったのですが、、、
いざやろうとすると、かなり忘れていたのでそのリハビリとしてKerasでの基本的なモデルを作って内容について書き残したいと思います。

## 対象
基本的にはある程度ディープラーニングについて知識がある方向けになります。
ですが一応全く知らない人でも多少調べながら読めばわかるかな？という感じの内容かと思います。

- ディープラーニングを復習したい方
- Kerasのサンプルをみたい方
- Kerasの使い方を知りたい方

## そもそもディープラーニングってなんだっけ？
簡単に言えば多層構造のニューラルネットワークのことです。
ニューラルネットワークは入力された値に対して、層の数だけ処理を繰り返します。
この各層での処理が終わった後に出てくる値（出力値）が「どれだけ正解の値と近いか」がいわゆる精度と呼ばれるものです。
様々なパターンの入力値と出力値の組み合わせを教えることにより、各層で行われる処理を調整していき、最終的には未知の入力値からそれにふさわしい出力値を導き出すことが主目的です。

## Keras実行環境の準備
インストールにはPythonのパッケージ管理ツールとして使用されているpipを使います。
Pythonの開発環境が構築されていれば、pipもインストールされているはずです。

```
pip install keras
```
[Keras Installation](https://keras.io/ja/#_2)

また今回はPythonのIDEとして[Jupyter notebook](Jupyter Notebook
https://jupyter.org/)を使っていきます。

## さっそくコードを書いてみる（MNIST分類）
MNISTとは0 ~ 9の手書き数字の画像集のことです。
画像に写っている数字がどの0 ~ 9の値のうちどの数字なのかを分類できるモデルを構築していきます。

内容はほとんどkerasが提供しているサンプルコードと同じです。
https://github.com/keras-team/keras/blob/master/examples/mnist_mlp.py

### 1. はじめに必要なmoduleをimport

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

### 2. モデルに学習させる際の設定を定義しておく

```python
batch_size = 120
num_classes = 10
epochs = 5
```

- batch_size
一回の学習にどのくらいのデータを与えるか。今回であれば120なので、120組のデータを与えてその結果から各層での処理を調整することになる。

- num_classes
最終的に何個の値を出力させるか。今回であれば0 ~ 9の数字のどれに当てはまるかを知りたい。今回は0 ~ 9までの計10種に対して、それぞれにあてはまる確率がどのくらいなのかを最終的に出力させる。

- epochs
データセットを何回あたえるか。ディープラーニングで用意したデータを何回も与えて調整を繰り返すのが一般的である。今回は5なので、用意したデータを5回与えて調整を繰り返すということになる。

### 3. データをロード&前処理

```python
(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')

# 入力データのrgbaスケールを0 ~ 1に
x_train /= 255
x_test /= 255

# 正解データを数値 → 確率が格納されたlistへ
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
```
データのロードはkerasが用意していくれいているロード用メソッドで簡単にできる。

前処理に関して

- 入力データの二次元配列化
元データは（画像数, 画像縦pixel数, 画像横pixel数）の三次元配列である。これを二次元配列化する。

- 入力データの型変換 
Kerasが計算処理する際に使う浮動小数点数型にデータを変換しておく必要があるため処理が必要。

- 入力データのrgbaスケールを0 ~ 1に 
機械学習では入力される値のスケールによって精度が変化するアルゴリズムも多い。ディープラーニングで扱われるニューラルネットワークもそのうちの1つ。スケールを小さくすることにより極端な学習結果になることを防ぐことができる。

- 正解データを数値 → 確率が格納されたlistへ
元データは対応する画像がどの数値なのかということが格納されているだけである。今回は最終的な出力結果をそれぞれにあてはまる確率がどのくらいなのかを最終的に出力させる。そのためには正解データも同様の形式にしておく必要があるため処理が必要。

### 4. モデルの定義
```python
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784, )))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy',
                          optimizer=RMSprop(),
                          metrics=['accuracy'])
```
モデル(Sequential)を定義して、層（Dense・Dropout）を追加していく。
最後にcompileメソッドでモデルの学習に使う手法を決定しモデルの構築を完了する。

- Dense

引数には、層のノード数, 活性化関数の種類、入力値のshape（最初の層のみ）を与える。
今回は、1・2層目はノード数512, 活性化関数relu関数, 縦横(28 x 28 = 784)のデータを入力として与えるため(784, )
最終層は、カテゴリー総数にする必要があるのでノード数10, 活性化関数softmaxは値を確率にしてくれる。

- Dropout

これを追加することで引数に与えた確率でランダムにノードが消滅する。
複雑なモデルに発生しやすい過学習を防ぐことができる。

- compile

損失関数（loss）と各層のノード係数を最適化する手法(optimizer)を指定する。
引数metricsは結果を評価する手法をlist指定する。
今回はaccuracy=正解値とと出力値を比較して正解率を決定する手法を用いる。

### 5. 学習と精度の確認

```python
model.fit(x_train, y_train,
                 batch_size=batch_size,
                 epochs=epochs,
                 verbose=1,
                 validation_data=(x_test, y_test))

score = model.evaluate(x_test, y_test, verbose=0)
print(score) ## →　[0.071611297502644444, 0.98050000000000004]
```
最後にfitメソッドで訓練データや各種設定値を決めて訓練させる。
evaluateメソッドで精度測定。
今回は正解率が`0.98050000000000004 = 約98.05%`だった。


## まとめ
公式で公開されているような簡単なサンプルでしたが、ひさしぶりに書いてみるとやはり色々忘れていたことを改めて実感しました。
特に各パラメーターの意味をしっかり見直せたのがとても有益だったかなという印象です。
ただ今実現したいモデルを作るにはまだまだ他の手法も見直していきたいですね。
おそらくLSTMをそちらでは使うことになると思うので次はLSTMの復習でもしようかと思います。