从零搭建自己的目标检测网络教程(四)损失函数

这篇文章的重点是解释为什么YOLO的损失函数中的置信度损失要设计成iou的形式而不是简单的0和1,而且既然是IOU那为什么不是最好用的ciou而就是最简单的iou?

置信度损失

只输出一个网格的时候损失函数很简单,一个置信度损失一个定位损失就够了,当输出多个网格的时候情况变的复杂起来。我自己在设计损失函数的时候最自然的想法就是,真实框的中心坐标落在哪个网格内,这个网格的置信度期望就是1,剩余的网格期望就是0,且只计算这个网格的定位损失。简单这样训练的结果是,因为正负样本极不匹配,网络倾向于判断目标不存在,但一旦判断存在就是接近1的置信度。
当我正准备对交叉熵损失加权或者使用focal loss的时候,又发现一个问题,就是如果目标覆盖了多个网格的话,尤其是中心坐标恰好出现在2个网格的边界线上,这样就会出现目标稍微移动一下期望就直接从0变为1的情况,这很不合理。此时iou就巧妙地解决了使期望能从0逐渐过渡到1的问题。
所以使用iou而不是ciou的原因就是,iou的作用并不是边界框回归,而只是起一个过渡的作用而已,这里使用ciou效果可能会更好,但在定位损失里ciou只需要算一次,而在置信度损失里,输出多少个网格iou需要计算多少次,显然计算量会很大。

定位损失

定位损失除了计算ciou比较复杂以外其它的都比较简单,只需要找到中心点落在哪个网格就可以了。关于ciou请参考其他资料,本文不详述。当使用多个特征层和多个先验框的时候,基本原理还是找到最合适的那个网格。比如多个特征层+1个先验框,哪个特征层的先验框的面积(或边长)与真实框最接近就选哪个特征层。

下标索引

如果是自己从零开始写损失函数的话,下标索引绝对是最令人头大的一个地方,没什么技术含量,计算却特别复杂,稍不留神还容易出错。如果不考虑效率,for循环就是最舒服的,但要使用向量运算,下标索引就是绕不过去的坎。

data_conf = data[..., 4].flatten()
data_box = data[..., :4].reshape(-1, 4)
img_height, img_width = data.shape[1], data.shape[2]
label_box = label.repeat(img_height*img_width, 1, 1).permute(1, 0, 2).reshape(-1, 4)
iou = box_iou(data_box, label_box)

这段代码出自置信度损失函数中,作用是计算真实框与每个网格的预测框的iou。由于真实框只有一个,而预测框有img_height*img_width个,所以要使用repeat方法。直接拿实际数据举例(输出特征图尺寸以15x20为例,批数量以32为例)。

变量shape
dataNx15x20x5
data_conf300N
data_box300Nx4
labelNx4
label.repeat(300,1,1)①300xNx4
label.repeat(300,1,1).permute(1, 0, 2)②Nx300x4
label_box300Nx4

这里有个大坑要注意,①和②的区别在哪?反正reshape之后都是300Nx4,那为什么要permute?因为两者的数据不对应。
设一个batch中的第3个label为(313,180,178,272),在15x20特征图中对应5x9,取data中data[3,5,9,:],data_box中对应1009,也就是说

data[3,5,9,:4]=data_box[1009,:]

计算方法是

3x15x20+5x20+9=1009

那么label_box[1009,:]对应label中的多少呢?如果不加permute,那么

label_box[3,:]=label_box[32+3,:]=label_box[64+3,:]=…

1009=32x31+17
label_box[1009,:]=label_box[17,:]=label[17,:]

加了permute就是

label_box[0,:]=label_box[1,:]=label_box[2,:]=…

1009=300x3+109
label_box[1009,:]=label_box[900,:]=label_box[1199,:]=label[3,:]

这一段虽说就是简单的加减乘除,但一不小心就会出错。

从零搭建自己的目标检测网络教程(零)前言

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值