christinaの備忘録

てきとーに。

Deep Learningでラブライブ!キャラを識別する

 

このところDeep Learningが相当流行っているようで、ほとんど至るところで話題になっているのを見ます。
Deep Learningは深層学習とも呼ばれ、ニューラルネットワークの層をこれまでより深くして機械学習を行う技法です(だそうです)。
画像認識コンテストで他の方法と比べて非常に高い精度を示しており、以前は人の手で行っていた特徴の抽出まで行えます。
以前であれば車を認識するには車はどのような特徴を持っているかを人がモデル化して入力していたわけですが、この特徴を入力画像と与えられたラベルからニューラルネットワークが捉えてくれます。詳しいことはDeep Learningで検索して出てくる記事やスライドを参照のこと。

Deep Learning自体は容易に実装可能なものではなさそうですが、多くの研究グループがDeep Learningを行うためのソフトウェアをオープンソースにしているため、気軽に試せるようになっています。
先日開催された87でSIG2DというサークルがDeep Learningの入門記事を載せた本*1を頒布しており、それを読んでなんとなくやる気になったのでその記事をなぞって自分でも画像分類器を作ってみました。
題材はラブライブ!のキャラクターです。与えられた画像に対し、どのμ'sのメンバーが画像の中にいるかをそこそこの精度で判定するのが目標です。また、他のアニメのキャラをμ'sと判別しないようにします(髪の色だけで判定したりはできない)。

 

完成品はこんな感じです

 

f:id:chris_tina:20150123194624j:plain

 

 

データ収集

最初に行わなければならないのが画像の収集です。ラブライブの画像自体はいくらでも見つかるのですが、Deep Learningはある程度の枚数の画像がないと精度が出ない印象で、しかもその入力画像の中には誰がいるのかというラベルを付けなければなりません。
Deep Learningを試すためだけにラベルを一枚一枚手で付けるのはあまりにハードルが高いので、今回は既に画像にタグが付いているサイトをクロールします。
また、タグが付いていても画像に二人以上のμ'sメンバーがいる場合はどれが誰なのか学習前に教えなければならないので、一人のメンバーだけが描かれている画像のみを使用します。


実際に人がキャラクターを認識する際には顔、髪型、体形、服装など様々な要素を考慮しますが、顔だけが描かれていても余裕で誰か認識できる事が(自分の)経験的に知られているのでDeep Learningには顔周辺だけを見てもらいます。
ここで別の画像認識タスクが加わりました。2次元キャラの顔の領域を認識しないと画像分類器に渡せません。むしろこっちの問題の方が難しいのでは…
この問題に1から取り組むわけにもいかないので、ここではその道のプロによる既存のライブラリを使います。OpenCV+AnimeFaceです。

nagadomi/lbpcascade_animeface · GitHub

 

基本的な手順としては以下のようになります。
1. 画像を収集
2. 顔領域を認識して切り取り
3. タグと切り取った画像を比較してごみを掃除

 

AnimeFaceの顔認識はかなり精度が良いのですが、膨大な画像を入力すれば当然顔でない部分も誤認識してしまいます。画像に付いていたタグも常に正しい訳ではありません。そのまま入力画像として使うと何を学習するか怖いので誤認識された画像は取り除きます。この目的には一般的な人間を利用します。平均的な人間(自分)であれば1分当たり100-200枚程度を正誤に分類できます。1時間あたり6000枚以上なのでそんなに遅いわけでもないし、お金を払って人を雇うとスケールします。Amazon Mechanical Turkとかに投げてみたい気分もしますね。


こうして集まった6600枚のμ'sの画像とμ'sではない画像24000枚で学習を行います(ある程度負例を入れないとμ's以外のキャラや顔ですらない物体をμ'sと判定する割合が高くなります。それにしても多すぎるかもしれない)。学習用データには画像の85%を利用し、残りの15%をテストデータにします。

 

Caffeの学習準備


今回はSIG2Dに従ってCaffeを使って学習します。CaffeはGPUを使うと爆速なようなのでAWSのEC2でGPUインスタンスを借ります。今回利用した範囲ではスポットインスタンスは1時間0.06ドル、つまり7円前後である事が多かったので使いすぎても破産はしないでしょう。
セットアップの方法はSIG2D'14に全部書いてあるのでそちらを参照して下さい。探せば似たようなセットアップ記事もあると思います。
学習の方はCaffeに同梱されているcifar10のネットワークを利用します。パラメーターを適当に調整して画像を突っ込むとモデルを生成してくれる優れもの。情報量無いしこの章いらないですね。

 

学習結果

学習中の過程はこんな感じです。縦軸が正答率、横軸が反復回数。

 

f:id:chris_tina:20150123195156j:plain

 

4000回の反復でテストデータに対して90%の精度を出した後はゆっくりと学習し、40000回の反復で96%の精度に達しています。そこから先は訓練データへの正答率は動いているものの、テストデータへの正答率はどこも変わらないように見えるので70000回の反復が終わった学習結果を利用することにします。

