Focal-EIOU Loss:用于精确边界框回归的高效IOU损失
作者:互联网
损失函数之Focal-EIoU Loss:
-
本文是复现的是CVPR2020的一篇关于边界框损失函数文章:Focal and Efficient IOU Loss for Accurate Bounding Box Regression。
-
在Focal-EIoU Loss这篇论文中,作者提出CIoU中的相对比例存在若干问题,因此提出了更为直接的使用边长作为惩罚项。
-
此外为了解决低质量样本造成的损失值剧烈震荡的问题,这篇论文设计了一个用于回归的Focal Loss。最后将这两个损失结合,构成了文章题目中的Focal-EIoU Loss。
前言
-
总所周知,目标检测通过Bounding box回归来预测来定位图像中的目标,早期的目标检测工作使用IoU作为定位损失。然而,当预测框与Ground truth不重叠时,IoU损失会出现梯度消失问题,导致收敛速度减慢,导致检测器不准确。这激发了几种改进的基于IoU的损失设计,包括GIoU、DIoU、CIoU。GIoU在IoU损失中引入惩罚项以缓解梯度消失问题,而DIoU和CIoU在惩罚项中考虑了预测框与Ground truth 之间的中心点距离和宽高比。
-
在本文中,作者提出大多数先前的边界框损失函数都有两个主要缺点:
-
1.基于ln-norm和基于IOU的损失函数都无法有效地描述BBR的目标,从而导致收敛缓慢且回归结果不准确。
-
2.大多数损失函数都忽略了边界框中的不平衡问题,即与目标框重叠较少的大量锚框对边界框的优化起了最大作用。
-
提出了一种有效的Efficient Intersection over Union (EIOU)损失,它明确地测量了边界框中三个几何因素的差异,即重叠面积,中心点和边长。
- 之后又分析了Effective Example Mining (EEM) 问题,并提出Focal loss的回归版本,以使回归过程专注于高质量锚框。最后,将以上两个部分结合起来得到一个新的损失函数,即Focal-EIOU损失。
- 经验表明,在多个目标检测数据集和模型上,Focal-EIoU损失优于现有的基于IoU的损失,并为小数据集和噪声Box提供更强的鲁棒性。
EIoU Loss及Focal-EIoU Loss表达式
-
大家可以看到Focal-EIoU Loss其实非常简单,在IOU及惩罚项表达式中加入了边长损失Lasp。可以看出EIoU是直接将边长作为惩罚项的,这样也能一定程度上解决我们在DIoU一文中分析的DIoU Loss可能的边长被错误放大的问题。
-
通过整合EIoU Loss和FocalL1 loss,最终得到了最终的Focal-EIoU loss,其中 γ是一个用于控制曲线弧度的超参。
Focal-EIoU Loss代码
- 原文中作者做了大量的实验来证明Focal-EIOU Loss的有效性,在训练中取得了比较好的效果,实现的话是通过修改iou_loss.py在ppdet/modeling/losses/iou_loss.py这个位置的损失函数,通过修改iou_loss.py一行代码即可开始训练,代码如下:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import paddle
from ppdet.core.workspace import register, serializable
from ..bbox_utils import bbox_iou
__all__ = ['IouLoss', 'GIoULoss', 'EIouLoss']
@register
@serializable
class Focal_EIoU_Loss(GIoULoss):
"""
Distance-IoU Loss, see https://arxiv.org/abs/1911.08287
Args:
loss_weight (float): giou loss weight, default as 1
eps (float): epsilon to avoid divide by zero, default as 1e-10
use_complete_iou_loss (bool): whether to use complete iou loss
"""
def __init__(self, loss_weight=1., eps=1e-10, use_complete_iou_loss=True):
super(DIouLoss, self).__init__(loss_weight=loss_weight, eps=eps)
self.use_complete_iou_loss = use_complete_iou_loss
def __call__(self, pbox, gbox, iou_weight=1.):
x1, y1, x2, y2 = paddle.split(pbox, num_or_sections=4, axis=-1)
x1g, y1g, x2g, y2g = paddle.split(gbox, num_or_sections=4, axis=-1)
cx = (x1 + x2) / 2
cy = (y1 + y2) / 2
w = x2 - x1
h = y2 - y1
cxg = (x1g + x2g) / 2
cyg = (y1g + y2g) / 2
wg = x2g - x1g
hg = y2g - y1g
x2 = paddle.maximum(x1, x2)
y2 = paddle.maximum(y1, y2)
# A and B
xkis1 = paddle.maximum(x1, x1g)
ykis1 = paddle.maximum(y1, y1g)
xkis2 = paddle.minimum(x2, x2g)
ykis2 = paddle.minimum(y2, y2g)
# A or B
xc1 = paddle.minimum(x1, x1g)
yc1 = paddle.minimum(y1, y1g)
xc2 = paddle.maximum(x2, x2g)
yc2 = paddle.maximum(y2, y2g)
intsctk = (xkis2 - xkis1) * (ykis2 - ykis1)
intsctk = intsctk * paddle.greater_than(
xkis2, xkis1) * paddle.greater_than(ykis2, ykis1)
unionk = (x2 - x1) * (y2 - y1) + (x2g - x1g) * (y2g - y1g
) - intsctk + self.eps
iouk = intsctk / unionk
# DIOU term
dist_intersection = (cx - cxg) * (cx - cxg) + (cy - cyg) * (cy - cyg)
dist_union = (xc2 - xc1) * (xc2 - xc1) + (yc2 - yc1) * (yc2 - yc1)
diou_term = (dist_intersection + self.eps) / (dist_union + self.eps)
# EIOU term
c2_w = (xc2 - xc1) * (xc2 - xc1) + self.eps
c2_h = (yc2 - yc1) * (yc2 - yc1) + self.eps
rho2_w = (w - wg) * (w - wg)
rho2_h = (h - hg) * (h - hg)
eiou_term = (rho2_w / c2_w) + (rho2_h / c2_h)
#Focal-EIOU
eiou = paddle.mean((1 - iouk + diou_term + eiou_term) * iou_weight)
focal_eiou = iouk**0.5 * eiou
return focal_eiou * self.loss_weight
对 Focal-EIoU Loss性能进行验证
- (1)git PaddleDetection目标检测套件
!git clone https://github.com/PaddlePaddle/PaddleDetection.git
- (2)配置环境目录
%cd PaddleDetection/
- (3)安装依赖
!pip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
!pip install paddleslim==2.2.1
-
(4)本次实验使用了PaddleDetection套件提供的交通路标数据集,所使用的模型是PP-PicoDet模型中的picodet_s_320_coco进行实现,学习率均设置为0.01,优化器为Momentum,L2正则项为0.00004,加载与预训练参数,对比了GIOU、Focal-EIoU_Loss
-
(5)数据集可以按照以下进行配置:
-
(6)默认版本为GIOU,训练完成后分别修改configs/picodet/base/picodet_esnet.yml中loss_bbox的name为Focal_EIoU_Loss,以及按照上述修改iou_loss.py,完成对比训练。
loss_bbox: name: Focal_EIoU_Loss loss_weight: 2.0
!python tools/train.py -c configs/picodet/picodet_s_320_voc.yml --eval --use_vdl=True --vdl_log_dir='./output_vdl'
GIOU、Focal-EIOU训练mAP可视化
- 绿色曲线为GIOU
- 蓝色曲线为Focal-EIOU
GIOU、Focal-EIOU可视化细节
总结
实验结果表明:
-
引入的边长损失以及Focal L1损失函数的设计增加了IoU目标的损失和梯度,进而提高了bbox回归精度。
-
Focal L1损失函数它根据猜想的损失函数梯度所具有的属性,设计了损失函数的梯度,再反向积分得到这个损失函数起到了很好的效果。
-
但是实验表明Focal_EIOU并不存在某个损失函数在所有数据集上碾压其它损失函数,还要依赖于数据集的分布,锚点框的设计,检测算法的设计等等诸多因素,在特定的任务下需要多做尝试才能知道选择哪个边界框损失函数。
请点击此处查看本环境基本用法.
Please click here for more detailed instructions.
标签:Loss,EIoU,EIOU,loss,IOU,paddle,损失,Focal 来源: https://blog.csdn.net/m0_63642362/article/details/122491856