CNN可视化/可解释性

在当前深度学习的领域,有一个非常不好的风气:一切以经验论,好用就行,不问为什么,很少深究问题背后的深层次原因。从长远来看,这样做就埋下了隐患。举个例子,在1980年左右的时候,美国五角大楼启动了一个项目:用神经网络模型来识别坦克(当时还没有深度学习的概念),他们采集了100张隐藏在树丛中的坦克照片,以及另100张仅有树丛的照片。一组顶尖的研究人员训练了一个神经网络模型来识别这两种不同的场景,这个神经网络模型效果拔群,在测试集上的准确率尽然达到了100%!于是这帮研究人员很高兴的把他们的研究成果带到了某个学术会议上,会议上有个哥们提出了质疑:你们的训练数据是怎么采集的?后来进一步调查发现,原来那100张有坦克的照片都是在阴天拍摄的,而另100张没有坦克的照片是在晴天拍摄的……也就是说,五角大楼花了那么多的经费,最后就得到了一个用来区分阴天和晴天的分类模型。

大家不妨思考下,假如我们手里现在有一家医院所有医生和护士的照片,我们希望训练出一个图片分类模型,能够准确的区分出医生和护士。当模型训练完成之后,准确率达到了99%,你认为这个模型可靠不可靠呢?大家可以自己考虑下这个问题。
好在学术界的一直有人关注着这个问题,并引申出一个很重要的分支,就是模型的可解释性问题。

从可视化的内容来分,主要的三种可视化模式:

  1. 特征可视化:又可分为两类—(1)直接将卷积核输出的feature map可视化,即可视化卷积操作后的结果,帮助理解卷积核的抽取到了什么特征。(2)与第一种方法类似,但不再是可视化卷积层输出的feature map,而是使用反卷积与反池化来可视化输入图像的激活特征。
  2. 卷积核参数的可视化,对卷积核本身进行可视化,对卷积核学习到的行为进行解释。
  3. 类激活图可视化(CAM/grad-CAM),通过热度图,了解图像分类问题中图像哪些部分起到了关键作用,同时可以定位图像中物体的位置。

反卷积和导向反向传播

“看懂”卷积神经网(Visualizing and Understanding Convolutional Networks)
Visualizing and Understanding Convolutional Networks翻译总结
关于CNN模型的可解释问题,很早就有人开始研究了,姑且称之为CNN可视化吧。比较经典的有两个方法,反卷积(Deconvolution)和导向反向传播(Guided-backpropagation),通过它们,我们能够一定程度上“看到”CNN模型中较深的卷积层所学习到的一些特征。当然这两个方法也衍生出了其他很多用途,以反卷积为例,它在图像语义分割中有着非常重要的作用。(ps:目前网上有一些关于反卷积的文章,我感觉没有说的特别到位的,当然也有可能是大家理解的角度不同,但是另外一些解读那就是完全错误的了,包括某乎。不得不说,真正要深入理解反卷积还是要去啃论文,很多人嫌麻烦总是看些二手的资料,得到的认识自然是有问题的。当然这些都是题外话,我也有写一篇关于反卷积的文章的计划。看以后的时间安排)
从本质上说,反卷积和导向反向传播的基础都是反向传播,其实说白了就是对输入进行求导,三者唯一的区别在于反向传播过程中经过ReLU层时对梯度的不同处理策略。在论文《STRIVING FOR SIMPLICITY:
THE ALL CONVOLUTIONAL NET》
中有着非常详细的说明,如下图所示:
在这里插入图片描述
在这里插入图片描述
虽然过程上的区别看起来没有非常微小,但是在最终的效果上却有很大差别。如下图所示:
在这里插入图片描述

  • 使用普通的反向传播得到的图像噪声较多,基本看不出模型的学到了什么东西。
  • 使用反卷积可以大概看清楚猫和狗的轮廓,但是有大量噪声在物体以外的位置上。
  • 导向反向传播基本上没有噪声,特征很明显的集中猫和狗的身体部位上。

