yolov2 损失函数_【AlexeyAB DarkNet框架解析】八,YOLOV2损失函数代码详解

想再说一下,这个系列的代码注释我放到https://github.com/GiantPandaCV/darknet 这里了,有需要的可以点star或者fork哦,还在持续更新中。

前言

昨天结合代码详细解析了YOLOV1的损失函数,今天AlexeyAB版DarkNet的YOLOV2损失函数代码解析也来了。之前我详细分析过YOLOv2的损失函数

YOLOV2损失函数

为了方便你理解,还是把YOLOV2损失函数叙述一下。

YOLOV2对每个预测box的[x,y],confidence进行逻辑回归,类别进行softmax回归;

在Darknet中,损失函数可以用下图来进行表示:

可以看到这个损失函数是相当复杂的,损失函数的定义在Darknet/src/region_layer.c中。对于上面这一堆公式,我们先简单看一下,然后我们在源码中去找到对应部分。这里的

equation?tex=W

equation?tex=H代表的是特征图的高宽,都为

equation?tex=13,而A指的是Anchor个数,YOLOv2中是5,各个

equation?tex=%5Clambda值是各个loss部分的权重系数。我们将损失函数分成3大部分来解释:第一部分:

第一项需要好好解释一下,这个loss是计算background的置信度误差,这也是YOLO系列算法的特色,但是用哪些预测框来预测背景呢?这里需要计算各个预测框和所有的ground truth之间的IOU值,并且取最大值记作MaxIOU,如果该值小于一定的阈值,YOLOv2论文取了0.6,那么这个预测框就标记为background,需要计算

equation?tex=%5Clambda_%7Bnoobj%7D这么多倍的损失函数。为什么这个公式可以这样表达呢?因为我们有物体的话,那么

equation?tex=%5Clambda_%7Bnoobj%7D%3D0,如果没有物体

equation?tex=%5Clambda_%7Bnoobj%7D%3D1,我们把这个值带入到下面的公式就可以推出第一项啦!

第二部分:

这一部分是计算Anchor boxes和预测框的坐标误差,但是只在前12800个iter计算,这一项应该是促进网络学习到Anchor的形状。第三部分:

这一部分计算的是和ground truth匹配的预测框各部分的损失总和,包括坐标损失,置信度损失以及分类损失。 3.1 坐标损失 这里的匹配原则是指对于某个特定的ground truth,首先要计算其中心点落在哪个cell上,然后计算这个cell的5个先验框和grond truth的IOU值,计算IOU值的时候不考虑坐标只考虑形状,所以先将Anchor boxes和ground truth的中心都偏移到同一位置,然后计算出对应的IOU值,IOU值最大的先验框和ground truth匹配,对应的预测框用来预测这个ground truth。 3.2 置信度损失 在计算obj置信度时, 增加了一项

equation?tex=%5Clambda_%7Bobj%7D权重系数,也被称为rescore参数,当其为1时,损失是预测框和ground truth的真实IOU值(darknet中采用了这种实现方式)。而对于没有和ground truth匹配的先验框,除去那些Max_IOU低于阈值的,其它就全部忽略。YOLOv2和SSD与RPN网络的处理方式有很大不同,因为它们可以将一个ground truth分配给多个先验框。 3.3 分类损失 这个和YOLOv1一致,没什么好说的了。

在计算boxes的

equation?tex=w

equation?tex=h误差时,YOLOv1中采用的是平方根以降低boxes的大小对误差的影响,而YOLOv2是直接计算,但是根据ground truth的大小对权重系数进行修正:l.coord_scale * (2 - truth.w*truth.h)(这里

equation?tex=w

equation?tex=h都归一化到(0,1)),这样对于尺度较小的

equation?tex=boxes其权重系数会更大一些,可以放大误差,起到和YOLOv1计算平方根相似的效果。

代码详解

#define DOABS 1

// 构建YOLOv2 region_layer层

// batch 一个batch中包含的图片数

// w 输入特征图的宽度

// h 输入特征图的高度

// n 一个cell预测多少个bbox

// classes 网络需要识别的物体类别数

// coord 一个bbox包含的[x,y,w,h]

region_layer make_region_layer(int batch, int w, int h, int n, int classes, int coords, int max_boxes)

{

region_layer l = { (LAYER_TYPE)0 };

l.type = REGION; //层类别

// 这些变量都可以参考darknet.h中的注释

l.n = n; //一个cell中预测多少个box

l.batch = batch; //一个batch中包含的图片数

l.h = h; //输入图片的宽度

l.w = w; //输入图片的宽度

l.classes = classes; //网络需要识别的物体类数

l.coords = coords; //定位一个物体所需的参数个数(一般值为4,包括矩形中心点坐标x,y以及长宽w,h)

l.cost = (float*)xcalloc(1, sizeof(float)); //目标函数值,为单精度浮点型指针

l.biases = (float*)xcalloc(n * 2, sizeof(float));

l.bias_updates = (float*)xcalloc(n * 2, sizeof(float));

l.outputs = h*w*n*(classes + coords + 1); //一张训练图片经过region_layer层后得到的输出元素个数(等于网格数*每个网格预测的矩形框数*每个矩形框的参数个数)

l.inputs = l.outputs; //一张训练图片输入到reigon_layer层的元素个数(注意是一张图片,对于region_layer,输入和输出的元素个数相等)

//每张图片含有的真实矩形框参数的个数(max_boxes表示一张图片中最多有max_boxes个ground truth矩形框,每个真实矩形框有

//5个参数,包括x,y,w,h四个定位参数,以及物体类别),注意max_boxes是darknet程序内写死的,实际上每张图片可能

//并没有max_boxes个真实矩形框,也能没有这么多参数,但为了保持一致性,还是会留着这么大的存储空间,只是其中的

//值为空而已.

l.max_boxes = max_boxes;

// GT: max_boxes*(4+1) 存储max_boxes个bbox的信息,这里是假设图片中GT bbox的数量是

//小于max_boxes的,这里是写死的;此处与yolov1是不同的

l.truths = max_boxes*(5);

// region层误差项(包含整个batch的)

l.delta = (float*)xcalloc(batch * l.outputs, sizeof(float));

// region层所有输出(包含整个batch的)

//region_layer的输出维度是l.out_w*l.out_h,等于输出的维度,输出的通道数为l.out_c,也即是输入的通道数,具体为:n*(classes+coords+1)

//YOLO检测模型将图片分成S*S个网格,每个网格又预测B个矩形框,最后一层输出的就是这些网格中包含的所有矩形框的信息

l.output = (float*)xcalloc(batch * l.outputs, size

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值