TensorFlow理解のために柏木由紀さん顔特徴を調べてみた【前編】

TensorFlowおよびCNN(畳み込みニューラルネットワーク)を理解するために柏木由紀さんの顔特徴を調べてみました。別に柏木由紀さんのファンではないのですが、アイドル・女優に詳しくないため、特徴がありそうな人の顔で思い浮かんだというのが人の選定理由です。
TensorFlowを使った学習部分にフォーカスして解説している[中編](http://qiita.com/FukuharaYohei/items/1192ca038b0052ef300f)と判定部分を解説している[後編](http://qiita.com/FukuharaYohei/items/3f26bfe71fdb5720ce7e)に続きます。

# 結論
TensorFlowにとっての柏木由紀さんの**特徴は鼻ではありません**でした。正直、TensorFlowがどんな特徴で判断しているかよくわからなかったです。
あえて特徴を絞り込むために、判定精度は対してあげようとせずに判定方法をある程度わかりやすく学習モデルを組んでみました。テストデータに対する精度68%のモデルで見ています(精度が低いのは筆者の組み立てたモデルおよび学習データにも問題多いです)。
第2層プーリング処理結果の画像が予実でこんな違いが出ています。
![10.Summary01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/932372d2-b280-65c6-d6cc-f94791b2b10c.jpeg)
ただ、あくまで初心者が実行した結果なので、優秀な方が組み立てれば精度が高い「鼻判定器」のようなものができるのかもしれません。

# 実行した全体の流れ
以下の流れで今回の顔特徴調査を実施しました。
![10.Summary00.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/cac4ea72-dc7d-b024-68f0-590a62435576.jpeg)
##1. 画像取得
Bing Image Search APIを使って画像検索をし、収集しています。収集した画像は全体で2471枚でその内訳は下図のとおりです。女優・アイドルで画像が多そうな人を検索しました。
![20.ImageSearch01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/41fb4216-48e3-5786-ca65-719156e10ea2.jpeg)
実行時のコードと解説は記事[「PythonからBing Image Search API v5を呼び出して画像収集」](http://qiita.com/FukuharaYohei/items/6d0aefb16dd78eb03a08)を参照ください。

##2. 顔検出 + 切り出し + 誤検知除去
「顔検出 + 切り出し」はOpenCVを使って、「誤検知除去」は手作業で実施しました。
「1. 画像検索」と併せて、以下の枚数を処理しています。だいたい顔検出率は60%から70%くらいです。
![30.openCV01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/f503ed33-126c-1e37-34d0-5b3faf09dd30.jpeg)
この部分で得た教訓などは、記事[「openCVで効率的に大量画像を顔検出するためのtips」](http://qiita.com/FukuharaYohei/items/1e15d79c87f1de513eac)に書きました。手作業「誤検知除去」は地味に時間がかかるので注意ください。

##3. 学習
TensorFlowを使って学習しています。TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)とほぼ同じモデルです。その解説については、記事[「【入門者向け解説】TensorFlowチュートリアルDeep MNIST」]
(http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)を参照ください。
![10.Summary02_model.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/5764daad-dbb4-e8f7-663c-54d36e214ddc.jpeg)
「結論」部分の画像は第2層のプーリング処理結果の画像をTensorBoardを使って取り出しています(記事[「【TensorBoard入門:image編】TensorFlow画像処理を見える化して理解を深める」](http://qiita.com/FukuharaYohei/items/fae6896e041235033454))。
![10.Summary02_model_02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/7fb7fcad-7b2c-a236-9417-2efd28084c00.jpeg)

もう少し教師データ作成を頑張ればよかったのですが、各データはこんな感じです。精度が目的でないにしても正直、ひどいです。表の右に「精度を目的にして場合」としてハイパーパラメータなどを調整した場合は、多少ましになります。

|項目|内容|備考|精度を目的にして場合|
|:--|:--|:--|:--|
|教師データ|約1600枚(うち600枚程度が正解(柏木由紀さん)画像)|少ないです・・・|約2500枚|
|訓練データ|ランダムで約1350枚|EXCEL関数でランダムにピックアップ|約2250枚|
|テストデータ|ランダムで約250枚|EXCELの関数でランダムにピックアップ|約250枚|
|訓練データに対する正答率|74%|低い・・・|85%|
|テストデータに対する正答率|70%|同じく低い・・・|84%|

学習における正答率と誤差の推移は下図のとおりです。TensorBoardへの出力は、記事[「【TensorBoard入門】TensorFlow処理を見える化して理解を深める」](http://qiita.com/FukuharaYohei/items/7ea120005f73cf882146)を参照ください。
![40.DeepLearning01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/02e2b6f1-67c2-ab2a-3003-fdca877fae80.jpeg)

学習に関しては後編でコードを含めて詳しく解説します。

##4. 判定
画像判定は、下図の形でOpenCVを使った顔検出 + 切り出しとTensorFlowを使った画像判定を続けてしています。画像判定の際に、「3.学習」のプロセスで保存した学習済パラメータを使用しています。
![50.Judge01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/b2a8a5e9-ac8b-162e-4a8a-64576f61400c.jpeg)

#環境
実行環境は以下のとおりです。

|種類|バージョン|
|:--|:--|
|OS|Windows 10 64bit Pro|
|Anaconda|Anaconda 4.4.0 |
|Python| Python3.5|
|TensorFlow| TensorFlow 1.3|
|OpenCV|OpenCV 3.3|