虽然借助反卷积和导向反向传播我们“看到”了CNN模型神秘的内部,但是却并不能拿来解释分类的结果,因为它们对类别并不敏感,直接把所有能提取的特征都展示出来了。在刚才的图片中,模型给出的分类结果是猫,但是通过反卷积和导向反向传播展示出来的结果却同时包括了狗的轮廓。换句话说,我们并不知道模型到底是通过哪块区域判断出当前图片是一只猫的。要解决这个问题,我们必须考虑其他办法。

CAM(class activation map) 类激活图

为了解决反卷积和导向反向传播对类别不敏感的问题,提出了CAM

在这里插入图片描述
CAM图与上图(热成像仪的图像)类似,当我们需要模型解释其分类的原因时,它以热力图(Saliency Map)的形式展示它的决策依据,如同在黑夜中告诉我们哪有发热的物体。

对一个深层的卷积神经网络而言,通过多次卷积和池化以后,它的最后一层卷积层包含了最丰富的空间和语义信息,再往下就是全连接层和softmax层了,其中所包含的信息都是人类难以理解的,很难以可视化的方式展示出来。所以说,要让卷积神经网络的对其分类结果给出一个合理解释,必须要充分利用好最后一个卷积层
在这里插入图片描述

CAM借鉴了很著名的论文Network in Network中的思路,利用GAP(Global Average Pooling)替换掉了全连接层。可以把GAP视为一个特殊的average pool层,只不过其pool size和整个特征图一样大,其实说白了就是求每张特征图所有像素的均值。
在这里插入图片描述
GAP的优点在NIN的论文中说的很明确了:

  1. 由于没有了全连接层,输入就不用固定大小了,因此可支持任意大小的输入;
  2. 此外,引入GAP更充分的利用了空间信息,且没有了全连接层的各种参数,鲁棒性强,也不容易产生过拟合;
  3. 还有很重要的一点是,在最后的 mlpconv层(也就是最后一层卷积层)强制生成了和目标类别数量一致的特征图(有N个类别,就有N个特征图),经过GAP以后再通过softmax层得到结果,这样做就给每个特征图赋予了很明确的意义,也就是categories confidence maps

我们重点看下经过GAP之后与输出层的连接关系(暂不考虑softmax层),实质上也是就是个全连接层,只不过没有了偏置项,如图所示:
在这里插入图片描述
从图中可以看到,经过GAP之后,我们得到了最后一个卷积层每个特征图的均值,通过加权和得到输出(实际中是softmax层的输入)。需要注意的是,对每一个类别C,每个特征图k的均值都有一个对应的w,记为 w k c w_{k}^{c} wkc。CAM的基本结构就是这样了,下面就是和普通的CNN模型一样训练就可以了。
训练完成后才是重头戏:我们如何得到一个用于解释分类结果的热力图呢?其实非常简单,具体步骤为:

(1)比如说我们要解释为什么分类的结果是羊驼,我们把羊驼这个类别对应的所有 w k c w_{k}^{c} wkc取出来,求出它们与自己对应的特征图的加权和即可。
(2)由于这个结果的大小和特征图是一致的,我们需要对它进行上采样,叠加到原图上去,如下所示。
在这里插入图片描述
这样,CAM以热力图的形式告诉了我们,模型是重点通过哪些像素确定这个图片是羊驼了。

GAP-CAM tensorflow实现
https://github.com/jazzsaxmafia/Weakly_detector
GAP-CAM pytorch实现
https://github.com/metalbubble/CAM/blob/master/pytorch_CAM.py

grad-CAM

源码地址
https://github.com/Ankush96/grad-cam.tensorflow
https://github.com/kazuto1011/grad-cam-pytorch

