v2版本,文中使用的参数和数值为代码中默认值并以voc数据集为例来说明的。
一.输入数据处理
jitter类似的手段:产生一个指定范围的随机数,调整输入图像作为传播使用的数据。
truth的使用上相对v1发生了变化,一张图片最大能容纳30个目标(这30个目标是预定的,可以修改),超过30个的目标舍去,每个目标以(x,y,w,h,id)为顺序存储。每张图片对应的输出outpunum为5*30 = 150个。
二.新增层的处理
route layer
copy过来,再做为输出使用,指定的层由layers参数确定,将不同大小的特征图连接到一块。其实这个操作在caffe里都不能算一层,只需要指针指向一下就可以了。这里主要说下copy的顺序,Layers参数可以有多个,即将多个层的数据拷贝过来做为输出。将每个batch中的各个层数据一次copy到output,即拷贝后的结果为:
L1 L2…Ln, L1 L2…Ln, …, L1 L2…Ln
batch1, batch2, … batchm
reorg layer
route layer之后,它是否需要存在要看上面一层特征的大小是否需要变化,在voc的例子中,由于需要将26层的26*26*512的特征图转化成13*13*2048,使用stride为2的reorg layer。
512个通道分成了4部分,分别遍历了所有数据,结合reorg_cpu的代码来看
1部分(0-127),横向从0开始取偶数位w=26个,纵向间隔stride*w*stride(4行),则通道间隔为h*stride*w*stride(从这里可以看出通道变化范围必须为原来的1/4)
2部分(128-255),横向从1开始取奇数位w=26个,之后同上(c2与上一样但offset变化为从1开始,而h2起始值没变)
3部分(256-383),横向从52开始取偶数位w=26个(h2起始位1,则out_index起始位52,之后与1部分相同)
4部分(384-511)横向从53开始取奇数位w=26个(h2起始为1,w2起始为1,则out_index起始为53,后续规律相同)
4行的1/4,恰好取完.
三.检测层的处理
v1那样使用全连接的方法,而是使用1*1的卷积生成125个通道,输出尺寸为w*h*c = 13*13*125,即将每张图片划分为13*13个网格,每个网格预测5个目标,每个目标包含三个部分,依次为:目标位置4个点、包含目标置信度1个点、目标类别置信度20个点,总共25个点。为了更加方便的以偏移取数据,使用flatten方法将最后的网络输出做转置处理,这样网络变成了125*13*13,每次取数据都可以按各个网络的5个预测目标依次处理。也可以将flatten理解成将输出的三维矩阵压扁成125*169的二维矩阵,对之后的取数据来讲,是等效的。
flatten,按顺序取数据(目标位置、置信度、坐标)为13行的每一行的列中分别取出,不符合上面的要求,转置后,变成了13*13的每个位置上取5组可能的预测信息。
logistic激活,是为了将输出压缩到0-1之间,用于后续计算误差(有无目标)。
softmax方法处理。然后就是计算回归的位置误差敏感项,根据误差求导生成。
v2版本的时候遇到的一个多gpu下训练不收敛的问题,或者出现nan,或者训练的时候收敛,但是是否有目标的置信度逐渐减小,直至为0,这样预测的目标置信度就都是0了。我是用的是tiny-yolo.cfg的配置,经过排查和各种尝试,发现刚开始训练时学习速率太大,在steps为-1,100,80000,100000的分段调整速率的划分中,使用小速率多学习一段时间,即可解决这个问题,比如改为-1,1000,80000,100000.分享出来,避免大家遇到相同的问题而纠结很久。