LoginSignup
93
100

More than 3 years have passed since last update.

【可視化】リアルタイムで処理、それがFaster-Grad-CAM

Last updated at Posted at 2020-03-17

前回は、深層距離学習にGrad-CAMを適用し、可視化する手法を紹介しました。

今回は、その論文を応用し、リアルタイムでGrad-CAMを処理できる
「Faster-Grad-CAM」を開発したので紹介します。

heat.gif
(RaspberryPi3 modelBで実行)

※コードはこちら
※こちらはPythonデータ分析勉強会#18の発表資料です。

結論から

  • Faster-Grad-CAMを使えば、通常のGrad-CAMより10倍以上高速化することが可能
  • しかも、前回ご紹介した技術を使っているため、高精度化にも成功

デモ

まずは試してみたいという方は、こちらにパーとグーを見分けるデモ機を作りました。
パーのときは反応せず、グーにするとFaster-Grad-CAMが発動します。

環境

  • Keras 2.2.4
  • TensorFlow 1.9.0
  • sklearn 0.19.0
  • Opencv 3.4.3.18
  • RaspberryPi3 modelB(もしくはPC)

使い方

カメラを準備し、以下のコマンドで実行できます。

python3 janken_demo.py

RaspberryPi3で5~6FPSの速度です。
さらに、得られたヒートマップを二値化すれば、枠で囲うこともできます。

手法の紹介

※前回の記事をご覧になっていない方は、こちらも併せてご覧ください。

Faster-Grad-CAMの適用条件はただ一つ、深層距離学習を使うことです。
TripletでもArcFaceでも適用できます。

前回紹介した論文では、深層距離学習にTripletを使っていました。
「Faster」ではTripletに代わりにArcFaceを用いています。

※データセットは@karaage0703 さんのjanken_datasetを使っております。

学習方法

まずは、MobileNet V2をArcFaceを使って普通に分類問題で学習させます(step1)。

step1.png

次に、データベースを作ります(step2)。
データベースは、embeded vectorweight vectorの二つがあります。

step2.png

embeded vectorは通常のArcFaceで出力されるものです。
このベクトルを使うことで、分類や異常検知ができます。

weight vectorは、block_16_expan_reluから出力されるベクトルを使って出力yを
偏微分したものです。といっても、通常のGrad-CAMと同じ操作をしているだけです。
weight vector前回の論文でいうと$\alpha_k$に相当します。

次に、Faster-Grad-CAMを学習させます(step3)。

step3.png

まずは、学習データのembeded vectorを求め、k-meansを適用してクラスタリングを行います。
論文ではクラスタ数は50でしたが、Fasterでは10に変更しています。

そして、各クラスタ内でクラスタに属するweight vectorの平均値を計算します。
最後に平均化されたベクトルのうち、Top50を取得し、その番地channel No
平均値の大きさweightを保存します。

※論文では、Tripletを使っているため、似たもの同士はユークリッド距離が近い傾向にありました。
 従って、k-meansを使うと、似たもの同士が同じクラスタに存在する可能性が高いです。一方、
 「Faster」はコサイン類似度が大きいもの同士が似た傾向を持っているため、k-meansで
 似たもの同士でどこまで固まるのか議論の余地があります。

推論方法

最後に、Faster-Grad-CAMで推論します(step4)。

step4.png

まずは、テストデータを学習したMobileNet V2に入れ、テストデータのembeded vector
weight vectorを得ます。そして、得たembeded vectorにk-meansを適用し、属する
クラスタを求めます。上の図では、cluster_Noが1のテストデータが得られたとしています。

次に、属するクラスタのchannel Noweightをロードして、得られたweight vector
適用します。channel Noは、可視化に使うNoだけを指定し、weightはそれらNoに掛ける重みが
保存されています。

最後に、得られたヒートマップをリサイズして、画像と合成しています。

速さの秘密

上の図から分かるとおり、「Faster」の推論で行う処理は以下のとおりです。

  • k-meansの推論
  • 保存データのロードやリサイズ

一方、普通のGrad-CAMは以下の処理を行っています。

  • ArcFaceの層とソフトマックス層の計算
  • 偏微分の計算
  • リサイズ

step2.png

step2では、前述したとおり、普通のGrad-CAMとほぼ同じ操作をしています。

「Faster」では、推論時、GAP以下の処理は不要なためネットワークから削除しています。
しかし、普通のGrad-CAMではそれが必要で、余分に計算時間がかかっています。

ただ、その計算時間は微々たるもので、一番重たいのはやはり偏微分です(上の図でいうと
"Normal" Grad-CAM)。どうしてここまで時間がかかるのか真剣に考えたことはありませんが、
とりあえず重いです。画像のサイズによりますが、1秒以下で終わったことはありません。

一方、「Faster」の方は一番重くてもk-meansくらいなので、可視化の計算はCPUでも楽々できます。
下手したら数msecです。

学習方法

提供しているデモ機は、自分の画像で学習させることも可能です。
学習方法は、こちらTrain_Faster-Grad-CAM.ipynbを参考にしてください。

ハイパーパラメータの調整

  • thresh_hand
    _janken_demo.py内でこの値をいじると、グーとパーの判定基準を変えることができます。
    この値の範囲は0~1で、ArcFaceのコサイン類似度に相当します。この値を大きくすると、グーは
    認識しやすくなりますが、パーの認識は厳しめになります。

  • thresh_OD
    _ janken_demo.py内でこの値をいじると、物体検出風の枠の閾値を変えることができます。
    この値を大きくすると、枠は小さめになり、小さくすると、枠は大きめになります。

  • ArcFaceのパラメータ
    ArcFaceのパラメータは主に、sとmの二つ存在し、分類精度に影響を与えます。2分類や3分類程度
    であれば、初期値から変える必要はないかと思います。10分類以上になると、いじる必要があるかも
    しれませんが、面倒な方はAdaCosを使う手もあります。AdaCosはパラメータを自動的に決めて
    くれる手法です。

応用例

異常部分の可視化

自己教師あり学習を使った異常検知では、Grad-CAMを適用することで「異常部分を
可視化すること」ができました。

余分な線や欠けた線があると「異常」となり、異常部分を枠で囲ってくれます。

オートアノテーションツール

以前にアノテーションを自動化するツールを作りました。

これは、Grad-CAMで二値化したマップにベイズ最適化を適用し、過不足なく
アノテーションするものです。

k_means (1).gif

この事例にFasterを適用すると、Grad-CAMで5秒かかっていたものが、ほぼ一瞬で
処理することができます。全体として、動作時間を25%削減することができます。
(20秒→15秒/画像1枚)

まとめ

  • Faster-Grad-CAMを使えば、通常のGrad-CAMより10倍以上高速化することが可能
  • しかも、高精度化にも成功
  • 速さの秘密は、推論時に偏微分を使っていないこと
93
100
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
93
100