【计算机视觉】Class Activation Mapping(CAM、GradCAM) 特征定位、激活图

转载自:https://zhuanlan.zhihu.com/p/51631163

论文来源

《Learning Deep Features for Discriminative Localization 》(2016CVPR)

简单来说,这篇文章主要介绍了两个核心技术:

GAP(Global Average Pooling Layer) 和 CAM(Class Activation Mapping)

GAP(全局平均池化层)

在说全局平均池化之前,我想先谈一谈池化层。我们都知道,池化层的作用是正则化。比如说,这是一个VGG-16的模型。

在这里插入图片描述
我们可以直观的看到,从卷积层到池化层,深度不变,尺寸变小了。我们使用更小尺寸的特征图来表示输入,虽然会丢失一些信息,但是池化层可以防止过拟合,降低维度,保留主要特征的同时减少计算量,减少了参数数量

全局平均池化也一样,可以用来正则化。让我们来看一个容易的例子,我想这个相信可以帮助我们理解全局平均池化。下图展示了三种池化的方式:

在这里插入图片描述

首先是Max pooling(最大池化)。如图所示,最大池化是选择每个子区域的最大值,然后使用子区域的最大值表示该子区域。

Average pooling(平均池化)是指计算出子区域的平均值,用一个平均值来分别表示子区域子区域。

与平均池化类似,Global Average Pooling(全局平均池化)是指计算整个区域的平均值,仅用一个值来表示整个区域。再上图中的计算方式是取整个所有16个像素点的平均。通过下面这个图,我想我们可以更直观的理解GAP。

在这里插入图片描述
左边是一个特征图。高度为6,宽度为6,深度(通道数)为3。当它经过GAP,我们把每一层的参数用一个值表示,这个特征图就变成一个113的特征向量。

第一个提出GAP这个想法的,是一篇叫做《Network in Network》的论文。这篇论文发现用GAP代替全连接层,不仅可以降低维度,防止过拟合,减少大量参数,网络的性能也很不错。

GAP怎么代替全连接层呢?让我们回到一开始的例子。

在这里插入图片描述
如果我们使用GAP,我们必须改变网络的结构。首先我们把最大池化层和全连接层扔掉,只需要将其换成一个尺寸为11512的GAP,即把512个14*14的方针取平均,之后和原网络一样接一个softmax层就可以了。当然这只是我从理论出发举的一个小小的例子,性能是否改变还没有做过实验。

如果我们使用GAP来代替FC,优点是最小化参数数量的同时保持高性能,结构变得简单,也避免了过拟合。但是缺点是和FC相比,GAP收敛速度较慢

虽然这个GAP不是新的技术,但是在论文《Learning Deep Features for Discriminative Localization 》中,他们发现了GAP的一个作用,能保留空间信息并且定位(localization)

尽管在图像级标签上进行了训练,它仍能够区分判别图像区域。 并且在许多任务中它都可以定位判别图像区域,尽管只是训练基于解决分类任务。

CAM(类激活映射)

那么什么是类激活映射呢?CAM是一个帮助我们可视化CNN的工具。使用CAM,我们可以清楚的观察到,网络关注图片的哪块区域。比如,我们的网络识别出这两幅图片,一个是在刷牙,一个是在砍树。通过CAM这个工具,我们可以清楚的看到网络关注图片的哪一部分,根据哪一部分得到的这个结果。

The class activation map is simply a weighted linear sum of the presence of these visual patterns at different spatial locations.
By simply upsamplingthe class activation map to the size of the input image, we can identify the image regions most relevant to the particular category.

使用论文中的话来说,类激活图仅仅是在不同空间位置处存在这些视觉图案的加权线性和。 通过简单地将类激活映射上采样到输入图像的大小,我们可以识别与特定类别最相关的图像区域。如果把这段话翻译成数学语言,就是如下的公式。 f k ( x , y ) f_{k}(x, y) fk(x,y)表示最后一个卷积层经第 k k k 个卷积核输出上某一点 ( x , y ) (x, y) (x,y) 的值, C C C 表示类别。
而类激活映射 M c M_c Mc 则表示所有卷积核输出上单个点对类别C贡献的概率值。

