最後にブログを書いてから1ヶ月が経ってしまいました。この期間の振り返りもしたいところですが、それはまた別の機会に。Learningを使って画像を分類したりする遊びをしていましたのでそれについて。yuheinakasaka.github.io画像をアップするとJuice=Juiceというハロプロのアイドルにどれだけ似てる顔なのかを判定できるサイトです(herokuの無料枠で動いてるのでサーバーはいともカンタンに死にます...😇)。見せられるようなコードではないですが、一応ソースコードも置いておきます。YuheiNakasaka/yukanya-front何番煎じかわからないほどにこの手の遊びは行われているのでコードやアルゴリズムの細かい解説は他の記事に譲ります。以下ではどのように作りあげていったかについてその思考過程と試行錯誤したポイントを中心に書いていきます。画像収集まずは学習データが必要なので画像を収集します。先にも書きましたが対象の画像にはJuice=Juiceというハロプロのアイドルを選びました。理由は単純に好きだからです。後々やっていくことになりますが、初心者が分類タスクに取り組む上で一番しんどいのは画像収集とそのラベル付けになります。その作業に耐えられる対象を選ぶことが重要です。収集元としてはブログとGoogle画像検索を利用しました。コードはこんな↓感じになります。https://github.com/YuheiNakasaka/yukanya/blob/master/scraping.pyブログから画像を取得する方法もありますが、その場合はメンバーごとにフォルダへ保存しようと試みても二人で写っていたり別の人が写っていたりする写真が多いのであまり効率が良くないです。手軽なのはGoogle画像検索です。メンバーの名前で検索して取得した画像をメンバーごとに別フォルダに保存していきます。一通り収集し終えたら次はノイズを除いていく作業です。メンバーの名前で検索していてもブログほどではないにせよ結構間違った人の画像が含まれていたりするので地道に手作業で除いていきます。顔画像を切り抜く次は顔診断を作りたいので全身画像から顔だけを切り取る作業をします。簡単なところだとOpenCVのHaar-Like特徴を利用した顔検出機能が便利です。labs.eecs.tottori-u.ac.jpただ単純にHaar-Likeを使うだけだとちょっと斜めになった顔に対応できません。アイドルは自撮りをするときに顔を斜めにしがちなので結構ミスクリップが発生します。次に考えつくのが画像を回転させることです。斜めになっている画像を回転させて正面を向くようにすればOpenCVのHaar-Likeでもうまく検知できるようになります。memo.sugyan.comこれで一件落着かと思いきや、これにも弱点があります。それは顔を検知しすぎてしまうことです。10°20°30°40°のように回転させてそれぞれに顔認識をさせていくと10°20°30°のそれぞれで顔が検知できてしまったりします。本当は10°の時の1枚で良いのに3枚分同じ顔画像が生成されてしまいます。避けられるならノイズはできるだけ減らしたいです。そこで最終的にはface_recognitionという顔認識ライブラリを使いました。dlibという機械学習ライブラリをベースにしているらしく、斜めでもボケていてもかなりの精度で顔を認識してくれます。github.comこれを使って収集した画像から顔をクリップしてメンバーごとに保存します。適当なCNNによるアプローチまずはCNNで顔画像を分類できるようにして、未知の画像に対してメンバーの誰に似ているかを診断しようという作戦です。先の顔画像を使ってまずは適当にCNNのモデルを構築して訓練しました。モデルの構築にはKerasを使っています。Learningで遊んだ時はChainerを使ってやっていたんですが、今はKerasを使っている情報が多いなという印象でした。理由はわかりませんが、確かに単純なネットワークの構築からCNN/RNNのような定番のネットワーク、そしてVGGやResNetのような一般物体認識データセットで学習済みのモデルが簡単に使えるので敷居の低さを感じます。今はDeepLearningのライブラリはどういう使い分けがなされているのか、知ってる人いたら教えてください。64x64で学習を行いました。accuracy:0.7042801556420234精度は約70%。原因はデータが少ないことだと思い、水増しに手をつけました。水増しとは元画像を回転させたりノイズを入れたりして学習データを増やす手法です。products.sint.co.jpやりすぎると過学習を引き起こしてしまうのですが、うまく使えば元データの少なさを補填してくれます。accuracy:0.90056903264450449割くらいまで伸びました。わーいという感じでしたが、過学習しまくってるので未知の画像でうまく識別できません。これでは使えないので別の手法を試します。VGG19を使った転移学習を用いたアプローチ転移学習とはすでに学習済みの優秀なモデルを利用して全結合層の部分だけ学習し直すという手法になります。特徴を捉えるのに優秀になっているモデルを使うことで特徴抽出のところをチートしちゃおうという感じです。今回はVGG19というモデルを使って転移学習を行いました。コードはこんな感じです。64x64と、水増ししすぎてた感があったので半分に減らして再度学習。結果はこんな感じでデータ量を減らしたのに91%と精度が上昇。さっきのモデルだとうまく識別できなかった未知の画像(川村文乃ちゃんは宮本佳林ちゃんに似ていると有名)もしっかり分類されました。Camという手法です。Camは簡単にいうと、AIがどこを見て画像を判断しているのかを可視化するものです。予測時の判断に大きく影響を与えた(微分係数がデカイ)箇所の特徴を強調します。Camの画像がわかりやすかったです。彼女は大きな口がチャームポイントなのですが、学習済みモデルもそこをうまく捉えて判断しているようでした。これは人間が金澤朋子を本人であると識別するときとほぼ同様の着眼点なので面白いですね。Colaboratoryここまでの作業は自前のMacBookProを使っていましたが、ある程度画像が増えてきたりサイズを128x128や256x256のように大きくしていくにつれて次第に学習時間が爆増していきます。自分の場合は10000枚の128x128サイズの画像をVGG16の転移学習で訓練させようとしたあたりで10時間以上かかることが判明したのでGPUを使うことに決めました。Colaboratoryを使うと無料で13GBのGPUが使えます。これが本当に恐ろしいほど便利で久しぶりにGoogleのサービスで感動しました。何ができるのかとか制約は以下のQiitaにざっくりまとめられた記事がわかりやすいです。Colabを使って回帰予測や分類タスクを行えるのがサラリーマンの普通のスキルになっているという未来が見えました。Colabを使ったオンライン講義資料あたりをやってみると良いかもしれないです。学習モデルさえできてしまえば、あとはweb上で遊べるようにするだけです。当初は簡単なCNNのネットワークを使ったモデルを想定していたのでtensorflow-jsを使って全てフロントエンドで完結するぞ!という見立てだったのですが、VGG19に手を出してしまったことで学習済みモデルだけで100MBほどになってしまったので諦めました。フロントで全て完結しないとなるとサーバー側でモデルを使って予測を行うAPIを作る必要があります。いっても特に難しいことはいらないのでAPIはPythonのFlaskを使いHeroku上で動かしました。sizeは350MBほどになりました。Herokuの無料枠は500MBまでしかUploadできないのでさらに大きな学習済みデータを設置したい場合などは注意が必要です。devcenter.heroku.comJuice=Juice顔診断ではフロントエンドで顔認識をするような作りになっています。いうのも、Herokuでface_recognitionを使うのが難しそうだったのと、顔認識に割と時間がかかるのでアクセスが詰まることが予想されたからです。できる限りフロントでできることはフロントで済ませておきたい。いうことでJavascript向けの顔認識ライブラリのfaceapi.jsを利用しました。これまた非常に精度が高い。関わらず必要なモデルファイルが6MB程度のサイズ。これなら何とか実用に耐えそうです。github.comあとはVue.jsを使って適当にフロントをこしらえて、最低限の静的ファイルをServiceWorkerにキャッシュするようにすれば完成です。-ここまではCNNベースで分類した結果を使う作戦でやってきました。この手法だと限られたクラスの中でどれに近いかを選択するので、例えば全く顔が似ていないおじさんの写真でもメンバーの誰かには似ているという結果を出してしまいます。それは如何とも許しがたい。いうことでアプローチを変えて、類似度を計算する作戦にします。類似度を計算するには、それぞれの画像の特徴量を取得してその距離の測れば良さそうです。lossという損失関数を計算をしています。techblog.zozo.com顔画像の場合にはfacenetというモデルがあり、これが特徴量抽出に使えます。qiita.comfacenetを使って学習データから特徴抽出したらあとはpickleでまとめてherokuにアップロードします。予測対象の画像がきたら、その画像からも同様にfacenetで特徴抽出して、あとは簡単にユークリッド距離を計算して一番近いものを類似している顔として使うという感じです。https://github.com/YuheiNakasaka/yukanya-api/blob/master/app.py#L55これによっておじさんをJuice=Juiceのメンバーに似てない顔として弾くことができました。Colab便利すぎる分類タスクだとおじさんがアイドルになってしまうfacenetを使った特徴量の距離計算で類似度を出すアプローチを取るとおじさんがアイドルにならなくできる6月頭くらいから初めて土日丸々4日分くらい試行錯誤しました。知識が2,3年前くらいで止まっていて都度学習しながらだったので完成まで思いの外時間がかかってしまいました。Juice=Juiceは6/18からリーダーの宮崎由加が卒業し新メンバーが2人加入した8人体制になってしまったのでこのサイトはすでにoutdatedなのですが、推しの卒業記念ということで良い勉強にもなったし良かったかなと思います。Colabはくそ便利で凄かったのでもっとみんな使った方が良いぞという感じでした。何かある人はブコメか@razokuloverまでどうぞ。面白結婚式/花見/北綾瀬駅/本/ラジオ改変/ハロプロ/TOEIC/Type...3/16~4/5までの振り返りを書く。SUM...2017-10-27「仕事ではじめる機械学習」をざっくり読んだので感想やメモなど仕事ではじめる機械学習を購入したので早速読んでみた。»プロフィールid:razokulover本業はwebエンジニアでGIFMAGAZINEの共同創業者。趣味はハロプロ/声優/将棋/美術/読書など。浅く広く思ったことを書きます。仕事依頼は@razokuloverのDMでどうぞ。#openchat料理が上手い人RSSRSS講読のfeedbanner月別アーカイブ検索はてなブログをはじめよう!razokuloverさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。