中一が深層学習でAI作った話

#前置き
おひさしぶりです!
半年以上前に「中学一年生がPythonの知識ゼロからAIを作るまで」という記事で意気込みを書いて以来すっかりqiitaを更新できず、気づいたらあと一日で中二になってしまうことに気づき慌ててこの記事を作成しております。あの頃と比べるとかなり成長したので最後まで見ていただければありがたいです。

##この半年間何をしていたのか
前回のpart2を更新してからすぐにTECH::CAMPというプログラミングスクールに通わせていただきました。
そこでは、従来の機械学習(SVMとか)を学びました。そっから画像分類がしたくて深層学習の勉強を始めました。(深層4ヶ月目の新人）
今は強化学習に興味があるため、これを機に画像関係とはしばらく離れようと思ってます。

##今回使うもの

|スペック||
|:--|:--|
|iMac|(Retina 4K, 21.5-inch, 2017)|
|メモリ|16GB|
|GPU|nvidia GEFORCE GTX1080ti 11GB|

|ライブラリ|バージョン|
|:--|:--|
|tensorflow-gpu|1.5.1|
|keras|2.1.5|

#本題

今回は信号機の分類をしていきたいと思います。
画像はgoogleで"赤信号","青信号","黄信号"と検索し、17枚くらい手動でダウンロードしました。なぜスクレイピングしないかというと、googleで検索したところ、写真の数が全然なくて、関係ない人がめっちゃ写っていたので、使える写真をダウンロードしていったら17枚ぐらいでした。
データの前処理をして、そっからテスト用に5枚ぐらいとっておき、後の12枚を水増ししました。

```python
from PIL import Image
import os, glob
import numpy as np


classes = ["red", "blue", "yellow"]
num_classes = len(classes)
image_size = 50
num_testdata = 5


X_train = []
X_test = []
Y_train = []
Y_test = []

for index, classlabel in enumerate(classes):
    photos_dir = "./" + classlabel
    files = glob.glob(photos_dir + "/*.jpeg")
    for i, file in enumerate(files):
        if i >= 17: break
        image = Image.open(file)
        image = image.convert("RGB")
        image = image.resize((image_size, image_size))
        data = np.asarray(image)
        
        if i < num_testdata:
            X_test.append(data)
            Y_test.append(index)
        else:
            for angle in range(-20, 20, 5):
                
                img_r = image.rotate(angle)
                data = np.asarray(img_r)
                X_train.append(data)
                Y_train.append(index)
                
                
                img_trans = img_r.transpose(Image.FLIP_LEFT_RIGHT)
                data = np.asarray(img_trans)
                X_train.append(data)
                Y_train.append(index)



X_train = np.array(X_train)
X_test = np.array(X_test)
y_train = np.array(Y_train)
y_test = np.array(Y_train)


xy = (X_train, X_test, y_train, y_test)
np.save("./singou.npy", xy)
```



そして、今回はcnnを使いたいので、keras(tensorflowバックエンド)でプログラムを書いていきます。

```
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.utils import np_utils
import keras
import numpy as np


classes = ["red", "blue", "yellow"]
num_classes = len(classes)
image_size = 50


def main():
    X_train, X_test, y_train, y_test = np.load("./singou.npy")
    X_train = X_train.astype("float") / 256
    X_test = X_test.astype("float") / 256
    y_train = np_utils.to_categorical(y_train, num_classes)
    y_test = np_utils.to_categorical(y_test, num_classes)

    model = model_train(X_train, y_train, X_test, y_test)
    model_eval(model, X_test, y_test)

def model_train(X, y, X_test, y_test):
    model = Sequential()
    model.add(Conv2D(32,(3,3), padding='same',input_shape=X.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(3))
    model.add(Activation('softmax'))

    opt = keras.optimizers.rmsprop(lr=0.00005, decay=1e-6)
    model.compile(loss='categorical_crossentropy',optimizer=opt,metrics=['accuracy'])
    model.fit(X, y, batch_size=28, epochs=500)

    
    model.save('./sky_cnn.h5')

    return model

def model_eval(model, X, y):
    scores = model.evaluate(X, y, verbose=1)
    print('Test Loss: ', scores[0])
    print('Test Accuracy: ', scores[1])


main()
```

こんな感じにしました。modelの部分はkeras公式ページのでいいかなーと思ったのでそれにしました。

これを何回か回した結果、80%~86%ぐらいの正答率でした。画像収集のところを手抜いたので仕方がないかなーと

![test_red.jpeg](https://qiita-image-store.s3.amazonaws.com/0/198198/6367da42-e819-04a2-5298-f78a6d8cfd41.jpeg)

red, (100 %)
こんな感じでちゃんと分類できてました。


#終わりに
今回はババっと作ったので少し適当になってしまったかもしれませんが、ちゃんと分類できていてよかったです。
最近ずっと理論を勉強していたため、実装能力がめっちゃ下がってました。本当は今回もtensorflow単体で書きたかったんですが、細かい文法とかめっちゃ忘れてたので、止むを得ずkerasで書きました。ちょっと悔しいです。

一応twitterやってるのでフォローしていただけると嬉しいです。[@zenbooooon](https://twitter.com/zenbooooon)
だいたい暇なんで絡んでください。お願いします（^人^）

もっと面白みのあるものを作りたかった...

#参考文献
[https://qiita.com/mm_sys/items/c169fe0ef37862c39a30](https://qiita.com/mm_sys/items/c169fe0ef37862c39a30)
[人工知能プログラミングのための数学がわかる本](https://www.amazon.co.jp/%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%95%B0%E5%AD%A6%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B%E6%9C%AC-%E7%9F%B3%E5%B7%9D-%E8%81%A1%E5%BD%A6/dp/4046021969)←とてもおすすめです