機械学習で乃木坂を識別してみた


##環境
・windows
・python
・Google Colaboratory

##概要
・作ったもの
・乃木坂４６とは
・深層学習とは
・画像を学習/検証データに分ける
・モデルの構築と学習
・webアプリ化

##作ったもの
乃木坂のメンバーの誰かを判定します。
![2019-08-05 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169545/54cfb7cb-1046-0f6a-ae32-20097727a512.png)
![2019-08-05 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169545/d297660e-78a3-8308-d451-a91c9cba12cb.png)

##[乃木坂46について](http://www.nogizaka46.com/)
AKBの公式ライバルとして秋元康のプロデュースによって誕生したアイドルグループです。
「乃木坂46、欅坂46、日向坂46」を総称して坂道グループと呼ばれています。詳しくは[こちら](https://ja.wikipedia.org/wiki/%E4%B9%83%E6%9C%A8%E5%9D%8246)をご覧ください。
##深層学習とは
多層のニューラルネットワークによる機械学習の手法です。
ニューラルネットワークは人間の神経細胞を数式モデルで人工的に表現したものです。
![ニューラルネットワークモデル図.png](https://qiita-image-store.s3.amazonaws.com/0/169545/af9f1b6e-3049-d077-2a2e-cea628fda0ea.png)
上図はニューラルネットワークのモデル図です。
「入力層、隠れ層、出力層」の各層を持ちノードとノードが繋がっている構造である。データが入力層から入り、入力層ー隠れ層、隠れ層ー出力層との間で重みが調整されていきます。
詳しくは[こちら](https://japan-medical-ai.github.io/medical-ai-course-materials/notebooks/Introduction_to_Neural_Network.html)
##画像を収集及び顔の切り出し
画像を収集は[pythonライブラリicrawlerを使い簡単に画像データを集める](https://qiita.com/NakaokaRei/items/8c7e7b1f2c0c7ef8b3a3)を参考に収集しています。
顔の切り出しについては[opencvで顔を検出してみた](https://qiita.com/Dexctersu/items/f193771afba3f5f1bd2e)を参考にし、上手く切り出せなかった画像については手動で調整しました。

##画像を学習/検証データに分ける
学習用と検証用にデータを3:1に分けます。


##モデルの構築/学習

webアプリ化する必要がなければ、[こちら](https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja#scrollTo=ol93N5hsyNG0)で試された方が爆速でできよいと思います。


```.py
from keras import layers,models
from keras import optimizers
from keras.utils import np_utils
import numpy as np
import keras
classes=["asuka","ikuta","nana","maiyan"]
num_classes=len(classes)
image_size=50
def main():
    X_train,X_test,y_train,y_test=np.load("./nogi.npy")
    X_train=X_train.astype("float")/255
    X_test=X_test.astype("float")/255
    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)
    model_eval(model,X_test,y_test)
def model_train(X,y):
    #モデルの作成
    model=models.Sequential()
    model.add(layers.Conv2D(32,(3,3),activation="relu",input_shape=(50,50,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(layers.Flatten())
    model.add(layers.Dense(512,activation="relu"))
    model.add(layers.Dense(4,activation="softmax"))
    #コンパイル
    model.compile(loss="binary_crossentropy",optimizer=optimizers.RMSprop(lr=1e-4),
    metrics=["acc"])
    #モデルの学習
    model.fit(X,y,batch_size=10,epochs=50)
    #モデルの保存
    model.save("./nogi_cnn.h5")
    return model

def model_eval(model,X,y):
    scores=model.evaluate(X,y,verbose=1)
    print("Test acc",scores[1])
if __name__=="__main__":
    main()

```
今回のテスト用の結果は91％になりました。

![2018-12-22 (1).png](https://qiita-image-store.s3.amazonaws.com/0/169545/a11cf1bb-352a-e99a-a6c3-49d98a14703e.png)



##おわりに
今回はKerasとopencvを使いました。より精度を上げるために画像の水増しや学習させる画像の増加を検討しています。さらなる上達のために、転移学習にも挑戦したいと考えています。
検証用データでは正解率が9割ですが、個人的に試した感じでは7割くらいな感じがしました。
質問や間違いがありましたらコメントまたは編集リクエストをしてもらえると幸いです。
全体のコードは[こちら](https://github.com/Dexctersu/facejudge)に載せておきます。
##参考
[pythonライブラリicrawlerを使い簡単に画像データを集める](https://qiita.com/NakaokaRei/items/8c7e7b1f2c0c7ef8b3a3)
[Opencvで顔を検出してみた](https://qiita.com/Dexctersu/items/f193771afba3f5f1bd2e)
[機械学習で乃木坂46を顔分類してみた](https://blog.aidemy.net/entry/2017/12/17/214715)
[FlaskとOpenCVで投稿された画像をOpenCV加工してで返す](https://ensekitt.hatenablog.com/entry/2018/06/27/200000)