AIの「根拠」を可視化せよ!ブラックボックスをこじ開けるCAMの正体

こんにちは。ゆうせいです。

これまで、GAPやGMPといった「データのまとめ役」についてお話ししてきましたね。実はこれらの技術、ただAIをスリムにするだけではないんです。

AIの世界では長年「なぜその答えを出したのか、人間には分からない」というブラックボックス問題が弱点とされてきました。しかし、今回紹介する「CAM(Class Activation Map)」を使えば、AIが画像のどこを見て判断したのかを、まるでサーモグラフィーのように赤く光らせて見ることができるんです!

研修の受講生からも「これが一番感動した!」という声が多いこの技術、その魔法のタネ明かしをしていきましょう。


AIの「着眼点」をカンニングする

例えば、AIが写真を見て「これは猫です」と答えたとします。でも、もしかしたらAIは猫そのものではなく、横にある「キャットフード」を見て判断しているかもしれません。これでは、キャットフードがない場所では猫を認識できなくなってしまいますよね。

CAMは、AIが判断に使った「重要度」を画像の上にヒートマップとして重ね合わせる技術です。これを使えば、AIがちゃんと「猫の顔や体」を見て判断しているかどうかを一目でチェックできるのです。


CAMが成立する「3つの条件」

CAMを実現するには、実はこれまでに学んだ技術の組み合わせが必要になります。

  1. 畳み込み層:画像から「特徴(耳、毛なみなど)」の地図をたくさん作る。
  2. Global Average Pooling (GAP):各地図の「平均的な反応の強さ」を1つの数値にする。
  3. 重み(重み付き和):どの地図がそのクラス(例えば「猫」)にとって重要かを計算する。

仕組みを数式で覗いてみよう

ある地図 f_k(x, y) が「耳担当」だったとします。GAPによってその地図の平均値 w_k が出されます。

最終的な「猫らしさ」のスコアは、すべての地図(map)の平均値(average)に、それぞれの重要度を掛け算して足したものになります。

\text{Score} = \sum w_k \times (\text{map}_k \text{average})

CAMでは、この「重要度 w_k 」を、平均化する前の「元の地図」に直接掛け合わせます!

\text{CAM}(x, y) = \sum w_k \times f_k(x, y)

これにより、重要度が高い地図(例えば耳担当)が強く反応している場所が、最終的なヒートマップでも赤く光るというわけです。


CAMを利用するメリットとデメリット

AIの「思考」を見える化することには、計り知れない価値があります。

項目内容
メリットAIの誤判定の原因(背景に騙されている等)を特定し、改善のヒントにできる。
メリット医療診断AIなどで「なぜこの病気だと判断したか」を医師に説明する根拠になる。
デメリットネットワークの最後にGAPが使われている必要があり、構造が制限される。
デメリット最後に全結合層が何層も重なっている古いAIモデルにはそのまま適用できない。

CAMのサンプルコード

このGoogle Colabのリンクをご覧ください。

import numpy as np
import torch
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import models
from torchvision.models import ResNet50_Weights
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget
from pytorch_grad_cam.utils.image import show_cam_on_image

# 1. モデルの準備
weights = ResNet50_Weights.DEFAULT
model = models.resnet50(weights=weights)
model.eval()

target_layers = [model.layer4[-1]]

# 2. 画像の読み込みと前処理(ファイル名を cat.jpg に変更)
input_path = 'cat.jpg' # ここを修正しました
try:
    rgb_img = Image.open(input_path).convert('RGB')
except FileNotFoundError:
    print(f"エラー: {input_path} が見つかりません。Colabにアップロードされているか確認してください。")
    raise

rgb_img_resized = rgb_img.resize((224, 224))
img_float = np.array(rgb_img_resized) / 255.0

transform = weights.transforms()
input_tensor = transform(rgb_img).unsqueeze(0)

# 3. 予測結果からトップのクラスとラベル名を取得
outputs = model(input_tensor)
target_category = outputs.argmax(dim=1).item()
predicted_label = weights.meta["categories"][target_category] # クラス名(品種名)を取得

print(f"AIの診断結果: {predicted_label} (Class ID: {target_category})")

# 4. Grad-CAMの実行
cam = GradCAM(model=model, target_layers=target_layers)
targets = [ClassifierOutputTarget(target_category)]

grayscale_cam = cam(input_tensor=input_tensor, targets=targets)
grayscale_cam = grayscale_cam[0, :]

# 5. 可視化
visualization = show_cam_on_image(img_float, grayscale_cam, use_rgb=True)

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title(f"Original: {predicted_label}")
plt.imshow(rgb_img_resized)
plt.axis('off')

plt.subplot(1, 2, 2)
plt.title(f"Grad-CAM Heatmap ({predicted_label})")
plt.imshow(visualization)
plt.axis('off')
plt.show()

現場での活用:信頼されるAIへ

現在では、CAMをさらに進化させた「Grad-CAM」という手法が主流です。これはGAPを使っていないモデルでも、偏微分の考え方を応用して「どの場所が重要か」を計算できる優れものです。

AIに「信じてください」と言うのではなく、AIに「ここを見て判断しました」と言わせる。この透明性こそが、AIが社会の重要なインフラになるための絶対条件なんです。


これからの学習の指針

「見える化」の技術を知ると、AI開発の視座が一段階上がります。

  1. Pythonのライブラリ(PyTorchやTensorFlow)を使って、既存のモデルにGrad-CAMを適用してみる。
  2. AIがわざと間違えるような画像(猫の着ぐるみを着た人など)を読み込ませ、どこに注目しているか観察する。
  3. 「説明可能なAI(XAI)」というキーワードで、最新の信頼性向上技術を調べてみる。

AIはもう、何を考えているか分からない不気味な存在ではありません。私たちが正しく「レンズ」を当ててあげれば、彼らは饒舌にその根拠を語ってくれるのです。

さて、AIの「中身」を覗く準備は整いました。次は、AIが学習中に陥る最大の罠「過学習」を防ぐために、あえて一部の脳細胞を眠らせる「ドロップアウト」という奇策についてお話ししましょうか?

セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。