Pytorch实现Grad-CAM

因为有一个分类模型始终得不到比较好的结果,所以查阅资料发现可以使用类激活图(CAM)的方式来看看模型究竟学到了什么,是不是重点关注我们希望的区域,所以特此记录一下学习过程。

简介

CAM全称是Class Activation Map,即类激活图。可以理解为模型某次预测中,对哪个区域的响应最大,可以说这个区域很大程度上决定了模型这次预测结果。以猫狗大战为例,如下面这张图
在这里插入图片描述一个任意的分类网络,输入一个既包含着一只狗,又包含着一只猫的猫狗合影图片,它会输出一个2维度的概率向量,分别对应着图片分类为猫和图片分类为狗的概率。那么这两个概率,与图片中的哪些部分的关系更大,那些部分的关系更小呢?换句话讲,输出的概率的大小与输入图片中哪些区域的像素值更敏感呢?如果找出这个敏感度的一个热力图,越敏感的地方,温度越高,越不敏感的地方,温度月底,那就是类激活热力图,如下图中c和i所示就分别时预测猫类别的CAM和预测狗类别的CAM,它很直观地告诉了我们模型是“看到了”猫的身体所以才认为图中有猫,“看到了”狗的脸才认为图中有狗。

网上已经有很多关于CAM原理和公式推导,本人水平不高,就不献丑了,各位感兴趣可以去网上自行搜索。在这里讲讲我个人的理解。一般来说,分类网络将其分成两个部分组成,一个是特征提取部分,一个是分类预测部分。特征提取就是将图片映射成特征图的形式,比如说VGG16的特征层可以将一张224224的图片映射为77*512(即下采样32倍),后面分类部分就是将这个特征图再次映射到类别向量,最后得到预测结果。现在问题来了,我们如何知道模型是根据什么信息对图片做出预测呢?一个比较直观上的思路就是将特征图与原图联系起来,毕竟我们一般都认为特征图是原图语义信息的映射,它反映了模型提取的信息(这语义信息不一定是我们想要的)。所以CAM就是干这种事的,将特征图与原图联系起来,并以热力图的形式展示出来。

CAM和Grad-cam是两种不同生成热力图的方式,关于它们的区别,下面这篇博客讲的很清晰并且附带了Keras版本的复现
keras CAM和Grad-cam原理简介与实现:https://blog.csdn.net/MrR1ght/article/details/92799591

整个流程为:

  1. 求图像经过特征提取后最后一次卷积后得到的特征图(如VGG16 conv5_3的特征图(7x7x512)),大小为H×W×C。
  2. C张feature map在全连接层分类的权重肯定不同,利用反向传播求出每张特征图的权重。注意Grad-cam这里的权重是指梯度的均值,反向传播回来得到的梯度刚开始也是H×W×C(也就是特征图尺寸),然后对每一个通道的H*W求均值,最后得到(C,)的梯度,也就是每张特征图的权重。
  3. 用每张特征图乘以权重得到带权重的特征图(7x7x512),在第三维求均值得到H×W(7x7)的map(np.mean(axis=-1)),relu激活,归一化处理(避免有些值不在0-255范围内)。

代码实现

如果想用pytorch实现Grad-cam,那就必须先了解pytorch中hook机制。下面的博客清晰明了的介绍了相关概念。
博客链接:PyTorch的hook及其在Grad-CAM中的应用
pytorch实现实例:https://github.com/TingsongYu/PyTorch_Tutorial/blob/master/Code/4_viewer/6_hook_for_grad_cam.py

猜你喜欢

转载自blog.csdn.net/weixin_41693877/article/details/107921771
今日推荐