
機械学習で乃木坂46を顏分類してみた
- web上から五人の画像を100枚ずつ取ってくる
- 画像から顔部分を取り出して保存、テストデータの取り出し
- 画像の水増し
- モデルを定義して、学習
- テスト(顔を四角く囲って、その人の名前を出力)
説明はこんなもんにして、彼女らの可愛さについて語りたいところですが、そういうブログではないので、少し技術的なことを書きます。
今回はjupyterを使って作業を進めました。notebook形式なので結果が見やすく初心者にはいい環境でした。環境は以下の通りです。
- macOS:10.13.1
- python:3.6.1
- openCV:3.3.0
- keras:2.1.2
まずはじめに、カレントディテクトリ上に、origin_image,face_image,face_scratch_image,test_imageディテクトリを追加しました。
目次[非表示]
- 1.Google APIを用いた画像取得
- 2.画像から顔部分を取り出し
- 3.画像の水増し
- 4.モデルを定義して、学習
- 5.テスト
- 6.最後にちょっとだけ感想
Google APIを用いた画像取得
これを取得することで、Googleが提供するリソースにアクセスすることができます。今回でいえば、例えば「西野七瀬」と画像検索した時の上位100枚のURLを取得できます。APIのコードについてはこちらのブログを参考にしました。
以下のコードでは、keywordsリスト["生田絵梨花","齋藤飛鳥","白石麻衣","西野七瀬","橋本奈々未"]で画像検索、URLを取得後、画像に変換し、jpgファイルとしてorigin_imageディテクトリに保存という流れになっています。100枚以上取れればいいんですが、600枚くらいで403Error Forbiddenが出てしまいました。また、1検索あたりの最大取得URLは100枚のようです。101枚以上を指定するとHTTP Error 400 – Bad Requestが出てしまいました。
画像から顔部分を取り出し
まずopencvに搭載されているカスケード分類器を利用して、顔を検出します。今回は正面顔を検出するhaarcascade_frontalface_alt.xmlという分類器を使いました。
引数のminNeighborsの値が重要でした。以下のコードでは、検出した顔部分をトリミングし、全て64×64ピクセルにリサイズして(学習器に入れやすくなる為)、jpg形式でface_imageディテクトリに保存ということをしてます。実際ここで、100内60~70枚ほどに減ってしまいます。
その理由として、正面顔しか検出しないため、正面を向いていても傾いた顔は検出できないため、などが挙げられます。ここで唯一、自力でデータを操作しなければなりません。検出できなかったものは自分の目でチェックして自力でトリミングした方がいいデータができると思いますし、またツーショットなどは別の人の顔も一緒に検出してまったので、そういうのはラベルを変えるor削除しましょう。
僕の場合は、この作業をしている時が一番こうf...幸せでした。またこのタイミングででテストデータを取り出しました。
カスケード分類器に関してはこのブログがおすすめです。

オリジナル写真
画像の水増し
顔検出してテストデータを抜き取って残った数が、それぞれ50~70枚ほどになってしまい、これでは学習データとして不足するだろうと思ったので、左右反転、閾値処理、ぼかしを使って水増しを行います。これで学習データが8倍になります。(それでも少ない気がしますが。。)。画像の水増しは自動でやってくれるツールがありますが、自分でかけるコードは自分で書きたいので(キリッ)。このドキュメントは、画像の前処理を行う上で、もっともスタンダードな方法の一つです。これを知ってれば早いです。
参考:画像の前処理 - Keras Documentation
ImageDataGenerator関数はリアルタイムにデータ拡張しながら,テンソル画像データのバッチを生成します。
以下のコードでは水増し加工をしたものをface_scratch_image1ディテクトリに保存してます。また、学習器に入れるために画像リストXと正解ラベルリストyを用意して、それぞれ追加していきます。
モデルを定義して、学習
さて、一人当たり400~600枚ほどのデータを取得できました。いよいよ本番です。これを学習させる学習器を構築して、学習させます。水増しした練習データは合計で1832枚、テストデータ57枚です。
これ以降のディープニューラルネットワークのモデルの作成・学習はKerasというライブラリを使用しました。KarasはTheanoやTensorFlowといった機械学習のライブラリのラッパーです。さて、学習器の構造ですが、CIFAR-10のサンプルを参考に作って見ました。それと、keras documentationは日本語のドキュメントなのでわかりやすかったです。畳み込み層、プーリング層の数を増やしたり、epoch数-精度のグラフをみて、精度の高かったものがこちらです。またこれらのブログも参考になりました。
参考:TensorFlowによるももクロメンバー顔認識(前編) - Qiita
ディープラーニングでザッカーバーグの顔を識別するAIを作る①(学習データ準備編) - Qiita
epochs数を60にしてテストデータの精度は70%になりました。低いですね。理由として、みんな可愛いから特徴量が低い、取得データ不足などが挙げられます。全結合層の関数は一般的にはrelu関数の方が良いとされますが、試して見たところ今回はsigmoid関数の方が精度が高かったです。浅めの学習モデルだとsigmoid関数の方がいいのかもしれません。
epochs-accグラフはこちらです。

テスト
見分けるモデルが完成したので、これを使ってアイドルの顔を見分けていこうと思います。画面に文字を追加したり、四角く囲ったりするのもopencvを用いました。いろんな画像でテストして見ると、生田絵梨花と誤認識する確率が高いように思いました。
コードは、画像中の顔を検出、四角くくくる、モデルで測定、名前を記入、といった感じです。
最後にちょっとだけ感想
今回のコードの制作期間は二日くらいでしたが、その6,7割くらいの時間を素材集めに使ってしまいまして、機械学習についてもっと触れたかったなと。でも、細かい文法などの知識が固まったかなあ。もっと人数の増やした、良い学習モデルを作ってサービスとしてリリースしたいなと思いました。また、さらなる上達のために、今回の応用として転移学習にも挑戦していきたいです。
追記
モデル学習のテストデータに水増しされた写真も入っていたことを指摘いただきまして、修正しました。テストデータに水増しされたデータを使うと、テストデータの精度は高くなりますが、オリジナルのデータに弱いモデルとなります。その他細かいコードの手直しをしました。
AI、機械学習それからディープラーニングの経験はないけど、「AIをどのように活用するのだろう?」や「Aidemy Premium Planを受講して、私でもきちんと続けられるだろうか?」など、少しでも気になることがございましたら、ぜひ一度気軽に無料相談会にお越しいただき、お悩みをお聞かせください!
最後までご覧くださりありがとうございました。