卷积神经网络因为其在很多任务上效果很好但是其学到的内容和规则很难用人类理解的方式来呈现(相对于传统机器学习算法,例如决策树或者逻辑回归等),所以被很多人认为是“黑盒”。如果我们可以可视化
- 网络模型里面的中间层的激活结果;
- 或者网络学到的过滤器是提取什么类型特征的;
- 或者是图像中哪些位置的像素对输出有着强烈的影响,换句话说,输出对哪些位置的像素值比较敏感。
那么无疑对我们理解模型,或者分析模型为什么犯错有着很实际的用处。
所幸的是,2013年以来,随着深度学习的发展,也有一些很好的论文研究深度学习中模型可视化这一领域并取得了一些成果。例如,2014年ECCV上Zeiler的《Visualizing and Understanding Convolutional Networks》研究了第一个问题,此文也是可视化这一领域的开山之作;2012年NIPS上Alex Krizhevsky发表的AlexNet应该是最早可视化过滤器的文章;而针对第三个问题,2016年的CAM 《Learning deep features for discriminative localization》,2017年的Grad-CAM 《Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization》和紧接着2018年的Grad-CAM++ 《Grad-CAM++: Generalized Gradient-based Visual Explanations for Deep Convolutional Networks》这一系列的文章都对类激活图(Class Activation Map)这种可视化技术做了比较充分的研究。
本文结合论文和有关资料,详细描述一些Grad-CAM这种可视化的方法,它除了原理简单,效果好之外,还有个很大的优点就是不需要重新训练模型也不需要改造模型结构。
欢迎探讨,本文持续维护。
N/A
CAM是Class Activation Map类激活热力图的意思,比如说,一个分类网络AlexNet,输入一个既包含着一只狗,又包含着一只猫的猫狗合影图片,它会输出一个1000维度的概率向量,其中有两个分量分别对应着图片分类为猫和图片分类为狗的概率。那么这两个概率,与图片中的哪些部分的关系更大,那些部分的关系更小呢?换句话讲,输出的概率的大小与输入图片中哪些区域的像素值更敏感呢?如果找出这个敏感度的一个热力图,越敏感的地方,温度越高,越不敏感的地方,温度月底,那就是类激活热力图,如下图中c和i所示就分别时预测猫类别的CAM和预测狗类别的CAM,它很直观地告诉了我们模型是“看到了”猫的身体所以才认为图中有猫,“看到了”狗的脸才认为图中有狗。
如上图所示,计算CAM的过程很简单,这里以计算上上图中猫类的CAM为例说明:
首先,计算最后一层Softmax输出中猫类概率yc对最后一层特征图所有像素Aij的偏导数,即,其中y是Softmax输出的概率向量,c是猫那一类的序号,A是最后一层卷积层输出的特征图,k是特征图的通道维度的序号,i和j分别时宽高维度的序号。
然后,把yc对特征图每个像素的偏导数求出来之后,取一次宽高维度上的全局平均。这一步得到的akc就是c类相对于最后一层卷积层输出的特征图的第k个通道的敏感程度。
第三步,把这个akc当作权重将最后一层特征图加权,线性组合起来。
第四步,把这个组合起来的值(其实是个二维map),送入ReLU激活函数处理一下输出。第三步和第四步写在一起就是。
这个L是一个二维map,它就是我们要的类别激活热力图。
这里有几个需要说明的地方,
- 原始论文《Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization》中说yc应该是“the score for class c”,“before the softmax”,但是一些实现代码里面,直接用的是Softmax层的输出,我觉得也是可以的,这里是忠于了文章的思想但是没有完全终于原文(私以为原文是为了让它的Grad-CAM方法适用于更多的问题领域),尽信书不如无书;
- 计算akc时用到的global average pooling这个方法比较粗糙,在后面2018年出来的Grad-CAM++论文中有进一步的细化和推广;
- 为什么第四步里面要加一个ReLU?因为我们需要得到的是和c类概率得分正相关的热力图,如果特征图A上某个位置通过a加权得到的值为负数,那么它更可能属于不是c类的别的类。另外,基于这个前提,我们是不是也可以去取一个f(x) = min(0,x)这样,来看看图片中哪些位置最抑制预测c类的分数的提高呢?挺有意思的。
- 因为最后一层特征图的分辨率不一定和输入图片一致,为了得到和输入图片一样大小的热力图,最后还有个resize操作,不要忘记了。
Chollet的《Python深度学习》这本书5.4节有比较简洁的实现(也有GitHub上的Jupyter notebook),在GitHub上jacobgil分别用Keras和PyTorch也实现了Grad-CAM。
本文简介了类激活可视化方法Grad-CAM来可视化深度学习模型是怎么做预测的,它对我们理解模型原理,做错误Case分析都有很大的帮助。
- Visualizing and Understanding Convolutional Networks
- Understanding Neural Networks Through Deep Visualization
- Learning deep features for discriminative localization
- Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization
- Grad-CAM++: Generalized Gradient-based Visual Explanations for Deep Convolutional Networks
- 《Python深度学习》
- pytorch-grad-cam
- keras-grad-cam