読者です 読者をやめる 読者になる 読者になる

キモオタがやってみるデータサイエンス〜その1:DeepLearningでミスコンっぽい顔を知る〜

注:この記事はキモヲタがキモヲタ同業者のために書いたとぉってもきも〜い記事です。それ以外の方は吐血するかもしれないので気をつけてくださいね♩

こんばんは。キモオタです。ブヒブヒ

さて、10月になりましたね。10月といえば、そろそろ学園祭のシーズンです。

学園祭に付きものと言えば、ミスコンですよね。ブヒブヒッ!*1

ミスコンっていいですよねぇ。私は好きですよ。

実際に足を運んで、イベントとして楽しむのもいいですね。

でも、ほら、やっぱデータサイエンティスト()なんでぇ〜データ*2をみてきゃっきゃっうふふ♡しちゃうんですよね。

でも、日本中でミスコンをやっている大学なんてたくさんありますよね?

それをいちいち見に行くのって面倒臭いじゃないですか?

ところが、ある日、私は聞いてしまったのです。

それがね!いいサイトがあるのよ!奥さん。ミスコレっていうの! 日本各地の大学でやってるミスコンの情報をわかりやす〜くまとめてくれてるのよ! しかも、今なら利用料無料!さあ、今すぐ、ミスコレへ!

あら素敵!たちまち虜になりますね!ブヒブヒッ!

これで出場者の最新の情報が追えますね!

しかし、まだ問題があります。「最近の流行はどんな感じ」と聞かれた場合です。次のような場面を考えてみましょう。

Bob: Hi! Joey! What's up?
Joey: Hi, Bob! 最近、ミスコレでミスコンにはまっているんだ!たくさんの出場者が見れてとっても楽しいよ!
Bob: Sounds Good! 今年のミスコンの出場者はどんな人が多いんだい?
Joey: えっ・・・どんなって言われても・・・そ、そんなのたくさんいてわからないよ・・・
Bob: おいおい、勘弁してくれよ!たくさん見ているのに説明できないのかい?ダサダサだね。ハッ(笑)

これはダサいですね。

さて、Joey少年はどうするべきだったのでしょうか?

きっと、Joey少年は「ああ、出場者の顔の特徴をうまくつかめる何かがあれば・・・」と思ったことでしょう。

それ、できるんです。そう、Deep Learningならね!

Deep Learningとは?

Deep Learningとは、ここ十数年で人気になったアルゴリズムのことです。

もうすでにご存知の方はおめでとうございます!あなたはすでに、データキモオタへの入り口に立っていますよ。

では、耳にすることはあるかもしれない、Deep Learning、何に使えるのでしょうか?

Deep Learningって何に使えるの?

簡潔にいうと、共通の情報を抽出することを得意にしています。

たとえば、この絵をご覧ください。*3 f:id:kensuke-mi:20151006000435p:plain

このきもいおっさんは、人の画像をたくさん集めて、共通部分を抽出した結果です。

また、こちらの猫画像をご覧ください。*4

f:id:kensuke-mi:20151006000552p:plain

この猫画像もまた、大量の猫画像を集めて、共通部分を抽出した結果です。

この猫画像は、「共通部分を集めた画像でモフモフで癒されていいのか?」という激しい論争を日本猫画像モフモフ学会に巻き起こしました。

ちなみに、両方ともGoogleの仕事です。*5

上の例は画像に応用した例ですが、もちろんあらゆるデータに利用可能です。

音声情報・テキスト情報にも利用できます。

テキスト情報向けにアルゴリズムを作り直したword2vecはある特定の分野では話題になりました。加賀さんから乳を引いてみたが、「瑞鳳さんから引いたら時空が曲がってしまうのではないか?」などの激しい論争が巻き起こりました。

Deep Learningはどやって動いてるの?

さて、Deep Learningというと、どんなイメージでしょうか?

私のイメージはこちらです。

f:id:kensuke-mi:20151005201755j:plain

Deepそうな男が勉強しようとしてますね?もちろん違います。

Deep Learningの正体は下のようなごちゃっとしたネットワークです。

f:id:kensuke-mi:20151005201817j:plain

この「ネットワーク装置」そのものが、Deep Learningなのです。

この装置では、左側の「でーた」にデータを入れます。

装置の中央では、データをいろいろ分解したり、傷つけてみたりと、変な操作をいっぱいします。

変な操作をいっぱいした上で、右側の「でーた'」から結果を出すます。

「でーた」と「でーた'」は元は同じ内容です。ただし、「でーた'」は「中央で変な操作をいっぱいしたけど、いろいろがんばった結果、元のでーたっぽく復元できたもの」です。

こうすると、中央部分では、「操作しまくったり、傷をつけても、元のデータに近しいものが復元できる情報」が蓄積されます。

あれ、それって・・・そう、中央に蓄積される情報こそが「共通部分」なのです。

それじゃあ、Deep Learningつかってみよう

それでは、哀れなJoey少年のために、共通部分を抽出してみることにします。

