CNN卷积层可视化
CNN 可视化
卷积神经网络(CNN)是深度学习中非常重要的模型结构,它广泛地用于图像处理,极大地提升了模型表现,推动了计算机视觉的发展和进步。但 CNN 是一个“黑盒模型”,人们并不知道 CNN 是如何获得较好表现的,由此带来了深度学习的可解释性问题。如果能理解 CNN 工作的方式,人们不仅能够解释所获得的结果,提升模型的鲁棒性,而且还能有针对性地改进 CNN 的结构以获得进一步的效果提升。
理解 CNN 的重要一步是可视化,包括可视化特征是如何提取的、提取到的特征的形式以及模型在输入数据上的关注点等。本节我们就从上述三个方面出发,介绍如何在 PyTorch 的框架下完成 CNN 模型的可视化。
经过本节的学习,你将收获:
- 可视化 CNN 卷积核的方法
- 可视化 CNN 特征图的方法
- 可视化 CNN 显著图(class activation map)的方法
CNN 卷积核可视化
卷积核在 CNN 中负责提取特征,可视化卷积核能够帮助人们理解 CNN 各个层在提取什么样的特征,进而理解模型的工作原理。例如在 Zeiler 和 Fergus 2013 年的paper中就研究了 CNN 各个层的卷积核的不同,他们发现靠近输入的层提取的特征是相对简单的结构,而靠近输出的层提取的特征就和图中的实体形状相近了,如下图所示:
在 PyTorch 中可视化卷积核也非常方便,核心在于特定层的卷积核即特定层的模型权重,可视化卷积核就等价于可视化对应的权重矩阵。下面给出在 PyTorch 中可视化卷积核的实现方案,以 torchvision 自带的 VGG11 模型为例。
首先加载模型,并确定模型的层信息:
1 | |
1 | |
卷积核对应的应为卷积层(Conv2d),这里以第“3”层为例,可视化对应的参数:
1 | |
1 | |
由于第“3”层的特征图由 64 维变为 128 维,因此共有 128*64 个卷积核,其中部分卷积核可视化效果如下图所示:
CNN 特征图可视化方法
与卷积核相对应,输入的原始图像经过每次卷积层得到的数据称为特征图,可视化卷积核是为了看模型提取哪些特征,可视化特征图则是为了看模型提取到的特征是什么样子的。
获取特征图的方法有很多种,可以从输入开始,逐层做前向传播,直到想要的特征图处将其返回。尽管这种方法可行,但是有些麻烦了。在 PyTorch 中,提供了一个专用的接口使得网络在前向传播过程中能够获取到特征图,这个接口的名称非常形象,叫做 hook。可以想象这样的场景,数据通过网络向前传播,网络某一层我们预先设置了一个钩子,数据传播过后钩子上会留下数据在这一层的样子,读取钩子的信息就是这一层的特征图。具体实现如下:
1 | |
这里我们首先实现了一个 hook 类,之后在 plot_feature 函数中,将该 hook 类的对象注册到要进行可视化的网络的某层中。model 在进行前向传播的时候会调用 hook 的call函数,我们也就是在那里存储了当前层的输入和输出。这里的 features_out_hook 是一个 list,每次前向传播一次,都是调用一次,也就是 features_out_hook 长度会增加 1。
CNN class activation map 可视化方法
class activation map (CAM)的作用是判断哪些变量对模型来说是重要的,在 CNN 可视化的场景下,即判断图像中哪些像素点对预测结果是重要的。除了确定重要的像素点,人们也会对重要区域的梯度感兴趣,因此在 CAM 的基础上也进一步改进得到了 Grad-CAM(以及诸多变种)。CAM 和 Grad-CAM 的示例如下图所示:
相比可视化卷积核与可视化特征图,CAM 系列可视化更为直观,能够一目了然地确定重要区域,进而进行可解释性分析或模型优化改进。CAM 系列操作的实现可以通过开源工具包 pytorch-grad-cam 来实现。
- 安装
1 | |
- 一个简单的例子
1 | |
1 | |
使用 FlashTorch 快速实现 CNN 可视化
聪明的你可能要问了,已经 202x 年了,难道还要我们手把手去写各种 CNN 可视化的代码吗?答案当然是否定的。随着 PyTorch 社区的努力,目前已经有不少开源工具能够帮助我们快速实现 CNN 可视化。这里我们介绍其中的一个——FlashTorch。
(注:使用中发现该 package 对环境有要求,如果下方代码运行报错,请参考作者给出的配置或者 Colab 运行环境:https://github.com/MisaOgura/flashtorch/issues/39)
- 安装
1 | |
- 可视化梯度
1 | |
- 可视化卷积核
1 | |












