masato-ka's diary

日々思ったこととか、やったことの備忘録。

AI RC Carは何を見て走行しているのか?

この記事について

この記事ではJetBotやJetRacerで学習させたAIモデルが推論結果を出力する際に、画像上のどこに着目したかを調べます。手法としてはResNet-18のモデルにGrad-CAMを使って推論時に重視した画像上の箇所を可視化させます。

AIの推論とその根拠について

ディープラーニングの推論結果に対して、なぜその出力が出たのか、入力データをどう解釈したかを調べることはAI研究のホットキーワドとなっているようです。詳細はXAIなどで検索されると多くの研究に当たります。AI RC Carにおいても、走行時にステアリング角や、画像座標を出力しますが、いったい画像上の何を見て出力しているかわかりません。もし推論の結果とともに、推論結果が画像上のどの部分に着目したのかを可視化できれば、学習後のモデルがどのくらい走行中の状況をしっかり見ているかがわかります。

Grad-CAM

Grad-CAMはCNNの推論根拠を可視化する手法の一つです。詳しくは詳細に書かれば他の記事を参考いただければと思います。端的に言うと、推論結果出力後、その誤差逆伝播を遡り、変化の激しい(勾配の大きい)パーセプトロンを見つけると言うものです。勾配の大きい箇所は推論結果の計算に大きく寄与した箇所なので、結果的に何を重要と考え、結果を出力できたかがわかるだろうという考え方です。

qiita.com

JetRacerやJetBotの転移学習に用いられるモデルはResNet-18で、PyTorchを利用して実装されています。ResNet-18でPyTorchを利用して可視化を行います。GradCAM自体の実装は以下のブログの内容を利用しました。こちらのブログではResNet-32を利用されていますが、Grad-CAMに渡すレイヤー名などは変わらないので、そのまま利用可能です。

tech.jxpress.net

モデルをGradCAMクラスでラップし、fowardを実行後の処理を変えます。参考にしているブログでは画像が出力となっていますが、AI RC Carの場合は2つの変数が出力になります。JetRacerの場合は出力のうち、推論された画像のx座標の値にのみ着目すればいいため、以下のように実行します。

# sample_image[None, ...]はモデルとロードした画像に合わせて変更、こちらはJetBotのサンプルでの実行方法
model_output = grad_cam.forward(sample_image[None, ...])
grad_cam.backward_on_target(model_output[0][1])

実際の可視化画像

実際に走行時の画像をGradCamで可視化した映像が以下になります。注意したいのは以下は実際にはJetBotで撮影した連続画像をオフラインで処理しています。また、このデータの場合は画像上の座標位置ではなく、ステアリング角を学習した場合のものです。ですが、JetRacerでも同様の方法で可視化が可能です。


Visualize Autopilot with Grad-CAM

この動画ではステアリング変更に、コースの白線が特徴として利用されていることがわかります。また、大きくカーブするシーンでは周囲の環境も特徴としてよく利用されているようです。JetRacerで画像座標を推論する場合もほぼ同じ結果が出ると考えています。

まとめ

GardCAMでの可視化は、直感的に走行に寄与しそうな画像上の特徴にモデルが着目しているかを確認することができます。これにより、学習したモデルがコース上を正確に走れるか検討ができそうです。