目标检测之GFL

2023-11-07

前言

论文地址:https://arxiv.org/pdf/2006.04388.pdf
本博客的讲解代码:https://github.com/open-mmlab/mmdetection
源码:https://github.com/implus/GFocal

1.GFL的主要创新部分

Generalized Focal Loss: Learning Qualified and Distributed Bounding Boxes for Dense Object Detection
论文通过分析预测输出时的分类,回归和定位质量评估的表示,发现他们之间存在一些问题:

  • classification score 和 IoU/centerness score 训练测试不一致(如FCOS的分类分数和中心预测分数)。
    bbox regression 采用的表示不够灵活,没有办法建模复杂场景下的uncertainty
    为了解决这两个问题,作者给这三种预测输出表示设计了新的representations,并提出了Generalized Focal Loss来优化网络。

提出了两种新的表征方式:
将分类分数和检测框质量分数结合,得到分类-质量联合分数,标签变为连续值。
bbox边框的回归值由单一确定值(狄拉克分布)变为一定范围的任意概率分布。
提出了两种新的Focal Loss损失函数:

Quality Focal Loss 对分类-质量联合分数连续值标签进行优化。
Distribution Focal Loss 对边界框的任意概率分布进行优化。
具体可以看原作者的解析:https://zhuanlan.zhihu.com/p/147691786
或者:https://zhuanlan.zhihu.com/p/310229973

2.结合代码体现创新部分

1.训练阶段的预测输出

这部分分数预测输出不变,主要是回归框的变化

    def forward_single(self, x, scale):
        """Forward feature of a single scale level.

        Args:
            x (Tensor): Features of a single scale level.
            scale (:obj: `mmcv.cnn.Scale`): Learnable scale module to resize
                the bbox prediction.

        Returns:
            tuple:
                cls_score (Tensor): Cls and quality joint scores for a single
                    scale level the channel number is num_classes.
                bbox_pred (Tensor): Box distribution logits for a single scale
                    level, the channel number is 4*(n+1), n is max value of
                    integral set.
        """
        cls_feat = x
        reg_feat = x
        for cls_conv in self.cls_convs:
            cls_feat = cls_conv(cls_feat)
        for reg_conv in self.reg_convs:
            reg_feat = reg_conv(reg_feat)
        cls_score = self.gfl_cls(cls_feat)
        bbox_pred = scale(self.gfl_reg(reg_feat)).float()	# 注意这里输出C的变化[B,4*(16+1),H,W]
        return cls_score, bbox_pred

这里,gfl的head部分,self.gfl_reg()输出的是一个一定数量的离散框的回归值。一定数量:表示的是每条边的预测回归输出为(self.reg_max + 1)倍,作者实验得出self.reg_max =16为最佳。

self.gfl_reg = nn.Conv2d(self.feat_channels, 4 * (self.reg_max + 1), 3, padding=1)	# (256,4*(16+1),3)

2.将bbox边框的回归值由单一确定值(狄拉克分布)变为一定范围的任意概率分布。

作者使用softmax函数实现离散形式的任意分布。 P i P_i Pi表示用softmax函数使预测值变为0-1的概率, y i y_i yi从所给的边框范围(16)均匀取值,这样就从一个回归问题变为一个“多分类问题”。
在这里插入图片描述
通过self.integral(pos_bbox_pred)来变化分布

pos_bbox_pred_corners = self.integral(pos_bbox_pred)    # [N,4]

这里注释解释的很清楚,就是通过一个任意分布+一个线性变换来确定预测的回归框lrtb值

class Integral(nn.Module):
    """A fixed layer for calculating integral result from distribution.

    This layer calculates the target location by :math: `sum{P(y_i) * y_i}`,
    P(y_i) denotes the softmax vector that represents the discrete distribution
    y_i denotes the discrete set, usually {0, 1, 2, ..., reg_max}

    Args:
        reg_max (int): The maximal value of the discrete set. Default: 16. You
            may want to reset it according to your new dataset or related
            settings.
    """

    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):
        """Forward feature from the regression head to get integral result of
        bounding box location.

        Args:
            x (Tensor): Features of the regression head, shape (N, 4*(n+1)),
                n is self.reg_max.

        Returns:
            x (Tensor): Integral result of box locations, i.e., distance
                offsets from the box center in four directions, shape (N, 4).
        """
        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

