推荐一个计算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)

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

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
相关推荐
CoderIsArt11 小时前
机器学习(1)安装Pytorch
人工智能·pytorch·机器学习
钰见梵星18 小时前
PyTorch 基础知识
人工智能·pytorch·python
fydw_71518 小时前
Pytorch nn.Module详解
人工智能·pytorch·python
木觞清1 天前
PyTorch与TensorFlow的对比:哪个框架更适合你的项目?
人工智能·pytorch·tensorflow
taoqick1 天前
nn.EmbeddingBag把offsets之间的进行归约,offsets从0开始
pytorch·python·深度学习
Allen-Steven1 天前
《Stable Diffusion绘画完全指南:从入门到精通的Prompt设计艺术》-配套代码示例
人工智能·pytorch·深度学习·stable diffusion·prompt·checkpoint
赵钰老师1 天前
【深度学习】遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)
pytorch·深度学习·目标检测·机器学习·数据分析·cnn·transformer
不打滑的西瓜皮2 天前
机器学习数理基础:从概率到梯度下降的全面解析
图像处理·人工智能·pytorch·python·深度学习·机器学习
taoqick2 天前
对PosWiseFFN的改进: MoE、PKM、UltraMem
人工智能·pytorch·深度学习