茨城エンジニアのPython開発日記

茨城のITベンチャー企業ではたらく2年目エンジニア。Pythonで色々なものを作成中。

KaiNDを作っていくぞ会 第2回 --AI改善--


ブログから記事を見つけたい場合はこちら

ブログ地図 - 茨城エンジニアのPython開発日記



こんにちは。
開発メンバー、AI担当のKです。

テレワークが続いているので重度の運動不足です。
ここ最近、簡易的なエアロバイクをGETしたので、毎日使っています。
これで少しでも運動不足を解消したいです。



目次

0. 前回まで

↓前回のブログ
tottorisnow33.hatenablog.com

前回からKaiNDシリーズを拡張・改善しています。一緒にやっているメンバーで以下のように分担しています。

松原: KaiND Web
K   : AI自体の改善
Y   :スマホアプリのUIの改善

前回は松原くんがWebアプリについてブログに載せてくれました。今回は私KによるAI自体の改善について書いていきます。


1. AIがどこを注目しているか可視化したい

リリースしたアプリ(KaiNDシリーズ -Pug or Bulldog-)は、スマホのカメラでかざしたものがパグなのかブルドッグなのかその他なのかを識別するものです。
play.google.com


これからもっと性能を上げたいと思っています。
性能を上げるためには、学習データセットを増やす、Data Augmentationをもっとかける、もっと良いネットワークを使う(今はMobilnetV2を使用)などがあると思います。
何から試すべきか決めるためにも、まずはAIが画像上のどこに注目して、パグ or ブルドッグと判定しているのかを可視化することにしました。


可視化のために、Grad-CAMという論文の手法を使いました。
https://openaccess.thecvf.com/content_ICCV_2017/papers/Selvaraju_Grad-CAM_Visual_Explanations_ICCV_2017_paper.pdf


Grad-CAMは、"grad"という名前がついているように勾配を使います。
最終出力と最後のConv layerの出力で勾配を取る(微分する)ことで、conv layerの特徴マップのどの辺が最終出力に寄与しているかを計算しています。
"最終出力"と言っているのは、パグとかブルドッグとかの結果を出すクラス識別結果の部分です。
一方、"最後のConv layer"というのは、全結合層を適用する前(CNN部分のおしり)の部分です。
Grad-CAMの詳細は、論文や、以下のサイトを参考にしていただけると良いかと思います。
以下のサイトではGrad-CAMの手法を、図を使いながら説明しています。
dajiro.com



2. 参考にしたソース

私たちは Tensorflow の2系を使っています。
同じくtfの2系を使っていてGrad-CAMを実装している人はいないかなと探したところ、見つけました。
Grad CAM implementation with Tensorflow 2 · GitHub

↑こちらのソースを参考にGrad-CAMを実装しました。



ただ、実装するにあたり、アプリで使っているMobileNetV2のソースではうまくいかなそうなので、以前自作したResNetを使いました。
tottorisnow33.hatenablog.com


なぜMobileNetV2のソースではうまくいかなかったのか。
私たちのMobileNetV2のソースでは、以下のブログで書いたようにtensorflow hubを利用しています。

tottorisnow33.hatenablog.com


Section 1で書いたように、Grad-CAMではConv layerの出力が必要となります。
しかし、tensorflow hubで引っ張ってきたモデルは、画像の入力から全結合層による出力まで1つの箱のようになっているみたいでなのです。
私はtensorflow hubで引っ張ってきたモデルからconv layerのところだけ取り出せないかと試しましたが、ちょっとダメそうでした。
一方で、自作したResNetなら各layerを1つ1つ書いていて、conv layerの出力を取り出すのは容易だったのでResNetのソースでGrad-CAMを試しました。

3. 自作ResNetでGrad-CAMをやってみた結果

自作ResNetでやってみた結果は↓です。

色の付き方だけ見ると、パグの耳、目、口元あたりに注目していることがわかります。
ただ、、、↑のツイートに書いたように、実際にGrad-CAMで計算した値は、青い部分と赤い部分で割と同じような値でした。
具体的に言うと、赤いところが1.09、青いところが1.06とかです。
(ちなみに、Grad-CAMの計算結果が大きいほど出力に寄与しています。可視化するときは、最大値を赤、最小値を青となるように正規化してます。)


値が近いので、結局赤いところも青いところも同じくらい注目しているのでは...?
と思いましたが。
これで良いのだろうか。。。。


今回Grad-CAMを初めて使ったので、Grad-CAMで出力した数値の勘所がわかりません。。
そもそも、今回のResNetは事前学習もしてないので、このモデルが微妙なだけかもしれません。。

4. 今後

今回は、AIが画像のどこに注目してパグ or ブルドッグと言っているのか可視化するために、Grad-CAMを使ってみるところまでやりました。
ただ、section 3で書いたように、Grad-CAMの計算結果が似たような値なのがOKなのかわかりません。
また、本当はアプリに入れているMobileNetV2でやりたいところを、事前学習もしていないResNetで試してしまいました。
次は、アプリに入れているモデルと同じく、事前学習されたMobileNetV2をパグ/ブルドッグの識別用にファインチューニングしたモデルを用意して、Grad-CAMを試してみます!