每条边的任意分布为{ x i : p i x_i:p_i xi:pi}, x i x_i xi表示预测的离散lrtb的值, p i p_i pi表示它们离散值对应的分布概率。输入x经过F.softmax处理后就是对应的 p i p_i pi
self.project:给了一个0-16的17个间距为1的值。用来表示边框周围的范围。

F.linear(x, self.project.type_as(x)).reshape(-1, 4)

将每条边的17个预测值通过概率分布预测出一个值,最后重新变为常见的4个lrtb预测输出。
在这里插入图片描述
从这个图可以看出,一些检测对象的边界并非十分明确。对于滑板左侧被水花模糊,引起对左边界的预测分布是任意而扁平的,对右边界的预测分布是明确而尖锐的。

3.Distribution Focal Loss

    需要获得的分布虽然不再像狄拉克分布那么极端,但也应该在标签值附近。因此作者提出Distribution Focal Loss损失函数,目的让网络快速聚焦到标签附近的数值,使标签处的概率密度尽量大。思想是使用交叉熵函数,来优化标签y附近左右两个位置的概率,使网络分布聚焦到标签值附近。
在这里插入图片描述

def distribution_focal_loss(pred, label):
"""
    Args:
        pred (torch.Tensor): Predicted general distribution of bounding boxes
            (before softmax) with shape (N, n+1), n is the max value of the
            integral set `{0, ..., n}` in paper.
        label (torch.Tensor): Target distance label for bounding boxes with
            shape (N,).

    Returns:
        torch.Tensor: Loss tensor with shape (N,).
    """
    dis_left = label.long()     # 转换为长整型,向下取整。偏向左边的值,label:是ltrb格式
    dis_right = dis_left + 1	# 偏向右边的值
    weight_left = dis_right.float() - label   # 小数,公式里的(y_{i+1}-y)
    weight_right = label - dis_left.float()		# (y-y_{i})
    #F.cross_entropy会对输入的pred进行softmax,dis_left为pre进行log_softmax后的索引
    loss = F.cross_entropy(pred, dis_left, reduction='none') * weight_left \
        + F.cross_entropy(pred, dis_right, reduction='none') * weight_right
    return loss

4.Quality Focal Loss

由下图可知,就是联合分类和IOU:预测的box与target box的IOU值作为监督的label,这样label值由一个0,1的离散值,变为0-1的连续值.所以计算分类Loss的时候,是通过分类和IOU的联系进行优化。
在这里插入图片描述

score[pos_inds] = bbox_overlaps(    # 没传中心置信度,是将预测的box与target box的IOU值作为置信度分数
                pos_decode_bbox_pred.detach(),
                pos_decode_bbox_targets,
                is_aligned=True)

计算分类分数的时候将score传入,好进行分类-质量联合分数Loss的计算
# cls (qfl) loss
loss_cls = self.loss_cls(
    cls_score, (labels, score),
    weight=label_weights,
    avg_factor=num_total_samples)

公式中,原始的Fcoal loss针对的标签是离散值(y=0或y=1),这里提出的分类-检测框质量联合表示,其标签y为[0,1]的连续值,σ为预测值。
在这里插入图片描述

def quality_focal_loss(pred, target, beta=2.0):
"""
    Args:
        pred (torch.Tensor): Predicted joint representation of classification
            and quality (IoU) estimation with shape (N, C), C is the number of
            classes.
        target (tuple([torch.Tensor])): Target category label with shape (N,)
            and target quality label with shape (N,).
        beta (float): The beta parameter for calculating the modulating factor.
            Defaults to 2.0.

    Returns:
        torch.Tensor: Loss tensor with shape (N,).
    """
    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
	# 负样本的loss为什么要单独出来计算呢?这里没太明白
    # negatives are supervised by 0 quality score,负样本用0去监督
    pred_sigmoid = pred.sigmoid()   # 前面都没用过sigmod
    scale_factor = pred_sigmoid     # [N,c]
    zerolabel = scale_factor.new_zeros(pred.shape)  #[N,c]
    loss = F.binary_cross_entropy_with_logits(	# 自带sigmod的交叉熵,传入后会对pred进行sigmod
        pred, zerolabel, reduction='none') * scale_factor.pow(beta)  #这里其实全部样本都用0监督了,后面正样本部分会被替换掉

    # 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()	#[pos,]
    # 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

