CNNによる学習データ

[kerasでCNN 自分で拾った画像でやってみる](https://qiita.com/haru1977/items/17833e508fe07c004119)
基本はこの記事を参照して作成しました。

微妙に違うだけです。

細かい部分は自分で調べて何とかしました。
ぶっちゃけ動いたからヨシなので勉強不足です。

目的としてはとある物の写真からOKとNGを判定したいので
元となるデータとしては画像データ(640x480)を
OK・NG共に1000枚使用しています。

あくまでも初心者が辿り着いた結果をメモとして残すのが目的です。

#環境
Windows10 64bit
Anaconda navigator
Jupiter notebook
Python 3.7.7
tensorflow 2.1.0
tensorflow-gpu 2.1.0
keras 2.3.1
numpy 1.18.1
matplotlib 3.1.3

上記環境でプログラムを構築


#ライブラリ
```Python:cnn.ipynb
import keras
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.convolutional import MaxPooling2D
from keras.layers import Activation, Conv2D, Flatten, Dense,Dropout
from sklearn.model_selection import train_test_split
from keras.optimizers import SGD, Adadelta, Adagrad, Adam, Adamax, RMSprop, Nadam
from PIL import Image
import numpy as np
import glob
import matplotlib.pyplot as plt
import time
import os
```
`from keras.optimizers import`には`Adadelta`だけでよかったですが
色々と試したくて入れてます。(結局テストせんかったけど…)

#各種設定関係
```Python:cnn.ipynb
#設定
batch_size = 16
epochs = 200

#画像ディレクトリ
test_dir ="画像保存しているディレクトリを指定"
folder = os.listdir(test_dir)

#元画像640x480をresizeする際の大きさ設定
x_image_size = 200#640→200
y_image_size = 200#480→200
dense_size  = len(folder)
```
`batch_size`に関しては色々なサイトを見るに1・4・32等々設定値が転がっていたので
初めは32で回してみましたがエラーが出てなんともならなくなったので16に設定しています。
細かい部分まで調べ切れていないので正しいとは言えないと…
ただ回ったのでヨシにしています。

画像サイズを縦・横で色々と変えて試す為に分けて設定していますが
結果200まで落とさないと重すぎて動きませんでした。
なので`image_size = 200`でも問題ありません。(後の記述は一部変更必要)

#画像読み込み
```Python:cnn.ipynb
X = []
Y = []
for index, name in enumerate(folder):
    dir = test_dir + name
    files = glob.glob(dir + "/*.jpg")
    for i, file in enumerate(files):
        image = Image.open(file)
        image = image.convert("RGB")
        image = image.resize((x_image_size, y_image_size))
        data = np.asarray(image)
        X.append(data)
        Y.append(index)

X = np.array(X)
Y = np.array(Y)
X = X.astype('float32')
X = X / 255.0

Y = np_utils.to_categorical(Y, dense_size)
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.15)
```
今回はテストを15%にした位で、参考にさせて頂いた記事とほとんど変わりません。

#CNNモデル作成
```Python:cnn.ipynb
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',input_shape=X_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(dense_size))
model.add(Activation('softmax'))

model.summary()
```
正直な所、勉強しながらなので
どこをどのように触れば変化するのか？については分かってないです。
[keras公式サイト](https://keras.io/ja/)
ここを見ていますが、素人には理解できないっす…

#学習機作成
```Python:cnn.ipynb
optimizers ="Adadelta"
results = {}

model.compile(loss='categorical_crossentropy', optimizer=optimizers, metrics=['accuracy'])
results[0]= model.fit(X_train, y_train, validation_split=0.2, epochs=epochs,batch_size=batch_size)

model_json_str = model.to_json()
open('model.json', 'w').write(model_json_str)
model.save('weights.h5');
```
正直、Qiitaがなければ辿り着く事すら出来ませんでした。
ありがとうございます。

#結果
学習結果
![2020-09-22 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607764/e4c5e98a-d960-e154-d6d1-6887edab4e0a.png)

テスト結果
![2020-09-22 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607764/f94ff65e-2d7d-cf4c-706b-71b2ac9aaa8e.png)

はじめはひどいもので学習結果が横棒になるという結果でした。
その時は画像データも各50枚程度と少なく
epoch数も20程度でした。

とある方に『画像が命』と教えて頂きましたが、正にその通りの結果になったと思います。

後はこのデータを元に推論を作って、ちゃんと結果出るかがドキドキです。

#まとめ
なんだかんだでデータとしては作る事が出来ました。
『色々と試してみる』部分が圧倒的に不足している事を思い知りました。
手を動かさないと覚えない・知ろうとしない事を改めて知る事が出来ました。

40歳目前から始めると脳が拒否するので大変です。

以上です。