Generalized Focal Loss(GFLv1)论文理解与代码分析

GFLv1是较早提出在训练和推理过程中,质量评估和分类不一致问题的论文。质量与分类往往被独立训练,(yolo输出中,有独立的一个维度用于目标的置信度评估,在训练时与分类解耦;fcos,atss则利用centerness作为质量评估,同样也与分类解耦),但在test过程中却被相乘联合使用。监督只分配给正样本,但有时候负样本可能会提供更高质量的监督,必然会存在一部分分数较低的“负样本”的质量预测是没有在训练过程中有监督信号的,有就是说对于大量可能的负样本,他们的质量预测是一个未定义行为。可能出现的情况就是:一个分类score相对低的真正的负样本,由于预测了一个不可信的极高的质量score,而导致它可能排到一个真正的正样本(分类score不够高且质量score相对低)的前面。

Questions:

总结来说,GFLv1提出两个问题:
1.在训练和推理的过程中,质量评估和分类的方法不一致;
2.在复杂的场景中,回归的表示不够灵活,用狄拉克函数(类似于脉冲函数)来进行定位是不准确的;

Methods:

1.localization quality representation
在这里插入图片描述为了解决上面两个问题,GFLv1提出定位质量估计,论文将其直接与分类分数进行合并,保留类别向量,每个类别的分数的含义变为与GT的IoU。另外,使用这种方式能够同时对正负样本进行训练,不会再有训练和测试的差异。

2.general distribution
在这里插入图片描述

对于预测框的表示方法,使用general的分布进行建模,不再强加任何的约束,不仅能够获得可靠和准确的预测结果,还能感知其潜在的真实分布情况。如上图所示,对于存在歧义或不确定的边界,其分布会表现为较平滑的曲线,否则,其分布会表示为尖锐的曲线。

实际上,使用上述提到的两种策略会面临优化的问题。在常规的one-stage检测算法中,分类分支都使用Focal loss进行优化,而Focal loss主要针对离散的分类标签。在论文将定位质量与分类分数结合后,其输出变为类别相关的连续的IoU分数,不能直接使用Focal loss。所以论文对Focal loss进行拓展,提出了GFL(Generalized Focal Los),能够处理连续值目标的全局优化问题。GFL包含QFL(Quality Focal Los)和DFL( Distribution Focal Los)两种具体形式,QFL用于优化难样本同时预测对应类别的连续值分数,而DFL则通过对预测框位置进行general分布的建模来提供更多的信息以及准确的位置预测。

下面我将结合代码给大家讲解GFL的思想与实现。

Focal loss(FL)

在这里插入图片描述
FL主要用于解决one-stage目标检测算法中的正负样本不平衡问题,包含标准的交叉熵部分 − l o g ( p t ) -log(p_t) log(pt)以及缩放因子部分 ( 1 − p t ) γ (1-p_t)^\gamma (1pt)γ,其中缩放因子可以降低简单样本权重,提高困难样本在loss的占比,缓和样本不平衡的问题。

Quality Focal loss(QFL)

在这里插入图片描述由于FL仅支持离散标签,为了将其思想应用到分类与定位质量结合的连续标签,对其进行了扩展。首先将交叉熵部分 − l o g ( p t ) -log(p_t) log(pt)扩展为完整形式 − ( ( 1 − y ) l o g ( 1 − σ ) + y l o g ( σ ) ) -((1-y)log(1-\sigma)+ylog(\sigma)) ((1y)log(1σ)+ylog(σ)),其次将缩放因子返泛化为预测值 σ \sigma σ与连续标签y(这里是指gt与anchor的iou)的绝对差值 ∣ y − σ ∣ β |y-\sigma|^\beta yσβ,将其组合得到QFL。

def quality_focal_loss(pred, target, beta=2.0):
    assert len(target) == 2, """target for QFL must be a tuple of two elements,
        including category label and quality label, respectively"""
    # label denotes the category id, score denotes the quality score
    label, score = target

    # negatives are supervised by 0 quality score
    pred_sigmoid = pred.sigmoid()
    scale_factor = pred_sigmoid
    zerolabel = scale_factor.new_zeros(pred.shape)
    loss = F.binary_cross_entropy_with_logits(
        pred, zerolabel, reduction='none') * scale_factor.pow(beta)

    # FG cat_id: [0, num_classes -1], BG cat_id: num_classes
    bg_class_ind = pred.size(1)
    pos = ((label >= 0) & (label < bg_class_ind)).nonzero().squeeze(1)
    pos_label = label[pos].long()
    # positives are supervised by bbox quality (IoU) score
    scale_factor = score[pos] - pred_sigmoid[pos, pos_label]
    loss[pos, pos_label] = F.binary_cross_entropy_with_logits(
        pred[pos, pos_label], score[pos],
        reduction='none') * scale_factor.abs().pow(beta)

    loss = loss.sum(dim=1, keepdim=False)
    return loss