5.后处理部分

        for cls_score, bbox_pred, stride, anchors in zip(
                cls_scores, bbox_preds, self.anchor_generator.strides,
                mlvl_anchors):
            assert cls_score.size()[-2:] == bbox_pred.size()[-2:]
            assert stride[0] == stride[1]
            scores = cls_score.permute(0, 2, 3, 1).reshape(
                batch_size, -1, self.cls_out_channels).sigmoid()   # sigmoid,[N,HWC]
            bbox_pred = bbox_pred.permute(0, 2, 3, 1)   # [N,H,W,4*(16+1)]
            bbox_pred = self.integral(bbox_pred) * stride[0]   # [N,H,W,4]
            bbox_pred = bbox_pred.reshape(batch_size, -1, 4)    # [N,HW4]

bbox_pred = self.integral(bbox_pred) * stride[0] # [N,H,W,4]不同之处只需使用self.integral变换回原来的lrtb格式就行。

3.消融实验

1.QFL

在这里插入图片描述

2.DFL

在这里插入图片描述
在这里插入图片描述
这里对DFL中取合适的数量和间隔进行了实验。

3.QFL+DFL

在这里插入图片描述

总结

十分优秀论文和研究工作!作者在论文后面还有些数据分析,值得阅读。并且作者后续已经发布了GFLV2,基于V1的情况下,利用学习到的bbox的分布来指导分类-质量评估的生成,能带来几乎无损涨点。后续有时间应该会介绍下GFLV2。
博客里所说都是个人理解,欢迎大家进行留言讨论!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

目标检测之GFL 的相关文章

  • 接口文档生成工具ApiPost挺好用

    作为一名程序员我深知一款好用的软件工具对工作效率的提升意味着什么 相信不少程序员还在依靠老外们做的软件处理手头工作 曾经我也是其中一员 不过现在我已经开始迷上了国产软件 国外的自然后他的优势 但国产软件工具也吸引了不少程序员开始尝试 虽然他
  • tensorflow2学习笔记

    目录 Tensorflow2 0特性 构架 TensorflowDemo AlexNet 过拟合 卷积后矩阵尺寸大小的计算 代码地址 VGG 感受野 网络结构 代码地址 GoogLeNet GoogLeNet网络结构 参数 Inceptio
  • [机器学习笔记-3]识别服饰图像的神经网络

    目录 1 安装tensorflow数据集 命令行输入 导入依赖 2 导入Fasion MINST数据集 3 处理数据 4 构建模型 5 训练模型 6 评估准确度 7 预测数据 8 图表显示数据 jupyter notebook中运行注意事项
  • 2020年最新的PHP面试题(附答案)

    684 PHP究竟是不是最好的语言 一直以来是程序员最大的 争议 但毋庸置疑的是 PHP绝对是最有前途和力量的变成语言 也是你入门最值得学习的语言 为什么这么说呢 不妨来了解一下 为什么学PHP 语言入门简单 容易掌握 程序建设性好 开发者
  • javaWeb的项目路径问题(对servlet路径和form表单请求路径的一些归纳)

    javaWeb项目的路径问题 这篇文章大神将路径问题讲的很透彻 我想说的是几点小细节 博主说的很清楚 如果这里的deployment下面的application context中不单单仅是一个 后面加的有其他字符的话 在form表单中我们填

