KerasでCNNを簡単に構築


KerasでCNNを構築して，CIFAR-10データセットを使って分類するまでのメモ

## CHANGE LOG
2020/07/12  
* ライブラリをスタンドアロンKeras → Tensorflow.kerasに変更

# インポートするライブラリ
```py3
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPool2D
from tensorflow.keras.optimizers import Adam

from tensorflow.keras.layers import Dense, Activation, Dropout, Flatten
from tensorflow.keras.utils import plot_model, to_categorical
from keras.callbacks import TensorBoard

from keras.datasets import cifar10
```

* Sequential: モデルを生成するためのモジュール
* Conv2d: 2次元畳み込み層のモジュール
* MaxPool2D: 2次元最大プーリング層のモジュール
* Adam: 最適化には，Adamを用いる
* Dense: 全結合層のレイヤモジュール
* Activation: 活性化関数モジュール
* Dropout: ドロップアウトモジュール
* Flatten: 入力を平滑化するモジュール
* plot_model: 構築したモデルを図として出力する
* Tensorboard: 学習過程をTensorboardに保存
* cifar10: CIFAR-10データセットを扱う為のモジュール
* to_categorical: One-Hot表現をするために使用

# データの準備
## CIFAR-10のダウンロード

```py3
(X_train, y_train),(X_test, y_test) = cifar10.load_data()
```

* X_train: 学習データ
* y_train: 学習ラベル
* X_test: テストデータ
* y_test: テストラベル

が格納される．

## 画素値を正規化
各画素値を0-1の範囲で正規化

```py3
# floatに型変換
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
# 各画素値を正規化
X_train /= 255.0
X_test /= 255.0
```

## One-Hot表現に変換
```py3
Y_train = to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
```

np_utils.to_categoricalでnb_classesのクラス分のone-hot表現に変換する.
今回10クラスなので，``nb_classes = 10``とした．

# モデルの定義
実際にモデルを定義していく，

```py3
# モデルの定義
model = Sequential()

model.add(Conv2D(32,3,input_shape=(32,32,3)))
model.add(Activation('relu'))
model.add(Conv2D(32,3))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Conv2D(64,3))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))
model.add(Dropout(1.0))

model.add(Dense(nb_classes, activation='softmax'))

adam = Adam(lr=1e-4)

model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=["accuracy"])
```

model.Sequential()で，モデルオブジェクトを定義．
model.add()で，要素を付け足していくことが可能となる．
最初のmodel.add()で32×32の畳み込み層(カーネル3×3)を追加，さらに，入力画像が32×32のRGB画像なので，入力層として，``input_shape(32,32,3)``で定義することができる．
Activation()で，活性化関数，Dense()で全結合層を追加する．
model.compile()に，最適化手法としてAdam，誤差関数に交差エントロピー，算出するのは精度を取得するように設定する．

# 学習の実行

```py3
history = model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, validation_split=0.1)
```

model.fit()で学習を行うことができる，今回は，エポック数を100にするため``nb_epoch = 100``を設定した．
varidation_splitは，学習データの何割かをテストに使うパラメータ．今回は10%をテストに用いる．

# データの可視化
Kerasでデータを可視化する

```py3
# モデルをプロット
plot_model(model, to_file='./model2.png')
```

# 学習済みモデルの保存
学習済みモデルはファイルとして保存可能なので，JSONファイルでモデル構成データ，HDF5ファイルでモデルの重みデータを保存できる．

```py
json_string = model.to_json()
open(os.path.join('./', 'cnn_model.json'), 'w').write(json_string)

model.save_weights(os.path.join('./', 'cnn_model_weight.hdf5'))
```

今回はバックエンドにTensorflowを用いてるので，以下でTensorboarも使うことができる．
[[Keras/TensorFlow] KerasでTensorBoardの利用](http://qiita.com/agumon/items/114da6921c5dc4f7d7f9)

# まとめ
KerasでCNNを構築して，CIFAR-10で10カテゴリの分類を行った．
ここから，色々試していきます．

# Source Code
https://github.com/sasayabaku/Machine-Learning/blob/master/Example_CNN/cifar10.ipynb

# 参考文献
[Keras Documentation](https://keras.io/ja/)
[KerasではじめるDeepLearning](http://dev.classmethod.jp/machine-learning/introduction-keras-deeplearning/)