Grad-CAM(Gradient-weighted Class Activation Mapping)热力图(内含示例代码)

Grad-CAM是一种用于解释CNN决策过程的技术,通过梯度加权激活区域生成热力图,特别适用于全局平均池化的模型。文章提供了使用Grad-CAM在ResNet和FasterR-CNN目标检测中的应用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Grad-CAM(Gradient-weighted Class Activation Mapping)是一种用于可视化卷积神经网络(CNN)中特定类别的激活区域的技术。Grad-CAM帮助我们理解神经网络在分类任务中的决策过程,特别是它关注哪些图像区域以及这些区域对最终分类结果的影响。

具体来说,Grad-CAM使用神经网络的梯度信息来生成权重,这些权重用于对特定类别的激活区域进行加权。通过将这些权重与卷积层的输出相乘,然后对结果进行求和,可以生成一个热力图,显示了哪些图像区域对于网络分类特定类别最为重要。

Grad-CAM的优势之一是它可以应用于任何使用全局平均池化(global average pooling)的CNN模型,而不需要对网络结构进行修改。这使得Grad-CAM成为一种在解释深度学习模型决策时广泛使用的工具。Grad-CAM的应用包括图像分类、目标检测等领域。

以下是一个简单的示例:

import torch
import torch.nn as nn
from torchvision import models, transforms
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
import cv2
import numpy as np

# 加载预训练的ResNet模型
model = models.resnet50(pretrained=True)
model.eval()

# 选择模型的中间层作为特征提取层,这里以layer3中的第一个卷积层为例
target_layer = model.layer3[0].conv1

# 图像预处理
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 读取并预处理图像
img_path = 'path/to/your/image.jpg'
img = Image.open(img_path).convert('RGB')
img_tensor = transform(img)
img_tensor = Variable(img_tensor.unsqueeze(0))

# 前向传播获取预测分数
logits = model(img_tensor)
pred_class = torch.argmax(logits, dim=1)

# 计算梯度
model.zero_grad()
logits[0, pred_class].backward()

# 获取目标层的梯度
grads = target_layer.weight.grad

# 对梯度进行全局平均池化
pooled_grads = torch.mean(grads, dim=[2, 3])

# 获取目标层的输出特征图
target = target_layer(img_tensor)

# 将梯度与目标层的输出特征图相乘
for i in range(pooled_grads.shape[1]):
    target[0, i, :, :] *= pooled_grads[0, i]

# 计算热力图
heatmap = torch.mean(target, dim=1).squeeze()

# 使用ReLU将负值置零
heatmap = np.maximum(heatmap.detach().numpy(), 0)

# 归一化热力图
heatmap /= torch.max(heatmap)

