CNNでの画像分類---赤ちゃんの泣き顔と笑顔

#About
・CNNを使って赤ちゃんの泣き顔と笑顔を分類
・Keras





#データセット作り
・ディープラーニングではデータ数が多い方が精度が良くなる
　訓練データ    10000枚    (cry 5000枚 : smile 5000枚)
　検証データ     2000枚　  (cry 1000枚 : smile 1000枚)
　テストデータ   3400枚    (cry 1700枚 : smile 1700枚)

###インスタグラムでダウンロード
今回は「crying baby」、「smiling baby」、「泣き顔」等でタグ検索すればOK
右クリック　→　名前を付けて保存　→　ファイルの種類を（ウェブページ、完全）にする
上記の方法でダウンロードすれば、一度に数十枚ダウンロードできて時短
詳細は下記の記事
https://qiita.com/Phoeboooo/items/7af7412fcbf890e9c9e5


#データセットを整える
ダウンロードした画像の中から必要のない画像は削除する
（関係のない画像、画質が悪すぎる、わかりづらい等）

ここまで来れば下準備はOK、コードをつくっていきましょう


#モデルづくり
＊　ここからは先にコードを書いて、そのあとにコードの解説という流れで説明していきます。

```python

from keras import layers
from keras import models
from keras import optimizers
from keras.layers import GlobalAveragePooling2D


model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])

model.summary()
```

Total params: 244,993
Trainable params: 244,993
Non-trainable params: 0

・過学習を抑えるためにパラメーターが少ないモデルを選択
　(今回はこのモデルが適していたが、万能ではありません）
・GlobalAveragePooling2Dを使うことでシンプルなモデルを作れる



#画像をディレクトリから読み込む
```python

from keras.preprocessing.image import ImageDataGenerator

train_dir = 'Downloads/baby/train'
validation_dir = 'Downloads/baby/validation'

# rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # directory
        train_dir,
        # resized to 150x150
        target_size=(150, 150),
        batch_size=50,
        # binary labels
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=50,
        class_mode='binary')
```

##ImageDataGenerator

・指定したディレクトリから指定したサイズでバッチサイズ分のデータを「際限なく」出し続ける
　今回では、「train_dir」から「150×150の画像サイズ」で「50枚1セット」で画像を引き出している
・「class_mode='binary'」は二値分類用のラベルを作ってね、ということ
・このジェネレーターをいつ止めるかは次のコードで指定する(後述)

##rescale=1./255
・画像の前処理の定番
画像はRGB(Red,Green,Blue)で表され、それぞれ0~255の値を取る
例：RGB =（110,15,40)
255で割ることでそれぞれの要素が0~1という小さな値になりモデルにとって処理しやすい　
例：RGB =（0.43,0.05,0.15)

#クラスの確認
改めて今回何を分類するのかを確認しましょう
**Class 1 =(cry)**

**Class 2 =(smile)**



#学習
```python

history = model.fit_generator(
      train_generator,
      steps_per_epoch=200,
      epochs=300,
      validation_data=validation_generator,
      validation_steps=40)
```
・steps_per_epochが先程言ったジェネレーターをいつ止めるかについて
　今回は10000枚のデータを50枚ずつ出しているので200回でデータをすべて出すことができる
・epochsはデータ1回りを何周するかを指定
・validation_stepsも同様に（2000枚÷50枚）で40回



＊今回は記事の簡略化のために300エポックを一気にやったことにしているが、
　本来は少ないエポック数で過学習や学習不足に陥っていないかチェックし、適したモデルを探りながら学習を進めた方が良い

#学習の結果
```python

Epoch 1/300
200/200 [==============================] - 644s 4s/step - loss: 0.6939 - acc: 0.5062 - val_loss: 0.6926 - val_acc: 0.5350
Epoch 2/300
200/200 [==============================] - 651s 4s/step - loss: 0.6932 - acc: 0.5129 - val_loss: 0.6921 - val_acc: 0.5213
Epoch 3/300
200/200 [==============================] - 642s 4s/step - loss: 0.6924 - acc: 0.5183 - val_loss: 0.6905 - val_acc: 0.5712
Epoch 4/300
200/200 [==============================] - 643s 4s/step - loss: 0.6910 - acc: 0.5320 - val_loss: 0.6878 - val_acc: 0.5438
Epoch 5/300
200/200 [==============================] - 651s 4s/step - loss: 0.6908 - acc: 0.5256 - val_loss: 0.6892 - val_acc: 0.5275
.
.
.
.
.
Epoch 296/300
200/200 [==============================] - 650s 4s/step - loss: 0.3448 - acc: 0.8443 - val_loss: 0.3959 - val_acc: 0.8290
Epoch 297/300
200/200 [==============================] - 643s 4s/step - loss: 0.3500 - acc: 0.8396 - val_loss: 0.5990 - val_acc: 0.7265
Epoch 298/300
200/200 [==============================] - 644s 4s/step - loss: 0.3492 - acc: 0.8418 - val_loss: 0.4906 - val_acc: 0.7720
Epoch 299/300
200/200 [==============================] - 653s 4s/step - loss: 0.3511 - acc: 0.8408 - val_loss: 0.4107 - val_acc: 0.8055
Epoch 300/300
200/200 [==============================] - 650s 4s/step - loss: 0.3452 - acc: 0.8464 - val_loss: 0.3975 - val_acc: 0.8225
```
<b>300エポック学習して82%まで精度が上がった</b>

#モデルの保存
```python

model.save('baby_300')
```
上手く学習ができたら忘れずに保存しましょう
カンマの中はモデルの名前（わかりやすければ、好きな名前でOK)



##続きは次の記事で！
・データ拡張で更に精度UP　　・最後にテストデータで性能チェック
https://qiita.com/Phoeboooo/items/56c1a02922c9ac959ec7

・学習結果をきれいなグラフにする方法
https://qiita.com/Phoeboooo/items/ec0eb1d50b6d42711563