Neural Network Consoleで笑顔分類器

# はじめに
Neural Network Console Challengeコンテストのレポートです。Neural Network Console（以下NNC）はディープラーニングをノンプログラミングで使用できる開発ツールです。コンテストではPIXTA提供の写真10,000枚とNNCを使って画像分類します。
[Neural Network Console Challenge](https://nnc-challenge.com/)

テーマは「NNCで画像を学習し人の感情によって分類」を選択しました。提供された写真老若男女の人物写真です。喜び、幸せ、楽しいなどポジティブな印象でした。写真の顔をじっくり眺めながら、ニッコリ微笑む顔、笑い声をあげて笑う顔、笑顔以外の３種類を分類する、ニコニコ笑顔分類器を目指すことにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/ae60d9ec-c59d-4f34-9e59-0fea331fcb9c.png)

# NNCの使い方とインストール
クラウド版、Windowsアプリ版があり、両方使用しました。初期設定はメール登録、アクティベートと簡単で、すぐにサンプルプログラムが動かせました。チュートリアル動画が充実しており、動画を見ながらサンプルプログラムを動かして、初歩的な使い方を学びました。

- [クラウド版チュートリアル：はじめてのNeural Network Console~セットアップからサンプルプロジェクトの実行まで~（動画）](https://youtu.be/b3wfiozov6k)
- [Windows版チュートリアル：5分で構築するCNN](https://www.youtube.com/watch?v=Vj7yfyiux0w)
- [NNCチュートリアル：Exif情報を利用し簡単にオリジナルデータセットを用いた実験を行う](https://www.youtube.com/watch?time_continue=30&v=tV306SWDhvw&feature=emb_title)

# 顔画像データ作成
NNCの使い方を学習と提供画像データの理解を深めるため、データ準備、ネットワーク作成、学習と予測結果の確認まで試してみました。

## 写真の選定
10,000点から、単身で正面向きを中心に1256枚選定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/e531c98c-b919-3c4f-bdcd-1fbea4693941.png)

## 写真から顔画像切り出し
人物と背景を含む写真で学習をしたのですが、時間がかかり精度が悪く断念し、顔だけで学習することに。切り出しはPython OpenCVです。
[【入門者向け解説】openCV顔検出の仕組と実践](https://qiita.com/FukuharaYohei/items/ec6dce7cc5ea21a51a82)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/034efc58-dfe2-7cfa-f65d-4a526f58be15.png)

## 画像アノテーション
3つのラベル名のフォルダを作成し、顔画像1256枚をを振り分けました。

|分類 |ラベル  |画像数  |
|---|---|---|
|笑い声が聞こえそうな笑顔 |0 |597|
|ニッコリ微笑む顔 |1 |358  |
|その他|2 |301  |

# Neural Network Console
## データセット作成
- アノテーション作業フォルダを指定
- 画像サイズを統一するためにPaddingを指定
- 画像サイズ48×64を指定
- 訓練データと検証データを8:2で指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/751e4650-292e-f238-23a8-a4f7f46ed7bd.png)
切り出した顔画像はサイズが違ったため、画像サイズを統一する必要があります。NNCデータセット作成にはアスペクト比を同じで、足りない部分を0埋めするPaddingが便利でした。

## ネットワーク設計
チュートリアル動画を参考に、畳み込み5層と全結合2層の計7層の畳み込みニューラルネットワークを作成しました。コツはニューロン数が徐々に減らすです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/1f31218d-db82-0d9a-1ff8-4f1751441c17.png)

## 学習
訓練用1130枚、検証用126枚で学習。40分で完了しました。VALIDATION ERRORはヒドイ状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/edcfc505-e966-510b-b18c-1c5441fa7ae1.png)

## 評価
混同行列で確認。Accuracy0.6031と正解率は低めです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/b9276658-132e-c9fd-4c12-ca479188cebd.png)

# 改良
- アノテーション間違いが多い　⇒　見直し
- 学習データ不足　⇒　顔画像追加
- 学習ネットワークが浅い？　⇒　深くする

## 顔画像データ作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/87642448-8e77-6487-ea87-97f35d63ed49.png)
- 複数人写真から顔画像追加（552枚）
- ピンぼけ、不鮮明、低解像度の画像除去
- アノテーション作業、見直し（2000枚）

## ネットワークを深く設計
畳み込み10層と全結合2層の計12層にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/84df9307-54fa-a0f5-146f-a1ca1fc0bf2c.png)

## 学習
訓練用1800枚、検証用200枚で学習。2時間17分で完了しました。VALIDATION ERRORが収束してきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/2aede071-9299-93de-1539-7c84f9787fea.png)

## 評価
混同行列で確認。Accuracy0.785と正解率が改善しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/72b9a3d1-ee03-04a4-e02d-2ce007b46a7e.png)

# クラウド版GPUでの精度改良
1万円分のGPU利用枠がもらえましたので時間を比較しました。GPUは圧倒的に早いです！！ディープラーニングにGPUが重宝されるのがよく分かりました。

