Help us understand the problem. What is going on with this article?

TensorFlowによるももクロメンバー顔認識(中編)

More than 3 years have passed since last update.

前編はこちら
http://qiita.com/kenmaz/items/4b60ea00b159b3e00100

機械学習やディープラーニングについては全く初心者のソフトウェアエンジニアが、畳込みニューラルネットワークを用いて「ももいろクローバーZ」のメンバーの顔識別を行うアプリを作った話の続きです。

deeplearning

前編ではクローラーが集めてきた画像から顔画像を取り出し、学習用データを生成するところまで説明しました。ここからようやく学習に入ります。

機械学習部分のコードは、Tensorflowに付属にしている Deep MNIST for Expertsと、CIFAR-10 Classificationあたりのコードをベースに実装をすすめました。

CSVの生成と読み込み

gen_testdata.py
https://github.com/kenmaz/momo_mind/blob/master/deeplearning/gen_testdata.py

まず訓練データをTensorflowに食わせる部分ですが、MNISTのサンプルコードと同様、CSVを生成し、そいつを読みこませることにしました。前編では学習用のももクロメンバー画像をそれぞれMacのFinder上でフォルダ分けしましたが、そのフォルダ/ファイルの構造を元に、

訓練用画像のファイルパス,メンバー名を0-4に対応させた数値

という形式のCSVを吐く小さいスクリプトを書きました。

ちなみにTensorflowでは訓練データをこんなような protocol bufferでシリアライズして、TFRecordsというファイル形式に書き出すのがオススメらしいです。ちょっと面倒だったので今回は見送りました。

学習データの入力

以下がCSVを読み込み後述のモデルの入力データとなるTensorを構築するスクリプトです。
mcz_input.py
https://github.com/kenmaz/momo_mind/blob/master/deeplearning/mcz_input.py

TensorFlowにはテキストファイルを読み込む tf.TextLineReaderや、読み込んだデータをcsvとしてデコードしてくれるtf.decode_csv関数など、便利なクラスや関数が予め用意されています。こいつらを使って入力データを読み込めば、そのままTensorFlowへの入力データ形式であるtf.Tensorを自動的に構築してくれます。

さらに機械学習のテクニックとして、訓練サンプル画像を左右反転したり、ちょっと回転させたりズームさせたり、コントラスをランダムに変えるなどすることによって、訓練サンプル画像を「水増し」するテクニック(「データ拡張」と呼ぶらしい)がありますが、それらの処理もほとんどTensorFlowが用意してくれています。

ランダムに左右反転させるtf.image.random_flip_up_down(), 明るさをランダムに変えるtf.image.random_brightness()、同じくコントラストを変える tf.image.random_contrastなど。

最初はこれらの関数の存在に気づかず、自分でopenCVを使ってがんばっていたのですが、素直にTensorFlowのものを使ったほうが良さそうですね。

バッチ入力

今回は訓練データとして、各メンバー150枚ずつ、計750枚の顔画像を用意してあります。これらからランダムに120枚の画像を取り出し、上記の通りデータ拡張を行いランダム化させた上で、学習モデルの入力としてまとめてぶち込みます。この作業を1ステップとし、1000ステップ〜30000ステップほどひたすら学習を繰り返します。

学習モデル

今回作ったコードの中でおそらくいちばん重要な、学習/推論のモデルを組み立てるスクリプトです。
mcz_model.py
https://github.com/kenmaz/momo_mind/blob/master/deeplearning/mcz_model.py

モデルの検討その1

まずは以下のような畳み込みニューラルネットワークのモデル定義してみました。
https://github.com/kenmaz/momo_mind/blob/master/deeplearning/mcz_model.py#L6

- 入力 (28x28 3chカラー)
- 畳み込み層1
- プーリング層1
- 畳み込み層2
- プーリング層2
- 全結合層1
- 全結合層2

これはほとんどCIFAR-10のサンプルそのままのやつです。このモデルだと、分類精度だいたい65~70%程度しか出ませんでした。

そもそも入力28x28なのはCIFAR-10のサンプルをそのまま持ってきたからですが、28x28といえば、例えばこれ、28x28の画像です。
スクリーンショット 2016-05-24 3.19.59.png
うーん、誰でしょうね?(僕はわかりますけど

この荒い画像から特徴を探しださなきゃいけない、ってことで人間がやってもいかにも大変そうです。もっと高解像度にしたい。

モデルの検討その2

ということでもうちょい精度を高めたいなと思い、入力画像の解像度を倍にして、さらに畳み込み&プーリング層をひとつづつ追加しました。
https://github.com/kenmaz/momo_mind/blob/master/deeplearning/mcz_model.py#L53

- 入力 (56x56 3chカラー)
- 畳み込み層1
- プーリング層1
- 畳み込み層2
- プーリング層2
- 畳み込み層3
- プーリング層3
- 全結合層1
- 全結合層2

という畳み込みニューラルネットワークのモデルを定義しました。
すると精度は最終的に85%程度まで上昇しました。

56x56の画像といえばこんな感じです。
スクリーンショット 2016-05-24 3.19.36.png
今度は誰だかわかりましたよね?

このくらいの解像度になってようやくえくぼが認識できます。やっぱりこれくらいはほしいですよね。

さて、じゃあもっと解像度を上げて、層を増やせばもっと精度向上できるんだろうな、と思い、
実はさらに層を増やしたり、入力の解像度を高めたりしたバージョンも作っては見たのですが、なかなかクロスエントロピーが収束せず、うまく行きませんでした。原因はよくわかってません。すぎゃーん氏のブログによると112x112の入力で90-95%まで達成できたとのこと。どこで違いが出たのだろう。。

モデルのグラフ

TensorFlowには学習モデルをグラフで表示してくれる機能が付いているので、雑な説明つきで以下に貼っておきます。

スクリーンショット 2016-05-24 3.09.13.png

下から上に向けてデータが流れていくイメージです。

中編おわり

そろそろ眠くなってきたので、つづきはまた後日。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away