在这里插入图片描述
但是,上式想要成立,就得满足一个条件——输入输出满足线性加法,即:
f k ( x 1 + x 2 , y 1 + y 2 ) = f k ( x 1 , y 1 ) + f k ( x 2 , y 2 ) f_{k}(x_1+x_2, y_1+y_2)=f_{k}(x_1,y_1) + f_{k}(x_2,y_2) fk(x1+x2,y1+y2)=fk(x1,y1)+fk(x2,y2)
,这里的输出指的不是模型最终的输出,而是指最后一个卷积层的输出特征图。
用代码来说明就是这样:
在这里插入图片描述

但是我想这样理解起来是很困难的,所以我想通过图片来解释它。

在这里插入图片描述

这是一个基于分类训练的CNN网络,最左边是输入,中间是很多卷积层,在最后一层卷积层之后接的是全局平均池化层(GAP),最后接一层softmax,得到输出。我们刚刚说过,GAP就是把特征图(卷积层的输出是一幅幅图)转换成特征向量(一个特征图计算得到特征向量的一个元素),所以如果这个特征图的深度是512,那么这个特征向量的长度就是512。我们的输出是Australian terrier,澳大利亚猎犬。我们用Australian terrier这个类对应的权重乘上特征图对应的层,用热力图归一化,即下面一排热力图:W1蓝色层+W2红色层+…+Wn*绿色层=类激活映射(CAM),所以说CAM是一个加权线性和。通常来说,最后一层卷积层的大小是不会等于输入大小的,所以我们需要把这个类激活映射上采样到原图大小,再叠加在原图上,就可以观察到网络得到这个输出是关注图片的哪个区域了。这也就是说可以是任意输入图片的大小和卷积层的深度。

我还想说一点是,因为CAM基于分类,所以被激活的区域是根据分类决定的,即同一个特征图,只更新不同的权重。所以即使我们使用同一张input,就像下面这个例子。

在这里插入图片描述
示例图片的地面真值是圆顶。五张类激活映射分别是前五名预测类别和得分。我们可以看到如果输出是宫殿,网络关注的是整块区域的。如果输出是圆顶,网络只是关注宫殿顶部。

CAM的缺陷

这项技术非常有用但是存在一些缺陷的。首先我们必须改变网络结构,例如把全连接层改成全局平均池化层,这不利于训练。第二是这是基于分类问题的一种可视化技术,用于回归问题可能就没有这么好的效果。

为了解决第一个问题,2017年出现了一种改进的技术叫Grad-CAM,Grad-CAM可以不改变网络结构进行可视化,详见这篇论文《Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization》 (2017 ICCV)。

CAM的应用

CAM也可以应用到很多方面。比如,它可以发现场景中有用的物体:
在这里插入图片描述
弱监督文字检测,它可以关注文字部分即使网络没有训练过文字或者任何注释框:
在这里插入图片描述
利用CAM的可视化技术,我认为CAM也能帮助我们对比模型,选择一个更合适的结构,下图还比较了class-specific saliency map(另一种根据梯度定位类特征区域的方法):

在这里插入图片描述
在日常做实验的时候也可以利用CAM帮助我们发现问题,改进结构:
在这里插入图片描述
这是一个简单的二分类问题,识别图片是猫还是狗,通过CAM技术,我们可以看到网络关注哪里。在第二排第一第二个结果中,网络错误的将猫识别为狗,使用CAM我们可以很快发现错误原因是对于两张图片网络忽略了猫,而关注了其他区域。所以CAM可视化这可以帮助我们理解网络。

Grad-CAM

来源论文:Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization

CAM的局限性就是网络架构里必须有GAP层,但并不是所有模型都配GAP层的。而本文就是为克服该缺陷提出的,其基本思路是目标特征图的融合权重 w k c w_{k}^{c} wkc可以表达为梯度。另外,因为热图关心的是对分类有正面影响的特征,所以加上了relu以移除负值。其实并不一定要是分类问题,只要是可求导的激活函数,在其他问题也一样使用Grad-CAM。特征融合权重计算公式如下:
在这里插入图片描述
其中 y c y^c yc 为目标类别的score。 A i j k A_{ij}^{k} Aijk为需要可视化的目标特征图的坐标。论文里证明了grad-CAM是上文利用GAP一般形式。

