卷积神经网络的可视化——热力图Grad CAM

前言

在大部分人看来,卷积神经网络是一种黑盒技术,通过理论推导,以及梯度传播,去不断逼近局部最优解。这也导致人们对于神经网络研究进展的缓慢,因为这种黑盒模型无法给出研究人员进行改进的思路。所幸的是,近几年来的论文,也从常规的神经网络结构转向神经网络可视化,目的是让我们能看见卷积神经网络“学习”到了什么,神经网络是怎么判别物体的类别

今天就要为大家介绍一种卷积神经网络可视化的技巧,它发表于一篇论文,名叫Grad CAM,通过热力图来对神经网络进行可视化。

简介

热力图通常是用来对类别进行划分的图像,它有点像红外成像图,温度高的地方就很红,温度低的部分就呈现蓝色。同理,我们使用热力图可以以权重的形式来展现,神经网络对图片的哪一部分激活值最大。比如输入到猫狗分类,如果卷积神经网络判别是猫,那它的热力图普遍分散在猫身上,而至于它是根据猫的哪一部分来判别,就利用了热力图的原理

原理

我们卷积神经网络进行分类,最后一层通常是softmax层,其最大值对应的就是分类类别

我们从这个最大概率分类类别的节点出发,进行反向传播,对最后一层卷积层求得梯度,然后对每一张特征图求出均值,最后我们取出 最后一层卷积层的激活值,与前面我们对梯度特征图的均值进行相乘,这个过程可以理解为,每个通道的重要程度与我们卷积激活值进行相乘,就相当于是一个加权操作。最后根据这个乘积值生成一个热力图,与原图进行叠加。

代码实现

这里笔者参考的是deep learning with python。环境为最新的keras框架
模型是自己简单训练出来的一个vgg16模型,只不过将对应的卷积层改为depthwise Separable卷积,全连接层也调小了很多,最后做的是一个多分类(五个类别)

先看一下我自己实现的vgg16代码

from keras import layers
from keras import models
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator

base_dir = './train_data/'

train_data_gen = ImageDataGenerator(rescale=1./255,
                                    rotation_range=30,
                                    horizontal_flip=True)
train_generator = train_data_gen.flow_from_directory(
    base_dir,
    target_size=(224, 224),
    batch_size=20,
    class_mode='categorical'
)

model = models.Sequential()
mode
  • 12
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Grad-CAM(Gradient-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 引擎的计算图记录功能,以避免梯度计算对模型参数的影响。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值