1. 写在前面
DFL最早在论文Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection中被提及,在YOLOv8中就已经在使用。
DFL的作者认为,在很多时候,检测目标的边界并不是一个确切的值,而是一个分布。
2. DFL
DFL,全程Distribution Focal Loss,很多同学一听到Focal Loss就立马想到分类,这没错,但DFL却是用在边框回归中。
在大部分时候,我们理所当然的认为边框(L、T、R、B)是一个确切的值,从分布的角度来说,就是一个Dirac delta分布,即一个脉冲,有如下的表示。
当我们给定标签的范围时,如,由上式可以继续推导出一个复原积分公式。
OK,到这一步还是连续的,接下来我们来推出一个离散化的公式。
但是,在很多场景下,边缘本身并不是绝对的一个值,而更倾向于是一个分布,我们可以将这个广义的分布看作是P(y)。可用如下表示。
为了复原估计值,我们可以做如下表示。
其中是预测的边框取值。
怎么理解这里呢?具体这个怎么反应box框的长宽呢?
我们假设box的左边框距离中心距离5.6,我们使用一个长度为16的向量表达这个距离,只需要满
特殊情况下,5.6取值在5和6之间,就是使得
P(5) + P(6) = 1,
P(5)*5 + P(6)*6 = 5.6
接下来我们定义DFL如下。
3. 代码阅读
在YOLOv9中,在计算预测box的Loss时,使用到了如上述定义的DFL Loss。
BboxLoss中的_df_loss
如下代码所示,
def _df_loss(self, pred_dist, target):
target_left = target.to(torch.long)
target_right = target_left + 1
weight_left = target_right.to(torch.float) - target
weight_right = 1 - weight_left
loss_left = F.cross_entropy(pred_dist.view(-1, self.reg_max + 1), target_left.view(-1), reduction="none").view(target_left.shape) * weight_left
loss_right = F.cross_entropy(pred_dist.view(-1, self.reg_max + 1), target_right.view(-1), reduction="none").view(target_left.shape) * weight_right
return (loss_left + loss_right).mean(-1, keepdim=True)
上述代码中,我们将时间要估计的y限制在target_left和target_right之间,
使用PyTorch的cross_entropy。