题记:因本人记性差,所以记录下深度学习各种方面研究进展小结以及其他方面的知识,方便以后复习,温故而知新。现在记录的只是深度学习中九牛一毛的知识点,有待后续的学习和记录。可以加群交流学习:334227548。
目录:
1. fine-tuning 改善效果的tricks
2. 特殊层介绍
3. 深度学习知识点
4. 目标检测小结
5. 学习网站和论坛以及博客
============fine-tuning 改善效果的tricks==============================
一, 数据集方面
1. Data Augmenttation:数据集扩充能提高性能,改善效果,防止过拟合,增加模型的泛化能力。
Data Augmenttation具体操作有:horizontally flipping, random cropsand color jittering...
(其中random crop和flip horizontally在caffe中通过指定参数即可,如下图:)
2. 预处理过程:包括去均值(数据集图像均值,比如可以减去ImageNet数据集的mean文件,也可以减去自己数据集的均值文件。);
Python代码参考:https://zhuanlan.zhihu.com/p/22147033
二, 网络结构上
1. 卷积层微调:有的任务,有些网络可以微调其卷积层,改善效果。
2. 修改最后一层(例如:fc8):
(1) 首先修改名字,这样预训练模型赋值的时候这里就会因为名字不匹配从而重新训练,也就达成了我们适应新任务的目的。
(2) 调整学习速率,因为最后一层是重新学习,因此需要有更快的学习速率相比较其他层,因此我们将,weight和bias的学习速率加快10倍。
3. 选取适合的优化参数:比如随机梯度下降(SGD)。
4. 添加一些特殊的层: 比如dropout(当然这个基本现在网络都有这层),防止过拟合。
5. pooling层可以通过实验测试选择上采用、下采样、均值采样等
三, 超参数的修改(Solver文件)
1. 学习率,步长,迭代次数都要适当的减少。
2. 初始学习率,经过迭代训练,当损失函数不再下降时,对学习率进行固定常数衰减(如乘以0.1(gamma)),如此反复贯穿训练始终。
3. 遗忘因子(momentum)= 0.9,这样可以让基于sgd算法的深度学习系统更加稳定,收敛更快。
4. 如果训练发散(损失函数值变得非常大,甚至出现NaN或Inf), 试着减小base_lr,然后重新训练,知道不再发散。
四,海康威视检测权威评测夺冠之道(部分tricks)
(https://zhuanlan.zhihu.com/p/22589208)
1. 训练技巧
a) 平衡采样。很多数据集存在样本不均衡的问题,有些类别特别多,有些类别特别少。训练模型时,从一个图像列表中依次读取样本训练。这样的话,小类样本参与训练的机会就比大类少。训练出来的模型会偏向于大类,即大类性能好,小类性能差。平衡采样策略就是把样本按类别分组,每个类别生成一个样本列表。训练过程中先随机选择1个或几个类别,然后从各个类别所对应的样本列表中随机选择样本。这样可以保证每个类别参与训练的机会比较均衡。在PASCAL VOC数据集上,使用平衡采样性能可以提升约0.7个点。
b) 难例挖掘(OHEM [5])。使用了难例挖掘后,收敛更快,训练更稳定。在ImageNet DET数据集上,性能可以提升1个多点。
c) 多尺度训练。使用多尺度训练的话,可以让参与训练的目标大小分布更加均衡,使模型对目标大小具有一定的鲁棒性。
2.预测技巧
预测阶段,我们用了多尺度预测,水平翻转,和检测框投票。这些策略的具体实现在很多文献中都有描述。这里我们可以分享一下多个检测结果的融合策略。当使用多尺度预测,水平翻转,还有多模型Ensemble时,对于同一张测试图像,我们会得到好几组结果。对于这些结果,最直观的融合方式就是把所有的检测框放在一起,然后用非极大值抑制(NMS)处理一下。但是我们发现另一种方式效果更好,就是把RPN和FRCN分开来做。先对RPN做多尺度、水平翻转、多模型的融合,得到一组固定的Proposal之后,再对FRCN进行多尺度、水平翻转、多模型的融合。RPN的融合用NMS更好,FRCN的融合用对Proposal的置信度和Bounding Box位置取平均值的方式更好。
LRN 把所有的变量都具有相似的方差,可以使监督学习算法快,即会增加性能。 局部响应归一化层完成一种“临近抑制”操作,对局部输入区域进行归一化。
该层需要参数有:
norm_region: 选择对相邻通道间归一化还是通道内空间区域归一化,默认为ACROSS_CHANNELS,即通道间归一化;
local_size:两种表示(1)通道间归一化时表示求和的通道数;(2)通道内归一化时表示求和区间的边长;默认值为5;
alpha:缩放因子(详细见后面),默认值为1;
beta:指数项(详细见后面), 默认值为5;
二 Slicing(http://blog.csdn.net/ws_20100/article/details/49184037)
Slice层将一个输入层根据切割指标给定的维度(现在只有num和channel)切割成多个输出层。
layer { name: "slicer_label" type: "Slice" bottom: "label" ## Example of label with a shape N x 3 x 1 x 1 top: "label1" top: "label2" top: "label3" slice_param { axis: 1 slice_point: 1 slice_point: 2 } }
三 Concat层 (和slice层正好相反)axis指定目标轴(0代表根据num,1代表根据channel。);slice_point指定选定维数的索引(索引的数量必须等于blob数量减去一)。
layer { name: "concat" bottom: "in1" bottom: "in2" top: "out" type: "Concat" concat_param { axis: 1 } }
Concat层将串连多个输入blob,成为一个单一的输出blob。
layer { name: "fc8" type: "InnerProduct" # learning rate and decay multipliers for the weights param { lr_mult: 1 decay_mult: 1 } # learning rate and decay multipliers for the biases param { lr_mult: 2 decay_mult: 0 } inner_product_param { num_output: 1000 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } bottom: "fc7" top: "fc8" }
InnerProduct层(通常也称为全连接层),将输入数据以简单的向量形式进行处理,并且输出一个简单的向量(blob的高度,宽带为1)。
输入的窗口的位置和分数,以及窗口面积交叉是多大比例进行抑制。boxes应当是N*5的矩阵,一行代表着一个窗口,包括[x,y,width,height ,score ],overlap是介于0~1的实数。输出的是局部分数最大的窗口序号序列。
程序解读:首先计算出所有窗口的面积,对所有窗口的分数进行从小到大排序取出最高分数的序号。循环计算1到次高分数窗口与最高分数窗口的交叉面积与两者间最小面积的比例,若超过overlap那么把这一窗口抑制了。交叉面积怎么计算呢?如下图对应于程序
one epoch:所有的训练样本完成一次Forword运算以及一次BP运算
batch size:一次Forword运算以及BP运算中所需要的训练样本数目,其实深度学习每一次参数的更新所需要损失函数并不是由一个{data:label}获得的,而是由一组数据加权得到的,这一组数据的数量就是[batch size]。当然batch size 越大,所需的内存就越大,要量力而行
iterations(迭代):每一次迭代都是一次权重更新,每一次权重更新需要batch size个数据进行Forward运算得到损失函数,再BP算法更新参数。
最后可以得到一个公式 one epoch = numbers of iterations = N = 训练样本的数量/batch size
===================目标检测============================================
一, 传统的目标检测方法
1. 区域选择
这一步是为了对目标的位置进行定位。由于目标可能出现在图像的任何位置,而且目标的大小、长宽比例也不确定,所以最初采用滑动窗口的策略对整幅图像进行遍历,而且需要设置不同的尺度,不同的长宽比。这种穷举的策略虽然包含了目标所有可能出现的位置,但是缺点也是显而易见的:时间复杂度太高,产生冗余窗口太多,这也严重影响后续特征提取和分类的速度和性能。(实际上由于受到时间复杂度的问题,滑动窗口的长宽比一般都是固定的设置几个,所以对于长宽比浮动较大的多类别目标检测,即便是滑动窗口遍历也不能得到很好的区域)。
2. 特征提取主要有SVM, Adaboost等。
总结:传统目标检测存在的两个主要问题:一个是基于滑动窗口的区域选择策略没有针对性,时间复杂度高,窗口冗余;二是手工设计的特征对于多样性的变化并没有很好的鲁棒性。
(1) 输入测试图像
(2) 利用selective search算法在图像中提取2000个左右的region proposal。
(3) 将每个region proposal缩放(warp)成227x227的大小并输入到CNN,将CNN的fc7层的输出作为特征。
(4) 将每个region proposal提取到的CNN特征输入到SVM进行分类。
针对上面的框架给出几点解释:
* 对每个region proposal缩放到同一尺度是因为CNN全连接层输入需要保证维度固定。
* 上图少画了一个过程——对于SVM分好类的region proposal做边框回归(bounding-box regression),边框回归是对region proposal进行纠正的线性回归算法。(步骤太复杂!)
小结:R-CNN在PASCAL VOC2007上的检测结果从DPM HSC的34.3%直接提升到了66%(mAP)。如此大的提升使我们看到了region proposal+CNN的巨大优势。
小结:使用SPP-NET相比于R-CNN可以大大加快目标检测的速度,但是依然存在着很多问题:
(1) 训练分为多个阶段,步骤繁琐: 微调网络+训练SVM+训练边框回归器
(2) SPP-NET在微调网络的时候固定了卷积层,只对全连接层进行微调,而对于一个新的任务,有必要对卷积层也进行微调。
(2) R-CNN训练过程分为了三个阶段,而Fast R-CNN直接使用softmax替代SVM分类,同时利用多任务损失函数边框回归也加入到了网络中,这样整个的训练过程是端到端的(除去region proposal提取阶段)。
(3) Fast R-CNN在网络微调的过程中,将部分卷积层也进行了微调,取得了更好的检测效果。
小结:Fast R-CNN融合了R-CNN和SPP-NET的精髓,并且引入多任务损失函数,使整个网络的训练和测试变得十分方便。在Pascal VOC2007训练集上训练,在VOC2007测试的结果为66.9%(mAP),如果使用VOC2007+2012训练集训练,在VOC2007上测试结果为70%(数据集的扩充能大幅提高目标检测性能)。使用VGG16每张图像总共需要3s左右。
缺点:region proposal的提取使用selective search,目标检测时间大多消耗在这上面(提region proposal 2~3s,而提特征分类只需0.32s),无法满足实时应用,而且并没有实现真正意义上的端到端训练测试(region proposal使用selective search先提取处来)。那么有没有可能直接使用CNN直接产生region proposal并对其分类?Faster R-CNN框架就是符合这样需要的目标检测框架。
4 Faster R-CNN(NIPS2015) : RPN +Fast R-CNN
(1)RPN的核心思想是使用卷积神经网络直接产生region proposal,使用的方法本质上就是滑动窗口。RPN的设计比较巧妙,RPN只需在最后的卷积层上滑动一遍,因为anchor机制和边框回归可以得到多尺度多长宽比的region proposal。
这样设计的好处是什么呢?虽然现在也是用的滑动窗口策略,但是:滑动窗口操作是在卷积层特征图上进行的,维度较原始图像降低了16*16倍(中间经过了4次2*2的pooling操作);多尺度采用了9种anchor,对应了三种尺度和三种长宽比,加上后边接了边框回归,所以即便是这9种anchor外的窗口也能得到一个跟目标比较接近的region proposal。
整体流程跟Fast R-CNN一样,只是region proposal现在是用RPN网络提取的(代替原来的selective search)。同时作者为了让RPN的网络和Fast R-CNN网络实现卷积层的权值共享,训练RPN和Fast R-CNN的时候用了4阶段的训练方法:
(1) 使用在ImageNet上预训练的模型初始化网络参数,微调RPN网络;
(2) 使用(1)中RPN网络提取region proposal训练Fast R-CNN网络;
(3) 使用(2)的Fast R-CNN网络重新初始化RPN, 固定卷积层进行微调;
(4) 固定(2)中Fast R-CNN的卷积层,使用(3)中RPN提取的region proposal微调网络。
权值共享后的RPN和Fast R-CNN用于目标检测精度会提高一些。
使用训练好的RPN网络,给定测试图像,可以直接得到边缘回归后的region proposal,根据region proposal的类别得分对RPN网络进行排序,并选取前300个窗口(可以自己选择数量)作为Fast R-CNN的输入进行目标检测,使用VOC07+12训练集训练,VOC2007测试集测试mAP达到73.2%(selective search + Fast R-CNN是70%), 目标检测的速度可以达到每秒5帧(selective search+Fast R-CNN是2~3s一张)。
需要注意的是,最新的版本已经将RPN网络和Fast R-CNN网络结合到了一起——将RPN获取到的proposal直接连到ROI pooling层,这才是一个真正意义上的使用一个CNN网络实现端到端目标检测的框架。
小结:Faster R-CNN将一直以来分离的region proposal和CNN分类融合到了一起,使用端到端的网络进行目标检测,无论在速度上还是精度上都得到了不错的提高。然而Faster R-CNN还是达不到实时的目标检测,预先获取region proposal,然后在对每个proposal分类计算量还是比较大。比较幸运的是YOLO这类目标检测方法的出现让实时性也变的成为可能。
总的来说,从R-CNN, SPP-NET, Fast R-CNN, Faster R-CNN一路走来,基于深度学习目标检测的流程变得越来越精简,精度越来越高,速度也越来越快。可以说基于region proposal的R-CNN系列目标检测方法是当前目标最主要的一个分支。
5 R-FCN (2016)
还没开始写。。。
Faster R-CNN的方法目前是主流的目标检测方法,但是速度上并不能满足实时的要求。YOLO一类的方法慢慢显现出其重要性,这类方法使用了回归的思想,既给定输入图像,直接在图像的多个位置上回归出这个位置的目标边框以及目标类别。
1)YOLO (CVPR2016, oral)
(You Only Look Once: Unified, Real-Time Object Detection)
(1) 给个一个输入图像,首先将图像划分成7*7的网格
(2) 对于每个网格,我们都预测2个边框(包括每个边框是目标的置信度以及每个边框区域在多个类别上的概率)
(3) 根据上一步可以预测出7*7*2个目标窗口,然后根据阈值去除可能性比较低的目标窗口,最后NMS去除冗余窗口即可。
可以看到整个过程非常简单,不需要中间的region proposal在找目标,直接回归便完成了位置和类别的判定。
那么如何才能做到直接在不同位置的网格上回归出目标的位置和类别信息呢?上面是YOLO的网络结构图,前边的网络结构跟GoogLeNet的模型比较类似,主要的是最后两层的结构,卷积层之后接了一个4096维的全连接层,然后后边又全连接到一个7*7*30维的张量上。实际上这7*7就是划分的网格数,现在要在每个网格上预测目标两个可能的位置以及这个位置的目标置信度和类别,也就是每个网格预测两个目标,每个目标的信息有4维坐标信息(中心点坐标+长宽),1个是目标的置信度,还有类别数20(VOC上20个类别),总共就是(4+1)*2+20 = 30维的向量。这样可以利用前边4096维的全图特征直接在每个网格上回归出目标检测需要的信息(边框信息加类别)。
小结:YOLO将目标检测任务转换成一个回归问题,大大加快了检测的速度,使得YOLO可以每秒处理45张图像。而且由于每个网络预测目标窗口时使用的是全图信息,使得false positive比例大幅降低(充分的上下文信息)。但是YOLO也存在问题:没有了region proposal机制,只使用7*7的网格回归会使得目标不能非常精准的定位,这也导致了YOLO的检测精度并不是很高。
2)SSD(SSD: Single Shot MultiBox Detector)
上面分析了YOLO存在的问题,使用整图特征在7*7的粗糙网格内回归对目标的定位并不是很精准。那是不是可以结合region proposal的思想实现精准一些的定位?SSD结合YOLO的回归思想以及Faster R-CNN的anchor机制做到了这点。
不同于Faster R-CNN,这个anchor是在多个feature map上,这样可以利用多层的特征并且自然的达到多尺度(不同层的feature map 3*3滑窗感受野不同)。
小结:SSD结合了YOLO中的回归思想和Faster R-CNN中的anchor机制,使用全图各个位置的多尺度区域特征进行回归,既保持了YOLO速度快的特性,也保证了窗口预测的跟Faster R-CNN一样比较精准。SSD在VOC2007上mAP可以达到72.1%,速度在GPU上达到58帧每秒。
总结:YOLO的提出给目标检测一个新的思路,SSD的性能则让我们看到了目标检测在实际应用中真正的可能性。
四. 提高目标检测方法R-CNN系列目标检测框架和YOLO目标检测框架给了我们进行目标检测的两个基本框架。除此之外,研究人员基于这些框架从其他方面入手提出了一系列提高目标检测性能的方法。
(1) 难分样本挖掘(hard negative mining)
R-CNN在训练SVM分类器时使用了难分样本挖掘的思想,但Fast R-CNN和Faster R-CNN由于使用端到端的训练策略并没有使用难分样本挖掘(只是设置了正负样本的比例并随机抽取)。CVPR2016的Training Region-based Object Detectors with Online Hard Example Mining(oral)将难分样本挖掘(hard example mining)机制嵌入到SGD算法中,使得Fast R-CNN在训练的过程中根据region proposal的损失自动选取合适的region proposal作为正负例训练。实验结果表明使用OHEM(Online Hard Example Mining)机制可以使得Fast R-CNN算法在VOC2007和VOC2012上mAP提高 4%左右。
(2) 多层特征融合
Fast R-CNN和Faster R-CNN都是利用了最后卷积层的特征进行目标检测,而由于高层的卷积层特征已经损失了很多细节信息(pooling操作),所以在定位时不是很精准。HyperNet等一些方法则利用了CNN的多层特征融合进行目标检测,这不仅利用了高层特征的语义信息,还考虑了低层特征的细节纹理信息,使得目标检测定位更精准。
(3) 使用上下文信息
在提取region proposal特征进行目标检测时,结合region proposal上下文信息,检测效果往往会更好一些。(Object detection via a multi-region & semantic segmentation-aware CNN model以及Inside-Outside Net等论文中都使用了上下文信息)