代码如上,首先负样本对应的监督信息是0,QFL中的缩放因子为 ∣ − σ ∣ β |-\sigma|^\beta σβ。然后,通过label找到正样本的pos索引,得到pos_label即pred输出对应的类别,score是指质量得分即anchor与GT的iou,缩放因子就等于score[pos] - pred_sigmoid[pos, pos_label],最后将正样本对应的loss重新赋值,获得最终的loss。

Distribution Focal loss(QFL)

论文将坐标回归的单个值更改成输出n+1个值,每个值表示对应回归距离的概率,然后利用积分获得最终的回归距离。
在这里插入图片描述论文对coco数据进行统计,发现回归距离分布在0-16之间,因此论文将单个坐标回归的值更改为维度为17的输出,分别对应回归距离0-16。下图代码中,x为regression pred,self.project为0-16的tensor。首先使用softmax将x归一化,使x的和为1,这样x与project的期望才能表示回归距离。F.linear就是让x与project做矩阵乘法获得期望。

class Integral(nn.Module):
    def __init__(self, reg_max=16):
        super(Integral, self).__init__()
        self.reg_max = reg_max
        self.register_buffer('project',
                             torch.linspace(0, self.reg_max, self.reg_max + 1))

    def forward(self, x):
        x = F.softmax(x.reshape(-1, self.reg_max + 1), dim=1)
        x = F.linear(x, self.project.type_as(x)).reshape(-1, 4)
        return x

考虑到分布应该集中与回归目标附近,论文提出DFL来强制网络提高最接近y的 y i , y i + 1 y_i,y_{i+1} yi,yi+1的概率,如公式6所示。其中, S i S_i Si表示 y i y_i yi点距离出现的概率,在下面代码中,dis_left表示 y i y_i yi。公式6可以这么理解,假设把0-16的regression target看作一个多分类问题,pred就是多分类的预测值,dis_left,dis_right是label,那么DFL的作用就是希望pred能够接近dis_left,dis_right。换句话说,DFL来强制网络提高最接近y的 y i , y i + 1 y_i,y_{i+1} yi,yi+1的概率。
在这里插入图片描述

def distribution_focal_loss(pred, label):
    dis_left = label.long()
    dis_right = dis_left + 1
    weight_left = dis_right.float() - label
    weight_right = label - dis_left.float()
    loss = F.cross_entropy(pred, dis_left, reduction='none') * weight_left \
        + F.cross_entropy(pred, dis_right, reduction='none') * weight_right
    return loss
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Generalized Focal Loss是一种处理不平衡数据集的损失函数,它在传统的Focal Loss上进行了改进,可以用于多分类和回归任务。YoloV5是一种目标检测算法,它采用一种基于单个神经网络的方法来实现快速而准确的目标检测。结合使用Generalized Focal Loss和YoloV5可以进一步提升目标检测的性能。 在目标检测任务中,不同类别的样本数量往往是不平衡的,一些常见的类别可能会有很多样本,而一些罕见的类别可能只有极少数样本。对于这种情况,使用传统的交叉熵损失函数可能会导致网络偏向于训练样本数量较多的类别,而对于那些样本数量较少的类别则表现不佳。 Generalized Focal Loss采用了类似于Focal Loss的方法来处理不平衡数据集,该方法通过降低容易分类的样本的权重来提高难以分类的样本在训练过程中的重要性。此外,Generalized Focal Loss还添加了一些参数来控制样本难度的权重,这提高了模型对于罕见类别的识别能力。 结合Generalized Focal Loss和YoloV5可以进一步提高目标检测性能。YoloV5现有的版本已经使用Focal Loss来处理类别不平衡的问题,但使用Generalized Focal Loss可以更加灵活地进行参数调节。通过用Generalized Focal Loss替换原有的损失函数,可以减少误分类样本的影响,提高整个模型对于样本数量较少的类别的识别能力,从而进一步提高整个目标检测系统的性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值