最近做Semantic Part的检测,阅读文章时发现很多方法都是基于一种"attention"的热力图来产生的,有一种产生热力图的方法,叫做Class Activation Map,这种方法是16年提出,可以在某种程度上分析神经网络训练出的结果的,生成的结果大概长这样:
论文地址
Codes
简单介绍算法的基本原理
图源自论文看图说话:前面Conv层是VGG16,GoogleNet等提特征的层,作者提出的是GAP层和后面W1到Wn这个进行分类的全连接层,这个层是用线性支持向量机训练出来的,我们把它叫做W_LR。
这个GAP层全程为Global Average Pooling,全局平均池化,即将每个channel取平均聚成一个点。
算法的输出有两个部分
- 输入图片的类别
- 与类别相关的热力图(行2)
输出类别很容易理解了,与其他分类网络没什么区别。重点是这个热力图,获得方法也很容易理解,即跳过GAP层,直接以输出类别的W_LR为权重,对特征层进行加权得到最后的热力图。
举个例子,假设
前面提取特征的结果为
,即尺度为
,C个Channel。
GAP层同样有C个Channel,但尺度只有
,即
,即全局平均池化了。
W_LR参数的尺寸为
,N为需要类别的数量,ImageNet中为1000。经过W_LR后,我们得到了N个类别的得分,经过一个Softmax就能得到最后的类别输出了。
然后生成热力图:假设预测出的类别为n,那么跳过GAP层,直接将特征结果,
这个层以W_LR(: ; n)为权重(尺度为
)叠加起来,就得到了最后的结果。
代码复现
代码复现需要caffe+matlab环境
作者给出的代码中有与训练好的一些数据,这些数据包含了ImageNet中1000个种类全连接层分类参数,还有VGG等网络的预训练参数,因此如果只是看一下效果是不需要做任何训练的。这些参数分别在:
- model文件夹中是网络模型和相应的参数,有些参数需要在readme给出的网址中下载
- W_LR的参数在data_net中
看代码:
首先是加载网络
net_weights = ['models/vgg16CAM_train_iter_90000.caffemodel'];
net_model = ['models/deploy_vgg16CAM.prototxt'];
net = caffe.Net(net_model, net_weights, 'test');
weights_LR = net.params('CAM_fc',1).get_data();
然后得到分类的分数
scores = net.forward({prepare_image(cur_img)});% extract conv features online
activation_lastconv = net.blobs('CAM_conv').get_data();
然后生成heatmap图
[curCAMmapAll] = returnCAMmap(activation_lastconv, weights_LR(:,IDX_category(909)));
生成出来是这个样子
客机的Heatmap关于W_LR是怎么训练出来的
如果要用自己的数据,自己的类别,当时是需要学会怎么训这个W_LR的,我认为实际上生成的这个热力图效果怎么样,能不能供后面算法的使用,最重要的一点就是W_LR的质量。另一方面,这样加权的终极道理是什么,也是我现在还没有想清楚的。
作者在论文中给出了一个reference,指向一个叫做LIBLINEAR的开源库,现在还在学习这个库,有空有心得的话再写一篇BLOG吧。
欢迎程序员同行参观我的BLOG