AWSを用いて転移学習して熱帯魚の画像判別機を作る

#AWSを用いて転移学習して熱帯魚の画像判別機を作る


###設定した課題

例えば下のような熱帯魚のカラシン目カラシン科の主要な46種を判別させる。
![4. dsc_0109-628fa-thumbnail2.jpg](https://qiita-image-store.s3.amazonaws.com/0/287296/7146abd8-c1c0-bef0-455a-e89a3727d831.jpeg)
アークレッドペンシルフィッシュ

AWSのサービスである「Rekognition」が似ていると思われるが、熱帯魚の種類名までは分からないので、自分たちでモデルを組むことにした。


###流れ
1.物体認識をして与えられた画像から、魚のところを切り取るモデル 
2.切り取られた画像に映る熱帯魚の種類を当てるモデル
の２つを作り、組み合わせる。

##学習データの収集

chromeの拡張機能である、googleimagedownloadを用いた。
googleで種類名を検索して検索上位に出てくる画像を用いている。
[このサイトを参考にした](https://co.bsnws.net/article/295)

調べた種類とは関係がない写真（水槽など）、別の魚（金魚など）の写真も少なからず、混ざってしまっているのでこれらを除く必要がある。


##モデル1 （物体認識）

###イメージ図

<img width="335" alt="スクリーンショット 2018-10-03 12.51.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/287296/7c75ca4c-66d7-8b8d-4077-7bba8839c4b2.png">
↓
<img width="377" alt="スクリーンショット 2018-10-03 12.51.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/287296/7d3bca1c-aa43-43b6-609b-39b04d2d1939.png">
魚のみ切り抜く!!!

###使ったデータの説明
魚が写っている写真をアノテーションして、学習用の画像データ800枚、validationデータ用の画像データを100枚作り、学習に用いた。
[このサイトを参考にした](https://dev.classmethod.jp/cloud/aws/sagemaker-umaibo-object-detection/)


欠損値はない


###前処理
手作業で、VOTTというものを使い、画像データにアノテーションをした。
その際ある種類のカラシンに特化した物体認識にならないように、各種のカラシンから均等にデータを選んだ。


###アルゴリズムの選択
・AWSのRekognitionという物体認識ができる既存のサービスを使う
・AWSの物体検出の埋め込みアルゴリズム（Object Detection）を使う
の2通りを考えた

Rekognitionを使うことが出来るのであれば、それが最良だったのだが、座標を取り出すやり方が分からなかったので、諦めて、２つ目の案を使った。
元々のObject Detectionをそのまま使ってみると例えば下の画像のように魚が、人やモーターバイクと認識されてしまっていて魚は認識できなかったので、自分で学習データを用意して学習させて用いることにした。
![ダウンロード .png]
(https://qiita-image-store.s3.amazonaws.com/0/287296/cf4af218-6ae0-4a35-68bb-3b7e2a17f03a.png)






###結果、解釈


<img width="901" alt="スクリーンショット 2018-10-03 13.03.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/287296/bbd15d5e-6d8e-99d9-4b7b-79ad8c77894a.png">

画像に魚が一匹しか写っていない時は高い精度で魚と認識される。
![キャプチャ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/287296/15caff70-6b3b-78c7-7ef5-c04bf27f4ffd.png)

二匹写っている時は約5割と、精度が下がってしまうものの閾値を下げれば、魚の位置を認識できそうだ。
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/287296/553094b0-99f5-caa5-3d3c-cbe7e5960ff5.png)

それ以上の数になると、精度はかなり悪くなってしまう。


学習データの数を増やせば精度は上がるのであろうが、アノテーションを手作業で行ったため、データ数には限界があった。
このモデルなしで、モデル2だけで、判別することも考えたのだが、（つまり、魚がどこかに写っている画像をそのまま学習させる、ということ）



##モデル2（切り取った画像にうつる魚の種類を当てるモデル)
###使ったデータの説明
・46種それぞれについて約20枚ずつ（合計約1000枚）の画像データ

・データの分布はほぼ均等である。（各種約20枚ずつだから）

・欠損値はない

・魚の種類名をフォルダの名前にして、そのフォルダに画像データを入れることで、画像と種類名を対応させてある。



###前処理の工夫
・魚に関係がない画像（例えば水槽など）や、別の種類の魚の画像が少なからず混じってしまっているので、目視で排除した。

・学習に使う画像は下のように　一匹の魚のみがうつるようにトリミングした。
![73. 594bd07328a78fd6f9a2a69fbb784e48.jpg](https://qiita-image-store.s3.amazonaws.com/0/287296/5dc22ef7-0fc3-1901-7e4a-5240a8b10910.jpeg)
例えば上のような画像は下のように切り取った。

![73. 594bd07328a78fd6f9a2a69fbb784e48のコピー.jpg](https://qiita-image-store.s3.amazonaws.com/0/287296/66fd8daa-a17b-6be1-496e-abcdaed29bff.jpeg)




・ノイズに影響を受けにくいモデルを作るために、学習させる画像はランダムに回転、左右を反転させた。
（魚のところのみを切り取った画像で学習させているので、上下移動や、左右移動、拡大などは行わなかった。）



###アルゴリズムの選択
魚の大量なデータを集めることは難しいので、少ない画像でも高い精度が出せる転移学習を選択した。
転移学習以外でやろうとしても画像が少なすぎてできないのではないかと予想した。


####まず自分でモデルを作ってみた。
kerasのVGG16をbasemodelに用いた。
[github](https://github.com/taichiobara/fish_check/blob/master/fish.ipynb)

切り取らずにそのままの画像（つまり魚が中央に写っていなかったり、複数の魚が写っている画像）で学習させることも考え、試してみたのだが、精度は約2%と極めて悪かったので、魚のところを切り抜いて学習させることにした。そうしたところ、
<img width="961" alt="スクリーンショット 2018-09-25 7.34.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/287296/4f9d25eb-1d77-798c-c65e-e57e77d71869.png">
精度は約20%で、低かった。
データ数を増やせば精度が上がるのでは？と、データの拡張を行い学習データを約10倍に増やしたのだが、精度は増やす前よりも下がってしまった。拡張をしたことにより、画質の悪いデータが沢山含まれてしまったことが原因かと思われる。
[データの拡張に使ったコード](https://github.com/taichiobara/fish_check/blob/master/increase_picture.ipynb)

次に以下の方法で試した。

####AWSのsagemakerの埋め込みアルゴリズムである「Image classification training with format demo」を利用してみた。このアルゴリズムも転移学習を用いている。

データはs3に格納し、GPUはp2.xlargeを用いた。


###結果<img width="597" alt="スクリーンショット 2018-10-29 19.53.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/287296/7bfb0966-2993-2ee2-95de-308df8d967f5.png">

validationデータでの精度は、約60%となった。



精度が低かった理由はデータ数が少なすぎたからではないだろうか。



##今後の展望
モデルの精度が低いのには学習データの数が少ないこと以外にも、何か原因があると予想しているのだが、探りきれず、残念だった。
現段階では２つのモデルを作ったものの、それらを組み合わせて、サービスの形にするところまでできていないので、そこに取り組みたい。