两者区别

Grad-CAM 是一种改进后的方法,证明了特征图坐标对某一类的重要性可用梯度表现出来,和原始的CAM有以上区别:

  1. CAM 只能用于最后一层特征图和输出之间是GAP的操作,grad-CAM可适用非GAP连接的网络结构;
  2. CAM只能提取最后一层特征图的热力图,而gard-CAM可以提取任意一层;

输出加softmax的影响

在这里插入图片描述

论文原文中目标类别score是指网络未经过softmax的得分,但是某些代码实现当中也使用了通过softmax后的。二者有无区别?下面我们通过公式推导一下。因为这两种做法仅仅相差一个softmax,所以对softmax的求导。假设softmax层有C个输出,记为: [ a 1 , a 2 , . . . , a c , . . . , a C ] [a^1,a^2,...,a^c,...,a^C] [a1,a2,...,ac,...,aC] 。则softmax输出为:
在这里插入图片描述
则输出 a c a_c ac y c y_c yc 的偏导为,由于这里计算的是目标类别,所以仅需计算对应输出的偏导:
在这里插入图片描述
所以特征融合的权重则变成:

在这里插入图片描述
可以看出,二者的梯度差异就是softmax输出的多一项 a c ( 1 − a c ) a^c(1-a^c) ac(1ac) ,而对于已经训练好的网络,该项为定值。后面特征层进行加权求和,再归一化后,该项 a c ( 1 − a c ) a^c(1-a^c) ac(1ac) 会被消掉。所以通过softmax和不通过softmax在理论上完全一致。但是在实际应用中我发现,加上softmax后,权重 s o f t m a x − a k c softmax-a^{c}_{k} softmaxakc 会变得非常小,就是因为训练的充分好的网络,预测输出 a c a^c ac 的值是非常接近1的,所以 a c ( 1 − a c ) a^c(1-a^c) ac(1ac) 的值非常非常小,存在丢失精度的风险。所以目标类别score建议使用不经过softmax的值

核心代码

仅需要对目标类别的score进行求导, 然后追踪到目标特征图的梯度, 对该梯度进行element-wise求平均(GAP操作)即获得特征融合的权重。具体如下:

# 利用onehot的形式锁定目标类别
one_hot = np.zeros((1, output.size()[-1]), dtype=np.float32)
one_hot[0][index] = 1
one_hot = torch.from_numpy(one_hot).requires_grad_(True) 
# 获取目标类别的输出,该值带有梯度链接关系,可进行求导操作
one_hot = torch.sum(one_hot * output)
self.model.zero_grad()
one_hot.backward(retain_graph=True) # backward 求导
# 获取对应特征层的梯度map
grads_val = self.extractor.get_gradients()[-1].cpu().data.numpy()
target = features[-1].cpu().data.numpy()[0, :] # 获取目标特征输出
weights = np.mean(grads_val, axis=(2, 3))[0, :] # 利用GAP操作, 获取特征权重
cam = weights.dot(target.reshape((nc, h * w)))
# relu操作,去除负值, 并缩放到原图尺寸
cam = np.maximum(cam, 0)
cam = cv2.resize(cam, input.shape[2:])
# 归一化操作
batch_cams = self._normalize(batch_cams)

继 Grad-CAM 之后有陆续延伸出了以下论文,感兴趣可以自己去研究一下:

Grad-CAM++: Improved Visual Explanations for Deep Convolutional Networks
Smooth Grad-CAM++: An Enhanced Inference Level Visualization Technique for Deep Convolutional Neural Network Models
Score-CAM: Score-Weighted Visual Explanations for Convolutional Neural Networks
Ablation-CAM: Visual Explanations for Deep Convolutional Network via Gradient-free Localization

CAM使得弱监督学习发展成为可能,可以慢慢减少对人工标注的依赖,能降低网络训练的成本。通过可视化,就像往黑箱子里打了一个手电筒,让人们可以尝试去理解网络。

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值