gradcam热力图可视化pytorch
时间: 2025-07-05 22:10:06 浏览: 8
### 使用 PyTorch 实现 GradCAM 热力图可视化
为了实现 GradCAM 热力图可视化,可以遵循特定的方法来处理卷积神经网络 (CNN),并利用目标类别的梯度信息。具体来说,在 PyTorch 中实现这一功能涉及几个重要步骤。
#### 准备工作
确保安装了必要的库,如 `torch` 和 `torchvision`。如果尚未安装这些包,则可以通过 pip 安装它们:
```bash
pip install torch torchvision
```
#### 导入库和定义辅助函数
加载所需的模块,并创建一些帮助函数用于后续操作,比如获取特征映射以及计算类别激活映射(Class Activation Mapping, CAM)。这部分代码展示了如何设置环境以便于执行 GradCAM 计算[^1]。
```python
import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import torch
import torch.nn.functional as F
from torchvision.models import resnet50
from torchvision.transforms import Compose, Resize, ToTensor, Normalize
def show_cam_on_image(img: np.ndarray,
mask: np.ndarray,
use_rgb: bool = False) -> None:
heatmap = cv2.applyColorMap(np.uint8(255 * mask), cv2.COLORMAP_JET)
if use_rgb:
heatmap = cv2.cvtColor(heatmap, cv2.COLOR_BGR2RGB)
superimposed_img = heatmap * 0.4 + img
plt.imshow(superimposed_img.astype('uint8'))
plt.axis('off')
plt.show()
```
#### 构建模型与前向传播过程中的钩子(Hook)
为了让 GradCAM 正常运作,需要修改 CNN 的结构以保存中间层输出。这通常通过注册正向传递期间的 hook 来完成。下面的例子说明了怎样为 ResNet50 添加这样的 hooks。
```python
class FeatureExtractor():
""" Class for extracting activations and
registering gradients from targetted intermediate layers """
def __init__(self, model, target_layers):
self.model = model
self.target_layers = target_layers
self.gradients = []
def save_gradient(self, grad):
self.gradients.append(grad)
def __call__(self, x):
outputs = []
self.gradients = []
for name, module in self.model._modules.items():
x = module(x)
if name in self.target_layers:
x.register_hook(self.save_gradient)
outputs += [x]
return outputs, x
model = resnet50(pretrained=True).eval() # 加载预训练模型并设为评估模式
feature_extractor = FeatureExtractor(model, ['layer4']) # 注册hook到最后一层conv layer上
```
#### 执行反向传播并提取梯度
一旦有了上述准备好的组件,就可以继续进行实际的 GradCAM 运算了。这里的关键在于对选定的目标类别执行一次完整的前向-后向遍历,从而获得相应的梯度信息。接着基于这些梯度构建最终的热力图[^2]。
```python
def get_gradcam(feature_maps, grads_val):
weights = np.mean(grads_val, axis=(1, 2))
cam = np.zeros(feature_maps.shape[1:], dtype=np.float32)
for i, w in enumerate(weights):
cam += w * feature_maps[i, :, :]
cam = np.maximum(cam, 0)
cam /= np.max(cam) + 1e-7
return cam
target_category = ... # 设定想要可视化的类别索引
output = model(input_tensor.unsqueeze_(0)) # 输入图像张量给模型做预测
one_hot_output = torch.FloatTensor(output.size()).zero_()
one_hot_output[0][target_category] = 1
model.zero_grad()
# 反向传播得到指定类别的损失相对于输入图片的梯度
output.backward(one_hot_output)
features, _ = feature_extractor(input_tensor.unsqueeze_(0))
grads_val = feature_extractor.gradients[-1].detach().numpy(), grads_val)
img = input_tensor.permute(1, 2, 0).numpy()*std + mean # 将标准化后的tensor转换回原始范围内的ndarray形式
show_cam_on_image((img*255).astype(int), cam)
```
阅读全文
相关推荐


















