Grad-CAM

Grad-CAM(Gradient-weighted Class Activation Mapping)提供了一种可视化视角来表明图像不同区域的卷积激活的重要程度。

实现:zjykzj/cam

CAM and Grad-CAM

CAM(Class Activation Mapping)来自于论文Learning Deep Features for Discriminative Localization使用CAM可以可视化模型在识别某一类别时图像不同区域的卷积激活的影响,也就是说,可视化图像不同区域的重要程度。其操作流程如下图所示:

模型整体架构如上图所示,通过多个卷积层进行特征提取,然后使用全局平均池化层(GAP/Gloabl Average Pooling)进行特征融合,最后使用全连接层得到分类输出。CAM就是将输出层权重反向投影到卷积特征,来可视化图像不同区域的重要程度。前向实现如下:

  1. 假定\(f_{k}(x,y)\)表示最后卷积层第\(k\)个滤波器在空间位置\((x,y)\)的激活输出;
  2. 针对第\(k\)个滤波器输出结果,执行全局平均池化得到激活\(F^{k}=\sum_{x,y}f_{k}(x,y)\)
  3. 对于给定类别\(c\),其最后全连接层输出\(S_{c}=\sum_{k}w_{k}^{c}F_{k}\),其中
    1. \(w_{k}^{c}\)表示针对第\(k\)个滤波器的池化层输入\(F^{k}\),以及输出类别为\(c\)对应的全连接层权重向量;
    2. 也就是说,\(w_{k}^{c}\)表示\(F_{k}\)对于类别\(c\)的加权因子;
  4. 最后类别\(c\)的分类概率计算如下:\(P_{c}=\frac{exp(S_{c})}{\sum_{c}exp(S_{c})}\)

注意:上述操作中忽略了偏置(bias),仅关注于矩阵操作。通过上述操作后,可以得到

\[ F_{k}=\sum_{x,y}f_{k}(x,y) \]

\[ S_{c}=\sum_{k}w_{k}^{c}\sum_{x,y}f_{k}(x,y)=\sum_{x,y}\sum_{k}w_{k}^{c}f_{k}(x,y) \]

定义\(M_{c}\)表示针对类别\(c\)的类激活图(class activation map),逐空间元素的计算如下:

\[ M_{c}(x,y)=\sum_{k}w_{k}^{c}f_{k}(x,y) \]

所以,\(S_{c}=\sum_{x,y}M_{c}(x,y)\)\(M_{c}(x,y)\)可以直接表明图像分类为\(c\)时,每个空间位置\((x,y)\)的卷积激活的重要程度。一句话总结,CAM(类激活图)就是逐空间针对卷积特征进行线性加权的结果

Grad-CAM来自于论文Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization,针对CAM进行了改进,通过反向传播算法计算得到特征梯度作为加权因子,不再局限于分类网络以及全局平均池化层的使用。

实现

通过可视化卷积激活在不同不同区域的变化,可以发现一些很有趣的事情,比如:

  • 更大判别力的模型拥有更聚焦的识别区域,
1
python imagenet/Grad-CAM.py --arch resnet18 imgs/dog.jpg

1
python imagenet/Grad-CAM.py --arch resnet50 imgs/dog.jpg

  • 针对同一个分类类别,不同架构模型具有相似的高激活区域,
1
python imagenet/Grad-CAM.py --arch mobilenet_v2 imgs/dog.jpg

  • 对于不同类别,其对应的高激活区域会有差别,比如类别Norwich_terrier的识别区域,
1
python imagenet/Grad-CAM.py --arch resnet50 --cls-name Norwich_terrier imgs/dog.jpg