主干网络加入Fcous结构,将图片宽高信息缩小,减小参数量,提升网络计算速度
Fcous结构:将输入的图片先经过Fcos结构对图片进行每隔一个像素取出一个值,得到四个特征层,然后再进行concat。从而图片宽高的信息缩小,通道数增加。在原始信息丢失较少的情况下,减小了参数量(由于fcous替代了两层卷积与一层bottleneck)
图 1 Fcous示意
silu函数相比于rule非线性能力更强,解决了rule当有负数输入输出为0,发生梯度弥散的缺点。同时继承了relu收敛更快的优点。
silu函数=x*sigmoid(x),是relu与sigmoid的结合。可以看做是一个平滑的Relu,对比来看,silu解决了relu具有负数输入输出为0的缺点,不会发生梯度弥散的问题。
(上层神经元通过加权求和,得到输出值,然后被作用一个激活函数,得到下一层的输入值。引入激活函数的目的是为了增加神经网络的非线性拟合能力。)
(被fcous处理后的feature map会被用silu激活函数的,残差卷积层进行卷积,卷积后进入
CSPLayer。)
图 2 silu激活函数
CSPLayer:内部的主要特征提取利用残差结构,但csplayer将feature map分为两部分,一部分进入残差块,与瓶颈结构,特征提取,另一部分与特征提取后的feature map进行concat操作从而进行信息融合。(需要注意从代码上,part1与part2是一样的输入)
图 3 CSPLayer结构与源码
这里的SPPneck主要通过不同大小的池化核,对图像进行池化,增大网络感受野,提取更多的特征。
图 4 空间金字塔池化公式
图 5 SPPneck(空间金字塔池化)
总而言之,主干网络卷积层的主要作用是特征提取与特征融合,相比于之前的YOLO版本,更换激活函数带来了一些非线性能力的提升。在主干网络中加入SPPneck增大了网络感受野。
在特征利用部分,YoloX提取多特征层进行目标检测,一共提取三个特征层。
三个特征层位于主干部分CSPdarknet的不同位置,分别位于中间层,中下层,底层,当输入为(640,640,3)的时候,三个特征层的shape分别为feat1=(80,80,256)、feat2=(40,40,512)、feat3=(20,20,1024)。
第一条的路径:主干卷积(20,20,1024)特征图上采样,与主干卷积(40,40,512)特征图进行concat和卷积下采样,融合信息与进一步特征提取得到merge_01。
第二条路径:merge_01通过1x1卷积降通道上采样与主干(80,80,256)concat和卷积下采样得到(80,80,256)大小的merge_02输出到YOLOHead_01(个人理解该层的特征偏向(80,80)的特征图)
第三条路径:merge02下采样与merge01进行concat与卷积下采样操作得到(40,40,512)的(40,40,512)大小的merge_03输出到YOLOHead_02(个人理解该层的特征偏向(40,40)的特征图)
第四条路径:merge_03下采样与主干卷积到(20,20,1024)的特征图进行concat与卷积下采样操作,得到(20,20,1024)的merge_04输出到YOLOHead_03(个人理解该层的特征偏向(20,20)的特征图)
总结:FPN层对3个维度的特征图进行了融合,但是每个输出都有一定的侧重,为了对不同尺度的目标有更好的检测效果。
YOLOV3中最后的回归框与置信度在1*1的卷积中一起实现,而在YOLOX通过解耦头,分别将置信度与回归框分别实现,在预测时合为一体。
将三个预测结果进行堆叠,每个特征层获得的结果为:
Out(h,w,4+1+num_classses)前四个参数用于判断每一个特征点的回归参数,回归参数调整后可以获得预测框;第五个参数用于判断每一个特征点是否包含物体;最后num_classes个参数用于判断每一个特征点所包含的物体种类。
将检测头解耦相对于YOLOV3检测头直接融合out输出而言,无疑会增加运算的复杂度,但是作者最终使用 1个1x1 的卷积先进行降维,并在分类和回归分支里各使用了 2个3x3 卷积,最终调整到仅仅增加一点点参数。解耦操作从逻辑上,对一个任务的精度而言有着绝对优势,缺点是在于增加运算的复杂程度。如何平衡性能与速度则是解耦方法是否优秀的关键。
解码目标:由yolox中的decoupled_head输出后concat的形状为((numcls+5)*8400)的网格点图。
经过concat与维度转换的网格点,每一行都是代表着一个预测框信息的(numcls、中心点与宽高、判断该预测点是否有物体的obj)的anchorpoint
解码主要解码中心点坐标,以及宽高(x,y,h,w)。
解码中心点坐标是通过torch.meshgrid生成网格数据为网格点的行列索引,将中心点的偏移量x,y加上索引号再乘上缩放倍数。即可解码还原到原图。具体操作为:outputs[..., :2] = (outputs[..., :2] + grids) * strides
解码宽高w,h则是通过output输出宽高部分直接乘以步长再求对数获得。具体操作为:
outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides
SimOTA主要的作用是为每个正样本(网络输出预测框)分配一个GT框,让正样本去拟合该GT框。从而替代之前的anchor方案去拟合anchor,从而实现anchor free
1.Reg部分,利用真实框和预测框计算IOU损失,作为Reg部分的Loss组成。
2.Obj部分,所有真实框对应的特征点都是正样本,剩余的特征点均为负样本,根据正负样本和特征点的是否包含物体的预测结果计算交叉熵损失,作为Obj部分的Loss组成。
3.Cls部分,计算交叉熵损失,作为Cls部分的Loss组成。
4.损失公式如下:
其中Lcls代表分类损失;
Lreg代表定位损失;
Lobj代表obj损失;
λ代表定位损失的平衡系数源码中设置是5.0;
Npos代表被分为正样的Anchor Point数;
感谢对本文有所帮助的人们!!
睿智的目标检测53——Pytorch搭建YoloX目标检测平台_Bubbliiiing的博客-CSDN博客
YOLOX之函数dynamic_k_matching解析 - 知乎 dynamic_k_match源码解析
yolox Head-Decoupled head源码解读_Mr.Q的博客-CSDN博客_yolox的head部分 yolo_head.py源码解析