随机推荐

  • 深聊测开领域之:Testcase中资源泄露

    1 引言 2 何为资源泄露 2 1 资源泄露定义 2 2 TestCase 中资源泄露 3 避免资源泄露 3 1 如何避免资源泄露 3 2 自动化执行顺序 1 引言 执行测试时离不开测试用例 测试用例辅佐执行测试 这就好比皇帝与宰相 需要的
  • jekyll网站上传服务器,jekyll 高效搭建个人博客之完整流程

    jekyll png 原创精选来自我的博客文章 目录 说在前面的话 作为一个和电脑 代码打交道的我 一直都想拥有自己的博客 一切都显得那么高 zhuang 大 bi 上 yong 在下定决心之后就在网上到处查找资料 最终发现一般用的就三种
  • 定时任务之Springboot整合Quartz详解

    文章目录 一 什么是Quartz 二 为什么使用Quartz 1 为什么要用定时任务 2 为什么使用Quartz 三 常见开源定时任务的框架的异同 四 Quartz的组件 五 Quartz持久化 1 为什么要持久化 2 Quartz提供了两
  • 解决openwrt ipk missing dependencies libpthread librt

    新版本的trunk有在ipk打包的过程中的bug 他不能自动识别SDK中已经变异的动态链接库 比如libpthread libboost这些 解决方案是修改与pakage里同级的makefile的内容 可以修改如下 主要是添加DEPENDS
  • JavaScprit---基础代码

    var text Hello World document write p text indexOf Hello p document write p text indexOf World p document write p text i
  • MySQL中Select+Update并发的更新问题

    小知识补充 首先 我们要知道在mysql中update操作都是线程安全的 mysql引擎会update的行加上 排他锁 其他对该行的update操作需要等到第一个update操作提交成功或者回滚 才能获取这个 排他锁 从而对该行进行操作 例
  • 程序员如何进行职业规划?

    本文来自作者 王俊生 在 GitChat 上分享 程序员如何进行职业规划 阅读原文 查看交流实录 文末高能 编辑 哈比 一直以来程序员这一职业都给人高薪资的印象 近年来随着互联网行业的快速发展 程序员更是人满为患 然而很多人关注的却是程序员
  • MOS管电源开关电路的软启动

    https mp weixin qq com s 5W8rveh69XVzJoRX XrSfgbeizhu 仅用于标注 适用于我这样的硬件小白
  • React你应该学会的开发技巧【总结】!

    关注公众号 前端人 回复 加群 添加无广告优质学习群 干净的代码不仅仅是工作代码 简洁的代码易于阅读 易于理解并且井井有条 在本文中 我们将研究六种编写更简洁的React代码的方法 在阅读这些建议时 请务必记住它们的实质 相信这些实践对我们
  • 链表两数相和 (2)--Leetcode

    题目描述 给出两个 非空 的链表用来表示两个非负的整数 其中 它们各自的位数是按照 逆序 的方式存储的 并且它们的每个节点只能存储 一位 数字 如果 我们将这两个数相加起来 则会返回一个新的链表来表示它们的和 您可以假设除了数字 0 之外
  • 通过在线游戏练习flex布局和各种css选择器

    懒是一个很好的托辞 说的好像你勤奋了就能干成大事一样 序言 不知道身为后端程序员的你写不写前端代码 反正我是经常写 调布局和样式着实有点费劲 一般像我这样的后端开发都不会系统的去学一些前端知识 都是遇到了就百度 然后复制粘贴一下 再不停的让
  • MyBatis七:自定义映射resultMap

    自定义映射resultMap 一 resultMap处理字段和属性的映射关系 为字段设置别名 是别名和属性名一致 方式一
  • STM32 系统定时器--SysTick

    目录 一 结构图与寄存器 二 SysTick定时时间计算 三 Systick 系统定时器配置程序 如何更改systick中断优先级 四 实验设计 1 通过查询标志位来写延时函数 2 通过使能中断来写延时函数 SysTick 系统定时器 24
  • Java学习笔记之用Box布局swing界面

    主要就用到了这四个方法 createHorizontalBox 创建一个从左到右显示其组件的 Box createHorizontalStrut int width 左右部件之间的中间间隔就可以用这个方法来控制 创建一个不可见的 固定宽度的
  • 如何清空Keil的历史文件记录

    解决方案 先把Keil 关掉再进行以下操作 1 Win R并输入regedit 2 点开HKEY CURRENT USER 3 点开SOFTWARE 4 点开你使用的KEIL 5 点开Recent File List并删除右侧的文件们 除默
  • 2.4G和蓝牙技术

    转自 http 25078558 blog 163 com blog static 8667921420121012103312364 随着笔记本电脑的普及以及用户的数据传输需求 越来越多的笔记本甚至一些中高端的上网本配备了蓝牙模块 此外
  • Ubuntu16.04安装php5.6

    安装步骤 sudo add apt repository ppa ondrej php sudo apt get install apache2 sudo apt get install mysql server mysql client
  • 【springboot】springboot默认logback日志

    一 问题说明 1 运行时记录日常运行的重要信息 应用报错信息 运维过程数据 2 springboot默认使用日志logback 3 日志级别 1 fatal 灾难信息 合计入error 2 error 记录错误堆栈信息 3 warn 记录运
  • 19年电赛经验总结-应该如何准备电赛

    19年电赛经验总结 应该如何准备电赛 写在前面的话 1 赛前准备 2 比赛经历 3 经验总结 写在最后的话 写在前面的话 最近忙着各大厂的实习面试 趁着准备简历的功夫回顾了一下19年电赛的比赛经历 总体来说还算说得过去 现在把我参加电赛的经
  • 目标检测之GFL

    文章目录 前言 1 GFL的主要创新部分 2 结合代码体现创新部分 1 训练阶段的预测输出 2 将bbox边框的回归值由单一确定值 狄拉克分布 变为一定范围的任意概率分布 3 Distribution Focal Loss 4 Qualit