まず、手始めに、ミスコレの全出場者の写真とプロフ情報を収集します。

出場者の名前にごとにフォルダ分け・・・きもいですね〜

f:id:kensuke-mi:20151006002638p:plain

次に、顔画像だけ切り抜きます。ここでも機械学習の技術が生きてますが、それはDeep Learningではありません。おっと、ときどき誤認識がありますね。こういうものは手動でハァハァしながら削除します。

f:id:kensuke-mi:20151006002834p:plain

さて、その後、画像をグレー画像にします。綺麗なお顔を色なしにしてしまうのは心苦しい限りですが、画像データの機械学習を行なう場合にはグレー画像化するのが定石なのです。*6

全部で434枚になりました。Googleがやったことに比べれば数は圧倒的少なさですが、まぁ、こんなものでしょう。

ここまでやって、最後に、さっきのDeep Learning装置にたくさんの画像を読み込ませます。

そして、最後に、中央の丸から共通部分を抜き出してみます。

その結果がこちらです。

f:id:kensuke-mi:20151006003547p:plain

いっぱいありますね?丸の数だけ画像が存在しているのです。いまは400個の丸を中央に置きました。

見りゃわかりますが、ほとんが砂嵐のテレビ状態ですね。

すべての丸が必ずしも人間が見て理解できる情報とは限らないのです。

でも・・・あれ?ちょっとまって、右端に顔っぽいものがありません?

拡大してみましょう。

f:id:kensuke-mi:20151006003843p:plain

顔の形をしてますね!11番と44番と58番は無事に顔の形を抽出できたようです!

ちょっと、比較してみましょう。

f:id:kensuke-mi:20151006004330p:plain

44番はこれら写真の特徴をうまく捉えているように思います。

他にも該当しそうな写真が30枚近くありました。

一方で、58番は少し顔を左に傾けて、左側も髪を下ろしているお方のようですね。これも該当写真が多くありました。

11番はロングの髪の女性のようです。しかし、それ以上の情報は捉えられていないようです。

ほかの番号の情報も確認してみたのですが、このレベルまで情報を捉えているものはありませんでした。

結論

今年のミスコン出場者は

  • 髪をやや左で分けている女性
  • 髪を両側まで下ろして、左に顔を傾けて写真にうつる女性
  • 全体的に長い髪の女性

がいそうだ。ということになります。*7これでJoey少年も大喜びですね!

その他

さて、とりあえずJoey少年を喜ばせる情報にはなりましたが、Googleの画像とはほど遠い感じでした。どうして差がでてしまったのでしょう?

まずはデータ量の違いです。今回は、たかだか400枚ちょっとしか使っていません。一方でGoogle人間は37,000枚の画像とのことです。

また抽出に要する時間も影響がありそうです。Deep Learningは一般に、たくさん時間をかけて抽出すると、よい共通情報が取れる(傾向があります)。

しかし、今回、たかだか、MacBookで数時間で終わるような抽出しかしませんでした。対してGoogleは巨大なサーバーを大量に用意して並列で抽出します。そら、かないませんわ。

てくにかる・のーと

実験に利用したコードはすべてGitの私のリポジトリにあります。

すべてpythonで書いています。

一緒にきゃっきゃうふふ♡するお仲間を募集中です。

なお、Deep NNの構築とTrainingはChainerを利用しました。

Chainerはとても簡便なDeep Learning用のフレームワークです。

チュートリアルをご覧になれば、大体のDeep NNの構築方法はわかるでしょう。

また、この記事はChainerのわかりやすいコードexampleだと思います。

今回、構築して試してみたDeep NNはこちらの記事で紹介されている内容とほぼ同じです。

つまり、AutoEncoderとDenoising autoencoderを試してみた。ということです。

特徴量の学習結果を観察すると、以下のような傾向がありそうです。

  • 活性化関数はSigmoidよりも正規化線形関数の方がよい結果が得られている
  • 中間ノード数は400前後がよいようだ。
  • Dropoutは実施した方が若干よい

私の記事で紹介した結果は2層、400ノード、DropOut有り、正規化線形関数の結果です。

手書き文字の認識では、ノイズありの方がよい傾向でしたが、今回はまったくダメでした。

ノイズを乗せると、すべてのノードでノイズだらけになってしまっています。

この傾向がデータ量のせいなのか、顔パーツというタスクから来るものなのか?わかりません。

最後に、テスト時のロスを表示しておきます。

この動きを見ると、学習イテレーションを増やせば、まだまだロスは減るかもしれません。

ただし、計算機資源のせいで30イテレーションでやめておきました。

f:id:kensuke-mi:20151006011049p:plain

*1:最近ではMrコンテストとかありますけど、どーでもいいです。マジで

*2:ここでいうデータとは広義のデータです。従って、顔写真とか顔写真とか、少しだけプロフィールもあるかな

*3:出典

*4:出典

*5:元論文はこちら

*6:専門じゃないから知りません。そう聞きました。

*7:この分け方はMECEではありません。かぶりもありながら、データ全体の特徴を複数の見方から観測していることになります