目录
简介
对CNN有所了解的同学应该知道,网络内部的特征层,随着越靠近最终输出,其特征所代表的语义信息就越明显。我们能够通过中间层的信息,直观的看到网络学习过程中,哪些像素的权重比较高,这些权重高的像素集中在什么区域,进而知道网络对数据理解的基本过程。
一、可视化原理
在CNN的重要工作Alexnet中就已经介绍过了,利用CNN网络在ImageNet上进行分类学习,如果按照最后一层输出的向量为标注,建立一个向量的度量,然后将不同的图像按照该度量,实现匹配,其结果会有高度语义一致性,如图1所示。
图1,基于特征向量计算的近似结果显示。可以看到每一行图像的语义内容关联。
这让人不禁去想,这种相似度与网络对各个节点的激活情况有一种相关性。在网络的最后一层,即马上就有直接输出语义标签的前一层,其特征表示已经具有高度的语义信息。那么,如果我们能够找到一种方法,能够将这种语义信息向前传导,以了解到底是那些像素为语义信息的表示提供了较大的权重,那些像素是可有可无的。那么当向前传导后,我们就可以推出每一层针对像素的一个权重分布。按照这个分布,我们可以直接对图像做一些变换,进而得到特征层对于这些像素的直接影响,用来表达可视化效果。
我们以LayerCAM为例,来介绍可视化实现的基本思路。LayerCAM目标是建立具有更好语义对应的色差图,以表示分类标点对应的语义信息。其核心的想法是重新思考了特征图以及梯度的关系。和其他方法不同的是,LayerCAM利用了梯度来标识在特征图中每一个位置的重要性。看到这里我们就知道了,在判断图像中哪个点对于分类问题的权重更大时,我们只需要将梯度变化作为一个参考,融合进特征向量的反向传递表达,以判断像素的权重即可。具体实现有兴趣的同学可以阅读论文以学习。
论文:LayerCAM: Exploring Hierarchical Class Activation Maps for Localization
二、项目配置
我们使用Github项目pytorch-grad-cam作为我们的平台。该项目获得6.4k星标,在同类项目里算是比较具有代表性的,且集成了许多CNN可视化的经典方法,包括:
Method | What it does |
---|---|
GradCAM | Weight the 2D activations by the average gradient |
GradCAM++ | Like GradCAM but uses second order gradients |
XGradCAM | Like GradCAM but scale the gradients by the normalized activations |
AblationCAM | Zero out activations and measure how the output drops (this repository includes a fast batched implementation) |
ScoreCAM | Perbutate the image by the scaled activations and measure how the output drops |
EigenCAM | Takes the first principle component of the 2D Activations (no class discrimination, but seems to give great results) |
EigenGradCAM | Like EigenCAM but with class discrimination: First principle component of Activations*Grad. Looks like GradCAM, but cleaner |
LayerCAM | Spatially weight the activations by positive gradients. Works better especially in lower layers |
FullGrad | Computes the gradients of the biases from all over the network, and then sums them |
Project Link:https://github.com/utkuozbulak/pytorch-cnn-visualizations
2.1 配置环境
需要配置基于python3.7版本的torch与torchvision,我在网上找到的安装代码为:
pip install torch==1.7.1+cu110
torchvision==0.8.2+cu110 -f
https://download.pytorch.org/whl/torch_stable.html
之后仅需要使用conda安装cudatoolkit就可以。注意,对应的cuda版本为11.0。随后安装对应的cudnn(cudnn不用再指定版本号,系统会自动根据安装cudatoolkit自动选择对应的cudnn版本)。
conda install -c anaconda cudatoolkit=11.0
conda install -c anaconda cudnn
到此,最重要的环境配置已经完成了。为了验证配置,需测试pytorch的GPU模式是否可用:
import torch
flag = torch.cuda.is_available()
if flag:
print("CUDA可使用")
else:
print("CUDA不可用")
ngpu= 1
# Decide which device we want to run on
device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu")
print("驱动为:",device)
print("GPU型号: ",torch.cuda.get_device_name(0))
2.2 代码运行
代码如下(示例):
Usage: python cam.py --image-path <path_to_image> --method <method>
To use with CUDA: python cam.py --image-path <path_to_image> --use-cuda
Instance:
python cam.py --image-path examples\both.png --method gradcam++
指定cam.py并执行对应的方法,就要能够得到特征层的示意图,程序默认使用resnet50作为网络结构来输出特征层数据。也可以通过参数调用可视化显示的方法,包括:GradCAM,ScoreCAM,GradCAM++,AblationCAM,XGradCAM,EigenGradCAM,LayerCAM,FullGrad。作者也实现了根据其他经典网络的实现,具体可以参看下面的代码,这里用VGG来做表示:
#默认
model = models.resnet50(pretrained=True)
target_layers = [model.layer4]
#替换VGG,这里的-1指的是最后一层的意思。VGG19共有37层,你可以指定任意一层来查看输出
model = models.vgg19(pretrained=True)
target_layers = [model.features[-1]]
图2展示一个示例,基于VCG网络和layercam方法。第一列为原始图像,第二列为输出第11层特征结果,第三列最后一层结果。
图2,深度特征可视化,基于VGG19。
总结
深度神经网络的特征层能够被可视化,并且具有不错的语义一致性信息。通过对这些信息进行可视化,可以清楚的知道网络在学习过程中是如何”看“图片,并识别出有效内容的。特征层的可视化对于我们深入理解神经网络的特征学习机制具有及重要的作用。