ところで、この精度はμ'sを識別するのにはあまりいい指標になりません。μ'sの画像に比べてそれ以外の画像の枚数が多すぎるので、精度の評価もμ'sではない画像の精度に引きずられる事になります。だったら最初からテストデータを調整しておけよという感じですが、今さら遅いのでもう少し詳細に精度を調べるために混同行列を見てみます。

 

f:id:chris_tina:20150123195503j:plain

 

縦が真のクラスで横がモデルによる分類結果です。

真姫ちゃんが96%といい精度を出している一方、海未ちゃんは85%と若干厳しい感じですね。その他のメンバーは90%の周りをふらついています。真のクラスをμ'sに限定した時の平均精度は90%です。

大部分の誤認識はμ'sをその他のクラスへ判定する事によって起きています。メンバー間の誤認識は絵里さんを穂乃果と判定が2%、凛ちゃんを穂乃果やことりちゃんと混同がそれぞれ1%程度ですね。
一方、その他からμ'sへの誤認識は僅差で矢澤がトップです。世界のYAZAWAだからね。仕方ないね。

 

Webアプリ

以上の手順で得られた画像分類器を使ってwebインターフェスを作ります。
訓練に使用したのは1人しか写っていない画像ですが、実用上はμ'sの集合写真に対して分類器を使用したいので顔認識を利用して得られたそれぞれの顔領域を分類器に入力し、分類結果を元の画像に乗せて返します。
これもOpenCVとAnimeFaceでお手軽に実現できます。

こちらがデモのURLです。

サーバーのお引越しと共に消えました。アーメン

 

画像をドラッグ&ドロップすると判定結果とスコアを画像に乗せて返します。四角形は実際にDeep Learningが見ている顔領域を表しています。

 

理想的に分類されるとこんな画像が返ってきます

f:id:chris_tina:20150123195815j:plain

 

おしい。花陽の認識は難しい

f:id:chris_tina:20150123195900j:plain

 

 

テストデータでは分類器の精度は90%程度だったので、9人が写っている画像だと大体1人は誤認識が行われる事になります。実際には精度はそれより落ちるようです。
訓練データには一人で写っている画像しか利用しておらず、正面を向いている画像が多くなりがちでしたが2人以上の画像になると別の方向を向いていたり顔の領域が交差する事も多くなり、うまく判定できなくなります。顔が傾いているとまじできついです。
加えてアニメの画像はほとんど訓練に使っていないのでそちらの系統の画像も苦手ですね。

 

分類器が混乱してる画像にはこんなのがあります。

f:id:chris_tina:20150123200128j:plain

 

髪を下ろした絵里さんは珍しいためスコアがかなり落ち、亜里沙と迷っている。

 

f:id:chris_tina:20150123200216j:plain

 

髪型の情報が大部分消えているので矢澤かどうか判断が付かない様子。希は横を向いているので顔認識が失敗してますね…

 

 

こちらは最終的には使っていないモデルの結果ですが、それっぽい間違え方をしています。

f:id:chris_tina:20150123200251j:plain

この髪型の海未ちゃんはあまりに珍しく、相当苦しんでいる。

 

 

f:id:chris_tina:20150123200304j:plain

確かに矢澤っぽい。

 

 

 

f:id:chris_tina:20150123200505j:plain

どう見ても絵里さん。

 

f:id:chris_tina:20150123200509j:plain

どう見ても絵里さんだが間違えている。

 

なんとなく瞳を閉じていると誤判別が多くなる印象がします。瞳がどれくらい影響しているか見てみたいので絵里さんに赤のカラーコンタクトを付けてもらうと:

 

f:id:chris_tina:20150123200604j:plain

2つ前の画像とは瞳の色しか違わないのにありえないくらいスコアが急落していますね。瞳の色っぽい何かを強い特徴として捉えていて、瞳の色が比較的近いことりちゃんと花陽の成分が入っているようです。

実際にDeep Learningに入力したのは画像と誰が写っているかというラベルだけなので、このようなキャラクターを識別するのに有効な特徴を人の手を借りず自動で獲得しているようです。

 

最後に別ジャンルのアイドルマスターから一枚です。

f:id:chris_tina:20150222091456j:plain

13人いてμ'sっぽさのスコアが出たのは千早のみ、値もかなり低い0.13なのでこの2つのグループの識別は大体できています。アイドルマスターは学習データに入っていないので、Deep Learningは千早の事は知らなくとも海未ちゃんっぽさを妥当に評価できるようですね。

 

 結論

 

今回はDeep Learningの中身には全く触れずに遊んでみただけですが、それでも結構まともな分類器が作れるようです。今回は顔認識にOpenCVとAnimeFaceを使っていますが、こちらもDeep Learningに関連した何かで実現できたら面白そうですね。

訓練データの不足についてはアニメを使うことである程度改善できます。アニメは差分画像の宝庫なので全フレームを画像に切り出し、ここで作った分類器でタグを付けて再度学習するブートストラッピングにより訓練データの不足を解消しより精度の高い分類器を作る事ができそうです。

ここで作ったモデルとコードはそのうち公開します。たぶん。

 

 

*1:Hazuki, Tachibana., Kotori, Otonashi., Yuuma, Kanoue., and Asuna. Proceedings of the 3rd Interdimensional Conference on 2D Information Processing. SIG2D'14