TensorFlowによるアイドル顔識別器の話 - 2016.12.13 TensorFlow User Group #2

## 自己紹介 ##

- すぎゃーん (id:sugyan)
  - Web系エンジニア
  - ドルヲタ
- TensorFlowで機械学習に入門 (2015.11〜)
- はてなブログ書いてます
  - すぎゃーんメモ http://memo.sugyan.com/


---

## アジェンダ ##

- アイドル顔識別について
  - 自作識別器の紹介
- データセット・学習の話
- 可視化


---

### 前回のあらすじ ###

[TensorFlowによるアイドル顔識別器の話 (2016.9.28)](http://qiita.com/sugyan/items/e66817d492414ef3daa5)

- 学習用データセットの収集・作成
  - …の苦労話
- モデルの評価と実験
- 収集したデータを使った顔画像生成

など


---

## アイドル顔識別について ##

問題設定 (やりたいこと)

**「入力した画像に対し、写っているのが『どのアイドル(人物)か』を機械学習により自動判定する」**

- 画像に対する 物体検出 + 分類
  - 顔検出は今のところCloud Vision API任せ
- 検出された領域を抽出した個々の顔画像に対する**分類**がメイン


---

## LINE BOTを作りました ###

<img src="http://qr-official.line.me/L/lJR6lyjwBW.png" width="200" height="200">

<a href="https://line.me/R/ti/p/%40uew8949d"><img height="36" border="0" alt="友だち追加" src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png"></a>

http://memo.sugyan.com/entry/2016/11/28/131952


---

2016.12.13現在 識別対象数 898人


---

※識別対象とする「アイドル」の定義については難しい問題

とりあえず今は

- Twitterアカウントを持っていて
- 多くの自撮りを投稿している
- ライブアイドル

をメインに独断と偏見で


---

データ提供していただければ対応も考慮します🙇


---

## アイドル顔識別器 ##

- 入力: `(96, 96, 3)` の画像
- 出力: 各分類ラベルに対応する`softmax`

CIFAR-10のモデルなどを参考に自分で組み立てて調整したもの 

|4層の畳み込み&プーリング|3層の全結合
|---|---|
|![19.09.45.png](https://qiita-image-store.s3.amazonaws.com/0/3245/079bfc93-c01d-bd47-a693-87855838df18.png)|![19.10.07.png](https://qiita-image-store.s3.amazonaws.com/0/3245/55f9b662-cca5-e479-91dc-ad683048043c.png)|

---

## 学習データの準備 ##

- 顔画像の収集
- 分類のためのラベル付け

教師あり学習のため、それぞれの顔画像に「それが誰であるか」正しいラベルが付与されている必要がある

---

### 収集 ###

- 取得対象のTwitterアカウントを登録 (ほぼ手動)
  - 2016.12時点で約1,500件 
- 検索APIで定期的に画像付きTweetを取得
- 自作の顔検出器で顔部分だけを抽出
  - http://memo.sugyan.com/entry/20151203/1449137219

放っておいても毎日2,000件くらい集まる

---

### ラベル付け ###

- 収集された1つ1つの顔画像に「正解ラベル」を対応付ける
- 超高度な知識が要求される
- とにかく頑張る
  - 頑張るしかない

色々仕組みを考えたり工夫している が、TensorFlowほぼ関係ないので割愛

---

約10ヶ月続けて 10万/70万 くらい

![1.png](https://qiita-image-store.s3.amazonaws.com/0/3245/701baf36-11fc-aa2a-d122-489e7ca356af.png)


---

「私のデータセットは53万です」

って言えるくらいまで頑張りたい

---

## 学習に使うデータセット ##

- 10万枚ラベル付けした、といっても色々ある
  - 400枚くらい揃っている人物、数枚しかない人物
  - アイドルではない人物
  - そもそも人間の顔じゃないもの (誤検出されたもの)

--- 

- できるだけ各クラス均等な数で
- それなりに分類できるところを目指したい

(検証用とかで分ける余裕はまだ無い)

---

人物ごとの枚数差はとても大きい

![2.png](https://qiita-image-store.s3.amazonaws.com/0/3245/0318cd77-4717-90f5-da71-3df7aee68810.png)

---

上限を120、下限を30として抽出 (30以下は学習対象外にする)

![3.png](https://qiita-image-store.s3.amazonaws.com/0/3245/e3fe4aaf-4476-6cf1-7d45-e3d08ebc40dc.png)

---

60以下のものは2倍に水増し

![4.png](https://qiita-image-store.s3.amazonaws.com/0/3245/a0f95347-929a-eb5b-525e-068a29a24644.png)

---

「学習対象外」のものは1つのラベルとしてまとめて1万件ほど抽出

- 30件未満しか集まっていない人物
- アイドルではない人物
- アイドルではなくなった人物…
- 顔ではないもの
- つまり学習対象の人物の顔ではないものすべて

---

## 学習の実行 ##

- tfrecordsファイルから`batch_size=128`の`tf.train.shuffle_batch`で
- 重みの初期値は`tf.truncated_normal_initializer`による乱数値 
- loss(cross entropyなど)が減少するよう各層の`weight`, `bias`を更新していく

が、まっさらな状態から学習は上手くいくのか？

---

データ数、分類数が多くなると収束しにくくなる (当然)

![5.png](https://qiita-image-store.s3.amazonaws.com/0/3245/51ee2230-e984-d71c-3a01-c5e3b5530f17.png)


---

850クラス分類を初期値から学習開始するとぜんぜん収束しない

![6.png](https://qiita-image-store.s3.amazonaws.com/0/3245/abe228e7-9de4-8369-0ee4-05fd34f60fdd.png)

---

まず10クラスなど、簡単な分類である程度学習させ、

そのパラメータを再利用して最終出力層だけ繋ぎ変える

---

中間層が事前学習してあれば割とイイカンジに

![7.png](https://qiita-image-store.s3.amazonaws.com/0/3245/8f3f7f6d-0c87-1faa-5804-dddeffd38272.png)


---

- 学習データが増えるごとに徐々に分類数を増やす
- が、初期値から学習をやり直すのは最終出力層の部分だけ
  - `g2.2xlarge`で3時間くらい

というのを繰り返して分類数を増やしてきた

今のところはこの手法で大きな問題なく動いている


---

## 可視化の話

0.12.0(現時点ではRC1) からTensorBoardに新機能が追加

- [Open sourcing the Embedding Projector: a tool for visualizing high dimensional data](https://research.googleblog.com/2016/12/open-sourcing-embedding-projector-tool.html)


---

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">おぉぉ、TensorFlow 0.12のEmbedding Visualisationでアイドル顔識別の中間層出力を可視化できた(30人x30点ずつ)。PCAだとゴチャゴチャしてるけどT-SNEだとはっきり分かれる、とか選択したものと距離が近いもの数点に絞って可視化、とかも出来る <a href="https://t.co/8aGiGDowPa">pic.twitter.com/8aGiGDowPa</a></p>&mdash; すぎゃーん💯 (@sugyan) <a href="https://twitter.com/sugyan/status/805271494267801601">December 4, 2016</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none" data-lang="en"><p lang="ja" dir="ltr"><a href="https://twitter.com/sugyan">@sugyan</a> 3Dでグリグリ動かせるし面白い <a href="https://t.co/dXf05ikSXx">pic.twitter.com/dXf05ikSXx</a></p>&mdash; すぎゃーん💯 (@sugyan) <a href="https://twitter.com/sugyan/status/805273452080812032">December 4, 2016</a></blockquote>

http://memo.sugyan.com/entry/2016/12/05/022346


---

デモ

現在の識別モデルで、識別対象に**なっていない**画像群を入力したときの中間層出力の分布をEmbedding Projecotorで見てみる


---

未知のデータのクラスタリングを視覚的に確認できそう


---

## まとめ ##

- 学習データが増えてもどうにか学習はできている
  - あとはとにかく増やし続けるのみ
  - まだまだ課題はあるし仕組みは考えていきたい
- 可視化たのしい


---

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">「去年の今くらいから機械学習さわり始めて、この1年間めっちゃ勉強しましたからねー。その成果あって今では500人くらいのアイドルを識別できるようになりました。俺が。」ていうのが最近の鉄板ネタ</p>&mdash; すぎゃーん💯 (@sugyan) <a href="https://twitter.com/sugyan/status/806497166860500993">December 7, 2016</a></blockquote>