CAM基础知识
更新:2023年3月29日22:30:15,发现之前有一些地方有歧义难理解,现在予以更正
参考链接:如何利用CAM(类激活图)动态可视化模型的学习过程
一、作用
类激活图可以显示模型在训练过程中,权重或重心在何处、如何转移,分类模型是根据哪一部分的特征进行判别的。简而言之,就是模仿人类识别物体的过程,随着模型的迭代,找到相关任务的关键部位。
二、定义
CAM列激活图由两部分加权构成:原图+特征图。其中特征图是通过:最后全连接层的参数(权重矩阵W)与最后输出的特征图集合对应相乘再相加(重叠)而形成,即显示模型是依据哪些特征图进行决策分类的。
- 输入:训练集或测试集图片,大小为[224,224,3]
- VGG16预训练卷积层最后一层的特征图大小为7*7,共512张,所以大小为[7,7,512]
- 经过全局平均池化(GAP),512张特征图被降维为长度512的特征向量
- 最后,特征向量与权重矩阵W点积,再经过softmax函数压缩为[0,1]区间内的概率
三、计算
相关论文:
Zhou, Bolei, et al. “Learning deep features for discriminative localization.” Proceedings of the IEEE conference on computer vision and pattern recognition. 2016.
1、 原理
由于采用迁移学习的方式,卷积层冻结固定,所以对于同一张图片,卷积层的输出特征始终不变,模型的分类概率只随着全连接层的权重矩阵W发生变化,这就是模型的学习更新过程。
权重矩阵W可以理解为对长度为512的特征向量的加权,毕竟特征向量是由特征图全局平局池化GAP所得。归根到底是对特征图集合的加权,所以利用特征图集合与权重矩阵相乘,再重叠为一张特征图,就可以模拟模型分类过程中,是依据哪部分区域做出判断的。
举例:假设初始模型在刚开始训练时,利用第10/50/40号特征图作为判断的依据,正确率为78%。使得损失值loss很大,则在反向传播过程中,权重矩阵W会不断更新,在损失函数约束下,找到有效的特征图作为判断的依据,那么当loss小到一定程度,或预测的准确率上升到一定程度,那么此时的模型便学会了判别,有了正确分类的能力。
2、形式
- 模型训练过程CAM
在模型训练过程中,将模型每一次更新的权重矩阵W保存下来,存储为fc.pkl,通过将不同批次不同迭代次数下的权重矩阵与特征图集合进行点乘相加,通过热力图和原图的加权,获得最终的类激活图CAM,可以模拟模型从一开始胡乱猜测,到后续拥有像人一样识别能力IDE过程。效果如下所示。
- 模型训练结果CAM
不需要清楚模型迭代训练过程是如何的,只想观察模型针对输入图片最后特征图的响应结果。则不需要训练模型,只需要加载训练好的模型,获取最后的特征图集合及权重矩阵W,通过opencv相关热力图函数,实现原图和热力图的加权结果可视化。效果如下所示:
3、代码
- 模型训练过程可视化
代码链接:类激活图的动态可视化
特点:针对迁移学习冻结所有卷积层,只对最后一层参数更新,框架使用的keras。数据集使用猫狗数据集 - 模型训练结果可视化
代码将在下文贴出,并给出相关步骤的注释和解释
特点加载预训练好的模型,迁移学习,框架使用pytorch,数据集使用蜜蜂和蚂蚁的数据集
CAM实现代码
一、参考链接
1、类激活图的动态可视化
缺点:框架使用的keras,实现的是模型从无到有建立的动态可视化CAM,借鉴度不高
2、Pytorch可视化神经网络热力图(CAM)
缺点:实现的方式和细节与本文都不太一样,框架需要重写,需要保留最后一个feature map的梯度,借鉴度不高
3、师兄实现CAM的代码
缺点:缺点是不可能会有的,针对自己对CAM的理解,做了一些简化和优化
二、使用须知
1、框架使用pytorch
2、需要加载预训练好的模型,包含或不包含全连接层(fc)皆可,任意模型(自己搭建的或现有的)皆可,二分类任 务(多分类也可)。本文以ResNet101,蜜蜂蚂蚁数据集为例。
3、实现针对输入图片,给出其全连接层参数矩阵W指导下的激活热力图可视化。
三、代码
1、加载预训练模型
model_ft = models.resnet101(pretrained=False)
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, class_num)
model_ft.load_state_dict(torch.load('./ant_bee_model.pth'