|CPU |学習時間  |備考  |
|---|---|---|
|NVIDIA® TESLA® K80 GPU x1|2分|クラウド版 210円/時間|
|Intel(R) Core i5-5200U CPU @ 2.20GHz|2時間17分  |ローカルPC  |

## さらに深いネットワークへ
VGG16を参考にネットワーク設計を試行錯誤しました。最終的にはニューロン数を増やし、畳み込み13層と全結合3層の計16層となりました。
[SONY Neural Network Console でミニ VGGnet を作る](http://cedro3.com/ai/mini-vgg-net/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/4c6b111a-cf6e-e77a-a703-900e148af84e.png)

## 複数人でアノテーション作業
いいシワが刻まれたご高齢の方が笑ってないのに仏のような微笑みに見えたり、眉間にシワが寄っていても歯茎が見え口角が上がって笑っているなど、様々な悩ましい笑顔がありました。家族にアノテーションを手伝ってもらい、多数決で顔画像1939枚を分類しました。

|分類 |ラベル  |画像数  |
|---|---|---|
|笑い声が聞こえそうな笑顔 |0 |895|
|ニッコリ微笑む顔 |1 |544  |
|その他|2 |500  |

## 学習
訓練用1551枚、検証用388枚で学習。11分で完了。
VALIDATION ERRORも収束してきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/df7ea961-9e12-7d9c-c9ff-a189ebe668d9.png)

## 評価
混同行列で確認。Accuracy0.8686に改善できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/0b9076ad-4391-1043-e535-74423a66a7b9.png)

分類間違いを確認しました。y:labelは正解ラベル、y_0は笑い声が聞こえそうな笑顔の確率、y_1はニッコリ微笑む顔の確率、y_2はその他の確率です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/953c728e-93f3-9a52-9cb8-e8a0ddc3a146.png)
正解は「2:その他」でしたが、確率84%で「1:ニッコリ微笑む顔」に分類されました。やや口が空いているのを微笑みと誤分類したのか思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/632669a1-78ce-742f-bd00-cca32d32c10d.png)
正解は「1:ニッコリ微笑む顔」でしたが、確率69%で「2:その他」に分類されました。画質が粗いからでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/c4610638-83d6-e7b2-26d1-9f579d38779a.png)
正解は「2:その他」でしたが、確率88%で「1:ニッコリ微笑む顔」に分類されました。口角が上がって微笑んでるようにも見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/b4d21475-aacd-958b-b13a-0e985db88b2d.png)
正解は「0:笑い声が聞こえそうな笑顔」でしたが、確率58%で「1:ニッコリ微笑む顔」に分類されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/fb8c4980-b8df-1ed5-6840-c4c8a941cc7b.png)
正解は「1:ニッコリ微笑む顔」でしたが、確率97%で「0:笑い声が聞こえそうな笑顔」に分類されました。

### 評価まとめ
分類の境界線近くで間違いが多い印象です。また、横顔も間違いがやや多そうです。

# ニコニコ笑顔分類器の作成
## Pythonで学習モデル実行
学習モデル「Pythonコード」とパラメータファイル「results.nnp」をダウンロードし、Google Colaboratoryで笑顔分類器を作成しました。
[Python APIを用いて推論を実行する方法](https://support.dl.sony.com/docs-ja/%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%EF%BC%9Aneural-network-console%E3%81%AB%E3%82%88%E3%82%8B%E5%AD%A6%E7%BF%92%E6%B8%88%E3%81%BF%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9/)
実行環境によってScipyのバージョンによりエラーが出るようです。

``` 
from scipy.misc import imread  # エラー発生
from imageio import imread     # 動作OK
```
## 推測用データ
無料素材サイト「ぱくたそ」から新たな顔画像を頂きました。
[PAKUTASO](https://www.pakutaso.com/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213256/53c95adf-aad4-fe30-fd92-afa4b1a5adbf.png)

## ニコニコ笑顔分類器の推測結果
笑顔分類器の推測結果です。1,3番目は正しく推測でき、2番目は間違っていました。まだ精度改善の余地はありそうです。

|画像 |推測ラベル  |正解ラベル  |正否 |
|---|---|---|:-:|
|man0-1.png |0：笑い声が聞こえそうな笑顔 |0：笑い声が聞こえそうな笑顔|○ | 
|man1-1.png |2：その他 |1：ニッコリ微笑む顔|× |
|man2-1.png |2：その他 |2：その他|○ |

# まとめ
クラウド版ワークスペースの10GB上限に達したため、チャレンジは終了としました。Neural Network Consoleも畳み込みニューラルネットワークも初めてでしたが、二週間ほどでモデルを外部から呼び出すところまで実装できました。時間配分はアノテーション作業5割、CNN勉強3割、NNCの操作2割くらいの感覚です。精度の高いデータを準備するのが大変なのを実感しました。

## さらなる改良案
- 横顔データを追加か削除する
- 高画質の画像で学習する
- ネットワークをさらに深くする

## 最後に
アノテーション作業で老若男女の様々な笑顔を眺めていて、楽しい、幸せな気持ちになりました。マスクせずに大きな口で笑える日が来ることを祈ります。