EfficientNetで分類したお米の特徴をGrad-CAMで可視化してみる

AI実装

Grad-CAMは畳み込みニューラルネットワーク(CNN)で学習したモデルがどこに着目しているかを可視化する手法です。CNNは強力なツールである反面、何を根拠としているか見えません。いわゆるブラックボックスとなっています。CNNに信頼性を持たせるためXAI(説明可能なAI)の可視化手法として有名なのがGrad-CAMです。過去に説明可能なAIについてブログを書いていますので良かったら併せて読んでみてください。

今回は、前の記事でつくったEfficientNetモデルでGrad-CAMを試してみようと思います。

EfficientNetモデルのつくり方は↓をご覧ください

VizGradCAM について

今回はGrad-CAMのコードとしてVizGradCAMをつかわせていただきます。

GitHub - gkeechin/vizgradcam: vizgradcam is the fastest way to visualize GradCAM with your Keras models.
vizgradcam is the fastest way to visualize GradCAM with your Keras models. - GitHub - gkeechin/vizgradcam: vizgradcam is the fastest way to visualize GradCAM w...

VizGradCAMはKerasでつくったモデルに対しGrad-CAMを簡単に適用することができます。CNNがどこに着目しているか確認するレベルであれば十分です。

Githubのコードをダウンロードして中身をEfficientNetモデルの作業ディレクトリ下へ保存してください。gradcam.pyがコピーできればOKです。

EfficientNetでGrad-CAMを適用するために

Grad-CAMをEfficientNetモデルで適用しようとすると少しクセがあります。前の記事でTensorflow_hubをつかったEfficientNetモデルの実装をしましたが、このままではGrad-CAMを適用できません。従ってEfficientNetのモデルをつくる部分のコードのみを書き直します。

このサイトを参考にしました。

!pip install efficientnet #efficientnetライブラリをインストール
from efficientnet.tfkeras import EfficientNetB0
eff = EfficientNetB0(
    include_top=False,
    weights='imagenet',
    input_shape=(64,64,3))
x = tf.keras.layers.GlobalAveragePooling2D()(eff.output)
output = tf.keras.layers.Dense(3, activation='softmax', name='last_output')(x)
model = tf.keras.Model(inputs=eff.inputs, outputs=output, name='model')
model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 64, 64, 3)]  0                                            
__________________________________________________________________________________________________
stem_conv (Conv2D)              (None, 32, 32, 32)   864         input_1[0][0]                    
__________________________________________________________________________________________________
stem_bn (BatchNormalization)    (None, 32, 32, 32)   128         stem_conv[0][0]                  
__________________________________________________________________________________________________
stem_activation (Activation)    (None, 32, 32, 32)   0           stem_bn[0][0]                    
_________________________________________________________________________________________________
 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
省略
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__________________________________________________________________________________________________
top_conv (Conv2D)               (None, 2, 2, 1280)   409600      block7a_project_bn[0][0]         
__________________________________________________________________________________________________
top_bn (BatchNormalization)     (None, 2, 2, 1280)   5120        top_conv[0][0]                   
__________________________________________________________________________________________________
top_activation (Activation)     (None, 2, 2, 1280)   0           top_bn[0][0]                     
__________________________________________________________________________________________________
global_average_pooling2d (Globa (None, 1280)         0           top_activation[0][0]             
__________________________________________________________________________________________________
last_output (Dense)             (None, 3)            3843        global_average_pooling2d[0][0]   
==================================================================================================
Total params: 4,053,407
Trainable params: 4,011,391
Non-trainable params: 42,016
_________________________________________________________________________________________________

Grad-CAMはconv層の最終層における特徴量マップ情報を利用しているため↑のように各層が出力されるようなモデルの書き方が必要なのかな?と思います。 Tensorflow_hubをつかうと各層の情報はKeras Layerという一つのまとまりで表現されてしまうのでNGです。

ここさえ乗り越えれば、あとは学習重みデータをつかってVizGradCAMで可視化するだけです。

VizGradCAMを実装する

VizGradCAMの実装はすごく簡単です。↓のコードでOKです。上記でも記載してますが、作業ディレクトリ下へgradcam.pyをコピーした状態で実行してください。

from gradcam import VizGradCAM
import cv2
VizGradCAM(model, test_img,plot_results=True, interpolant=0.5)
#modelはEfficientNetモデルの重み, test_imgはGrad-CAMを適用したい画像

実行すると↓の様な画像が表示されます。

赤い部分をCNNが着目したということになります。

EfficientNetモデルはちゃんとお米のをみているか

Grad-CAMの結果とオリジナル画像を比較してみます。

Grad-CAM(正解ラベル:緑、間違えたラベル:赤)
オリジナル画像

狙い通りお米の一部を着目して分類しているケースと、関係ない背景部分に着目しているケースが混在しています。EfficientNetモデルがうまく特徴に着目しているのか。。。ちょっと分からない結果となりました。

Grad-CAMでEfficientNetモデルが何処を見ているか可視化することはできました。ただし、可視化すればEfficientNetモデル(CNN)の考えていることが全てわかるということは無いようです。XAI(説明可能なAI)への道は険しそうですが、もっと色んな方法を試していきたいですね😅

関連書籍・撮影機材

ディープラーニングやお米の栽培で参考書籍を紹介します。バケツでも栽培できるようなので気になる方は是非やってみてください👍

画像/動画撮影はiphone11ですが、できるだけブレないように三脚・グリップで固定して使っています。関連機材を紹介します。

コメント

タイトルとURLをコピーしました