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

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()

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值