推荐一个计算Grad-CAM的Python库

前言

类激活图CAM(class activation mapping)用于可视化深度学习模型的感兴趣区域,增加了神经网络的可解释性。现在常用Grad-CAM可视化,Grad-CAM基于梯度计算激活图,对比传统的CAM更加灵活,且不需要修改模型结构。

虽然计算grad-cam并不复杂,但是本着能导包就导包的原则,想着去用现成的库。

bash 复制代码
pip install grad-cam

官方文档,开源仓库

简单试用

  1. 加载模型和预训练权重

这里使用PyTorch官方提供的在ImageNet上预训练的Resnet50。注意:这里使用现成的模型参数,也需要用它们提供的图片预处理方式

python 复制代码
from torchvision.models import resnet50, ResNet50_Weights

# 加载ResNet模型和预训练权重
weights = ResNet50_Weights.DEFAULT
model = resnet50(weights=weights)
model.eval()

preprocess = weights.transforms() # 图片预处理方法
  1. 简单读入一张图片
python 复制代码
from PIL import Image

src = 'bird.jpg'
img = Image.open(src)
print(f'The Image size:{img.size}')
img_tensor = preprocess(img)
print(f'The shape of image preprocessed: {img_tensor.shape}')

Output

shell 复制代码
The Image size:(474, 315)
The shape of image preprocessed: torch.Size([3, 224, 224])
  1. 计算Grad-CAM
python 复制代码
rom pytorch_grad_cam import GradCAM

grad_cam = GradCAM(model=model, target_layers=[model.layer4[-1]])   
cam = grad_cam(input_tensor=img_tensor.unsqueeze(0)) # 输入的Shape: B x C x H x W

print(f'Cam.shape: {cam.shape}')
print(f'Cam.max: {cam.max()}, Cam.min: {cam.min()}')

Output

shell 复制代码
Cam.shape: (1, 224, 224)
Cam.max: 0.9999998807907104, Cam.min: 0.0

这里可以看到计算的CAM值的区间是0, 1,一些处理长尾数据的图像增强的方法,通过CAM的值与原图像相乘,得到图像的主体或背景(上下文)。

  1. 可视化
python 复制代码
from pytorch_grad_cam.utils.image import show_cam_on_image
import uuid
import numpy as np
import torch

def vis_cam(cam: np.ndarray, input_tensor: torch.Tensor):
    def normalization(x: np.ndarray, scale=1):   # 归一化
        x_min = np.min(x)
        x_max = np.max(x)
        return (x - x_min) / (x_max - x_min) * scale 
    
    # 底层是cv2实现的所以要求图像形状为 H x W x C
    input_tensor= input_tensor.permute(1, 2, 0).numpy()
    norm_img = normalization(input_tensor)
    
    # 可视化不支持batch,所以要取cam第一个
    vis = show_cam_on_image(norm_img, cam[0], use_rgb=True)
    
    vis_img = Image.fromarray(vis)
    vis_img.save(f'cam_{uuid.uuid1()}.jpg')
    return vis

vis1 = vis_cam(cam, img_tensor)

结果如下,由于图像经过了预处理,size变味了224x224,所以CAM的大小也是这个尺寸。

另外,这个库也提供了其他CAM方法,如GradCAMElementWise,与Grad-CAM相似,将激活值与梯度逐元素相乘,然后在求和之前应用 ReLU 运算。但是简单使用后,肉眼没有察觉差异:

python 复制代码
from pytorch_grad_cam import GradCAMElementWise
grad_cam = GradCAMElementWise(model=model, target_layers=[model.layer4[-1]])
cam = grad_cam(input_tensor=img_tensor.unsqueeze(0)) # 输入的Shape: B x C x H x W
vis2 = vis_cam(cam, img_tensor)

将它们做一个横向对比,从左至右分别是原图、GradCAM,GradCAMElementWise

python 复制代码
img_hstack = np.hstack([img.resize(size=(224, 224)), vis1, vis2])
Image.fromarray((img_hstack).astype(np.uint8)).save('cam_compare.jpg')            



其他

有一点很重要,但是文中并没有使用,关于ClassifierOutputTarget的使用,文档中它的一种用法:

python 复制代码
cam = GradCAM(model=model, target_layers=target_layers, use_cuda=args.use_cuda)

targets = [ClassifierOutputTarget(281)]

grayscale_cam = cam(input_tensor=input_tensor, targets=targets)

输入的参数是图片对应的target,也就是one-hot标签里面的1的下标,但由于使用的是预训练模型,所以不知道具体的标签。而当cam这里的targets=None时,会自动选择得分最高的类。

关于grad-cam还有许多功能,这里仅仅介绍了计算cam和可视化的部分。

运行环境

txt 复制代码
grad-cam                  1.5.0                    pypi_0    pypi
pytorch                   2.2.2           py3.12_cuda12.1_cudnn8_0    pytorch
相关推荐
海天一色y1 天前
模型部署的「通用语」:ONNX 转换
pytorch·onnx
Thomas.Sir1 天前
第26课:工业零部件外观缺陷检测系统:从学术Demo到产线工程的重构实战
pytorch·ai
Zguigo2 天前
【CUDA6】CUDA Stream 是什么,为什么 CUDA 是异步执行,如何正确测量 GPU 时间以及多个任务如何重叠执行
人工智能·pytorch·深度学习
论文复现现场2 天前
RTX 3090 24GB 适合科研吗?单卡论文复现、PyTorch 显存检查与 OOM 排错
人工智能·pytorch·python·深度学习·cuda·rtx3090
论文复现现场3 天前
AutoDL、算家云与公有云 GPU 怎么选?环境复现、计费与断点恢复对比
pytorch·深度学习·云计算·gpu
盘古开天16663 天前
PPO算法代码实战(三):PyTorch从零实现PPO求解CartPole
人工智能·pytorch·算法
Είναι η κοπέλα3 天前
PyTorch 安装与验证
人工智能·pytorch·python
盼小辉丶4 天前
PyTorch强化学习实战(27)——进化策略在强化学习中的应用
人工智能·pytorch·深度学习·强化学习
weixin_447195294 天前
【无标题】
pytorch·python
bigdata-余建新4 天前
week2
人工智能·pytorch·深度学习