# 使用OpenCV将热力图叠加到原始图像上
img_array = cv2.imread(img_path)
heatmap = cv2.resize(heatmap, (img_array.shape[1], img_array.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img = cv2.addWeighted(img_array, 0.6, heatmap, 0.4, 0)

# 显示结果
plt.imshow(cv2.cvtColor(superimposed_img, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()

在目标检测算法中,通常使用的是卷积神经网络(CNN)作为特征提取器,其输出被传递给目标检测头部。你可以选择目标检测头部之前的中间层来进行 Grad-CAM 可视化。

以下是一个简单的示例代码,假设你使用的目标检测模型是 Faster R-CNN,并且你想在 RoI pooling 层之前的中间层上应用 Grad-CAM:

import torch
import torch.nn as nn
from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision import transforms
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
import cv2
import numpy as np

# 加载 Faster R-CNN 模型
model = fasterrcnn_resnet50_fpn(pretrained=True)
model.eval()

# 选择中间层,这里以 resnet50_fpn 的 layer3 的第一个卷积层为例
target_layer = model.backbone.body.layer3[0].conv1

# 图像预处理
transform = transforms.Compose([
    transforms.Resize((800, 800)),  # 适应 Faster R-CNN 的输入大小
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 读取并预处理图像
img_path = 'path/to/your/image.jpg'
img = Image.open(img_path).convert('RGB')
img_tensor = transform(img)
img_tensor = Variable(img_tensor.unsqueeze(0))

# 前向传播获取预测
with torch.no_grad():
    output = model(img_tensor)

# 获取目标层的梯度
grads = target_layer.weight.grad

# 对梯度进行全局平均池化
pooled_grads = torch.mean(grads, dim=[2, 3])

# 获取目标层的输出特征图
target = target_layer(img_tensor)

# 将梯度与目标层的输出特征图相乘
for i in range(pooled_grads.shape[1]):
    target[0, i, :, :] *= pooled_grads[0, i]

# 计算热力图
heatmap = torch.mean(target, dim=1).squeeze()

# 使用ReLU将负值置零
heatmap = np.maximum(heatmap.numpy(), 0)

# 归一化热力图
heatmap /= torch.max(heatmap)

# 使用OpenCV将热力图叠加到原始图像上
img_array = cv2.imread(img_path)
heatmap = cv2.resize(heatmap, (img_array.shape[1], img_array.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img = cv2.addWeighted(img_array, 0.6, heatmap, 0.4, 0)

# 显示结果
plt.imshow(cv2.cvtColor(superimposed_img, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()

Grad-CAMGradient-weighted Class Activation Mapping)是一种可视化卷积神经网络(CNN)中模型对输入图像的分类决策的方法。它可以根据模型的输出和梯度信息,生成一个力图,用来表示输入图像中哪些区域对于模型分类结果的影响较大。 以下是使用 PyTorch 实现 Grad-CAM 力图可视化的简单步骤: 1. 加载预训练模型,设置为 evaluation 模式。 ```python import torch import torchvision.models as models model = models.resnet18(pretrained=True) model.eval() ``` 2. 对输入图像进行预处理,并将其送入模型中进行前向传播。 ```python from PIL import Image import torchvision.transforms as transforms # 加载输入图像 img_path = 'example.jpg' img = Image.open(img_path) # 图像预处理 preprocess = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) input_tensor = preprocess(img) input_batch = input_tensor.unsqueeze(0) # 模型预测 with torch.no_grad(): output = model(input_batch) ``` 3. 计算模型输出关于目标类别的梯度。 ```python # 目标类别的下标 target_class = 2 # 计算目标类别的梯度 model.zero_grad() output[:, target_class].backward() # 获取目标类别的输出和特征图 target_output = model.features[-1].forward(input_batch) target_grads = model.features[-1].weight.grad # 计算特征图上每个像素点的权重 weights = target_grads.mean(dim=(2, 3)).squeeze() ``` 4. 根据权重和特征图计算 Grad-CAM 力图。 ```python import numpy as np # 取出特征图 features = target_output.squeeze() # 特征图上每个像素的权重乘以对应像素的值 cam = np.zeros(features.shape[1:], dtype=np.float32) for i, w in enumerate(weights): cam += w * features[i, :, :] # 对力图进行归一化处理 cam = np.maximum(cam, 0) cam = cam / cam.max() # 将力图可视化到原始图像上 from matplotlib import pyplot as plt # 加载原始图像 img = Image.open(img_path) # 将力图缩放到原始图像的大小 cam = np.uint8(255 * cam) cam = np.array(Image.fromarray(cam).resize(img.size, resample=Image.BILINEAR)) # 叠加力图和原始图像 heatmap = plt.get_cmap('jet')(cam)[:,:,:3] heatmap = np.float32(heatmap) heatmap = heatmap / heatmap.max() superimposed_img = heatmap + np.float32(img) superimposed_img = superimposed_img / superimposed_img.max() # 可视化力图和叠加后的图像 fig, ax = plt.subplots(nrows=1, ncols=2) ax[0].imshow(cam, cmap='jet') ax[0].set_title('Grad-CAM heatmap') ax[1].imshow(superimposed_img) ax[1].set_title('Original image with heatmap') plt.show() ``` 这样就完成了 Grad-CAM 力图的生成和可视化。需要注意的是,在计算模型输出关于目标类别的梯度时,需要将模型设置为 eval 模式,并关闭 autograd 引擎的计算图记录功能,以避免梯度计算对模型参数的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值