前面看到CAM的解释效果已经很不错了,但是它有一个致死伤,就是CAM要求修改原模型的结构,导致需要重新训练该模型,这大大限制了它的使用场景。如果模型已经上线了,或着训练的成本非常高,我们几乎是不可能为了它重新训练的。于是乎,Grad-CAM横空出世,解决了这个问题。
Grad-CAM的基本思路和CAM是一致的,也是通过得到每对特征图对应的权重,最后求一个加权和。但是它与CAM的主要区别在于求权重 w k c w_{k}^{c} wkc的过程。

  • CAM通过替换全连接层为GAP层,重新训练得到权重
  • 而Grad-CAM另辟蹊径,用梯度的全局平均来计算权重。
  • 事实上,经过严格的数学推导,Grad-CAM与CAM计算出来的权重是等价的。

在这里插入图片描述

grad-CAM整体框架图
注意这里和CAM的另一个区别是,Grad-CAM对最终的加权和加了一个ReLU,**加这么一层ReLU的原因在于我们只关心对类别c有正影响的那些像素点**,如果不加ReLU层,最终可能会带入一些属于其它类别的像素,从而影响解释的效果。
实现方法:

1)在CAM中,我们根据最后一层的FC学到的权重作为对应feature map的权重,而后upsampling到原像素空间,看起来利索应当,但当我们在最后一次适用conv之后,得到对应的feature map,之后多次使用FC,我们如何计算feature map对应的权重呢?
 这里有一个小问题,我们为什么使用conv阶段最后一次得到的feature map呢?因为最后一次conv得到的feature map是前面多次conv+ReLU+pooling的结果,具有最强的空间信息和语义信息,随后的FC和softmax所提取的信息已经很难理解,所以我们若想实现CNN的可视化,必须好好利用最后一次conv得到的feature map。

 # Get last convolutional layer gradient for generating gradCAM visualization
 #用预测对卷积最后一层输出求梯度
      target_conv_layer = vgg.vgg19_net['pool5']
      target_conv_layer_grad = tf.gradients(y_c, target_conv_layer)[0]

在这里插入图片描述

Guided Grad-CAM(导向反向传播和Grad-CAM的结合)

1)问题:虽然Grad-CAM可以很好的类别判别能力,也可以将相关区域定位出来,但是其不具备像素空间梯度可视化(比如导向反向传播和反卷积这种细粒度重要性可视化)的方法
 2)解决问题:
  2.1)首先对图像使用插值法进行上采样
  2.2)然后将导向反向传播和Grad-CAM结合起来,实现可视化

grad-CAM与guided grad-CAM 直观效果

使用Grad-CAM对分类结果进行解释的效果如下图所示:
在这里插入图片描述

guided Grad-CAM: Grad-CAM 还可以与其他经典的模型解释方法如导向反向传播相结合,得到更细致的解释。
在这里插入图片描述

扩展

其实无论是CAM还是Grad-CAM,除了用来对模型的预测结果作解释外,还有一个非常重要的功能:就是用于物体检测。大家都知道现在物体检测是一个非常热门的方向,它要求在一张图片中准确的识别出多个物体,同时用方框将其框起来。物体检测对训练数据量的要求是非常高的,目前常被大家使用的有 PASCAL、COCO,如果需要更多数据,或者想要识别的物体在这些数据库中没有话,那就只能人工来进行标注了,工作量可想而知。
仔细想想我们不难发现,Grad-CAM在给出解释的同时,不正好完成了标注物体位置的工作吗?虽然其标注的位置不一定非常精确,也不一定完整覆盖到物体的每一个像素。但只要有这样一个大致的信息,我们就可以得到物体的位置,更具有诱惑力的是,我们不需要人工标注的方框就可以做到了。

LIME

但如果我们面对的是一个黑盒,对其内部一无所知,只能提供一个输入并得到相应的输出值(比如别人的某个模型部署在线上,我们只有使用它的权利),在这种情况下,我们如何判断这个模型是否靠谱?能不能像Grad-CAM那样对分类结果给出一个解释呢?
针对这个问题,LIME作为另一套办法,即使我们对模型一无所知也能够对它的行为作出解释。

参考文献:

凭什么相信你,我的CNN模型?(篇一:CAM和Grad-CAM)
凭什么相信你,我的CNN模型?(篇二:万金油LIME)
Yes, Deep Networks are great, but are they Trustworthy?
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值