GAP CAM Grad-CAM Grad-CAM++的解释

转载于:https://www.zhihu.com/question/274926848/answer/473562723

 

卷积层输出的特征映射其实和原图是存在一定的空间对应关系的。把最后一层卷积输出的特征映射处理一下,然后绘制到原图上,就得到了热图(也就是网络模型更关注的区域)。

关键是通过什么方式处理得到的效果比较好?

GAP

让我们小小地绕行一下,先介绍下全局平均池化(global average pooling,GAP)这一概念。为了避免全连接层的过拟合问题,网中网(Network in Network)提出了GAP。GAP层,顾名思义,就是对整个特征映射应用平均池化,换句话说,是一种极端激进的平均池化。

GAP CAM Grad-CAM Grad-CAM++的解释_第1张图片

图片来源:Alexis Cook

图片

从上图可以看到,这维度降得真是彻底啊,本来是 现在生生降到 ,这样大幅简化参数,从而避免过拟合问题。

CAM

从另一方面来说,GAP层的输出,可以认为是“简要概括”了之前卷积层的特征映射。在网中网架构中,GAP后面接softmax激活,ResNet-50中,GAP层后面接一个带softmax激活的全连接层。softmax激活是为了保证输出分类的概率之和为1,对于热图来说,我们并不需要这一约束。所以可以把softmax拿掉。拿掉softmax的全连接层,其实就是线性回归。结果发现,这样一处理,效果挺不错的:

GAP CAM Grad-CAM Grad-CAM++的解释_第2张图片

图片来源:Alexis Cook

这就是CAM算法背后的主要思路。

Grad-CAM

但是CAM要发挥作用,前提是网络架构里面有GAP层,但并不是所有模型都配GAP层的。另外,线性回归的训练是额外的工作。

为了克服CAM的这些缺陷,Selvaraju等提出了Grad-CAM。其基本思路是对应于某个分类的特征映射的权重可以表达为梯度,这样就不用额外训练线性回归(或者说线性层)。然后全局平均池化其实是一个简单的运算,并不一定需要专门使用一个网络层。

GAP CAM Grad-CAM Grad-CAM++的解释_第3张图片

图片来源:arXiv:1610.02391

另外,因为热图关心的是对分类有正面影响的特征,所以在线性组合的技术上加上了ReLU,以移除负值。

GAP CAM Grad-CAM Grad-CAM++的解释_第4张图片

图片来源:arXiv:1610.02391

我们之前提到了分类,其实并不一定要是分类问题,只要是可微的激活函数,其他问题也一样使用Grad-CAM。

顺带提一句,Grad-CAM的作者还将Grad-CAM和可视化所有有贡献的特征的技术Guided-Backprop结合,得到了Guided Grad-CAM,不过这个可视化的效果就不是热图了,所以这里我就不介绍了。

代码 https://github.com/hiveml/tensorflow-grad-cam

Grad-CAM++

为了得到更好的效果(特别是在某一分类的物体在图像中不止一个的情况下),Chattopadhyay等又进一步提出了Grad-CAM++,主要的变动是在对应于某个分类的特征映射的权重表示中加入了ReLU和权重梯度 :

图片来源:arXiv:1710.11063

只需一次反向传播即可计算梯度

下图是CAM、Grad-CAM、Grad-CAM++架构对比:

GAP CAM Grad-CAM Grad-CAM++的解释_第5张图片

图片来源:arXiv:1710.11063

Grad-CAM和Grad-CAM++生成的热图效果是这样的,可以看到,Grad-CAM++的解释性更好:

GAP CAM Grad-CAM Grad-CAM++的解释_第6张图片

图片来源:arXiv:1710.11063

代码

GitHub上有不少Grad-CAM(++)的实现,你可以根据情况自行选择。例如:

  • 如果你用TensorFlow,可以看看Hive开源的hiveml/tensorflow-grad-cam
  • 如果你用PyTorch,可以看看jacobgil/pytorch-grad-cam

当然,你也可以根据Grad-CAM++论文自行实现。


题主修改了问题,说是计算出attention map后如何可视化。我猜是想问如何把attention map可视化成matrix heatmap,类似这样:

GAP CAM Grad-CAM Grad-CAM++的解释_第7张图片

既然已经有attention map了,那可视化只需用颜色或亮度表示权重就可以了(比如,颜色越浓权重越大,或者越亮权重越大)。可以参考datalogue/keras-attention中的代码。

In [1]: import seaborn as sns

In [2]: import numpy as np

In [3]: np.random.seed(0)

In [4]: unf = np.random.rand(10,12)

In [5]: sns.set()

In [6]: ax=sns.heatmap(unf)

In [7]: ax=sns.heatmap(unf,vmin=0,vmax=1)

 

你可能感兴趣的:(网络架构)