读论文(6)——RetinaNet(focal loss)

前言

原论文题目是《Focal Loss for Dense Object Detection》。这篇文章主要是介绍了一种特殊的损失函数focal loss,RetinaNet则是作者为了证明focal loss有效而专门搭建的一个单阶段目标检测器。值得一提的是,本文来自何恺明团队,这个团队还曾提出过大名鼎鼎的、目前被引次数最多的ResNet。看完focal loss这篇文章,我个人感觉这个改进方法非常之简洁,简单到好像单独拿出来发论文都有点说不过去,但是它的效果确实是十分的有效。

问题与思路

通过前面的学习我们知道,目标检测方法可以分为两大类:两阶段和单阶段。其中单阶段的方法虽然较为简单且速度更快,但一般其精度要比两阶段的方法低。造成这一现象的主要原因是单阶段的方法往往在训练密集检测器时前景与背景类的数量极度不平衡
那么为什么会造成类不平衡的问题呢?双阶段又是如何在一定程度上避免了这个问题呢?
类不平衡问题的形成原因是图片中的物体框数量一般来说都小于背景框的数量,也就是说不是所有的框都能检测出物体
对于单阶段方法来说,只有一次分类,因此是细分类,这就导致背景类和如猫、狗等具体类是平行进行分类的,因此显然背景类的数量比每个细分的具体类多太多。
而两阶段的方法首先进行一个粗分类,也就是先对是前景还是是背景进行一个二分类,虽然这样还是背景类比前景类要多,但是和每个细分的具体类相比,背景类和前景类的数量更接近,也就是更平衡。

那么我们怎么解决这个类不平衡的问题呢?
总体思路是让各类的贡献尽可能平衡
一个很自然的想法是对多的类进行抽样来均衡这种不平衡,比如固定前景类和背景类比例为3:1(faster R-CNN),但是这样显然没有充分利用所有的信息。那么我们不如换一种思路,也就是所有的类都要,但是对每种情况采用不同的权重进行处理,从这种思路出发最直接的做法就是去修改损失函数。之前有一种常用的方法称难例挖掘(我们在SSD中学习过),对于指向同一个目标的ROI,取满足条件且loss最大的几个ROI用作训练,其他都删除,以此来提高难样本的比例。这其实就是对每种情况的权值粗暴的赋予了0或1。但focal loss不同,它使得样本稀少的和难分类的权重相对增加,让模型更关注这一部分的训练

focal loss

这部分主要来看看focal loss是怎么构造的。
首先来看最原始的二分类交叉熵损失函数:
在这里插入图片描述
然后我们把这个式子的分段情况用一个新变量pt给抹去:
在这里插入图片描述
得到:
在这里插入图片描述
我们可以先分析一下这个损失函数的特点,我们可以发现,这个损失函数对于pt>>0.5的易分类样本也会产生一定的loss,而且这些loss累计加起来之后
会淹没难分类样本的对loss的贡献。
一个自然而然地想法是加上权重,首先定义一个权重 α \alpha α(取值[0,1]),将其设置为类频率的倒数或者一个又交叉验证设置来的超参数。仿照 p t p_t pt的定义来定义权重 α t \alpha_t αt,得到改进后的CE:
在这里插入图片描述
个人认为, α \alpha α可以用来让样本稀少的类别权重高一些,起到控制类内样本数量不平衡的作用,但是还是没有解决对易分类和难分类样本的平衡。
因此修改损失函数:
在这里插入图片描述
由上式,可得:
(1)当一个样本难分类时, p t p_t pt是接近0的,那么对应的调制因子就接近于1,进而这个loss是不受影响的;而当一个样本易分类时, p t p_t pt接近1, ( 1 − p t ) γ (1-p_t)^{\gamma} (1pt)γ接近0,因此loss相当于被降权重了。
(2) γ \gamma γ这个参数可以调整易分类样本被降低权重的比率,实验验证 γ \gamma γ时效果最好。

这个函数就可以很好的控制易分类和难分类样本的平衡了,这我们也可以成为是一种难例挖掘方法。我们把 α \alpha α参数再加进来:
在这里插入图片描述
这就是完全体的focal loss了。通过这种处理,样本稀少的权重变高,样本多的权重变小,样本易分类的权重变低,样本难分类的权重不变(相比易分类相当于权重变多)。因此模型就会更加关注样本数少的(如前景),更加关注难分类的,这就解决了样本不平衡的问题。
网上有人总结了一个表格,正好和我上面说的一致:
在这里插入图片描述

RetinaNet

这一部分讲RetinaNet。我们说过,RetinaNet是何恺明团队专门写来用来验证focal loss强大之处的一个简单的目标检测器。
RetinaNet其实就是一个ResNet提取特征、FPN做backbone、两个自网络作检测、focal loss做损失函数的单阶段目标检测器,其具体结构如下:
在这里插入图片描述
其中FPN是在P3到P7级上构建的,在每个金字塔级上,都使用三种纵横比的anchors(和FPN原论文设置一样,{1:2,1:1,2:1}),在每一级的原来的3种纵横比上还增加了3种尺度大小({20,21/3,22/3}),采用FPN的主要原因是只用ResNet的效果不好。
两个子网一个用于分类,一个用于框的回归。
分类子网络会对每个位置的每个anchor(A个)的每个类别(K个)进行概率预测。这个子网络是在每个FPN级上联接一个小的FCN;这个子网络的参数在所有金字塔级上是共享的,最后联接sigmoid激活函数对于每个位置输出KA个二分类预测值。相比于RPN,这个分类子网络更深,且只采用3×3卷积核。
与目标分类子网络并行,本文对于金字塔的每一级联接了另一个小的FCN来对每个anchor对其临近的ground truth框(如果存在)进行回归。注意,分类子网络不与框回归子网络共享参数。

结果

在这里插入图片描述
由上表可以看出,RetinaNet的性能还是十分强悍的。

总结

这篇论文感觉最创新的点就在于focal loss这个损失函数的提出,RetinaNet倒是没有什么很让人眼前一亮的感觉。通过解读focal loss,我们可以很明显的体会到一点,那就是他真的非常简洁且有效,颇有种大道至简的意味。只对损失函数做了很小的改动,就可以使得效果有如此多的提升,这让人感到十分的震撼。

### Focal Loss 的定义与背景 Focal Loss 是一种专为解决类别不平衡问题而设计的损失函数,在目标检测领域尤其重要。它由 Lin 等人在 RetinaNet 论文中首次提出,旨在改进标准交叉熵损失的表现[^3]。当数据集中正负样本数量差异较大时,模型容易偏向于预测多数类,从而降低少数类别的识别精度。 Focal Loss 的核心思想是对难分类样本赋予更高的权重,同时减少简单样本对总损失的影响。其公式如下: \[ FL(p_t) = -(1-p_t)^{\gamma} \log(p_t) \] 其中 \(p_t\) 表示预测概率,\(γ\) 控制调焦的程度。随着 \(γ\) 增大,易分样本的贡献逐渐减小,从而使模型更加关注那些难以区分的样本[^3]。 --- ### 实现细节 以下是基于 PyTorch 和 TensorFlow 的两种实现方式: #### 使用 PyTorch 实现 Focal Loss ```python import torch import torch.nn as nn import torch.nn.functional as F class FocalLoss(nn.Module): def __init__(self, alpha=1, gamma=2, reduction='mean'): super(FocalLoss, self).__init__() self.alpha = alpha self.gamma = gamma self.reduction = reduction def forward(self, inputs, targets): ce_loss = F.cross_entropy(inputs, targets, reduction='none') pt = torch.exp(-ce_loss) focal_loss = self.alpha * (1-pt)**self.gamma * ce_loss if self.reduction == 'mean': return focal_loss.mean() elif self.reduction == 'sum': return focal_loss.sum() else: return focal_loss ``` 此代码片段实现了动态调整权重的功能,并允许用户自定义超参数 `alpha` 和 `gamma` 来适应不同的应用场景[^4]。 #### 使用 TensorFlow 实现 Focal Loss ```python import tensorflow as tf def focal_loss(gamma=2., alpha=.25): def focal_loss_fixed(y_true, y_pred): epsilon = 1e-7 y_pred = tf.clip_by_value(y_pred, epsilon, 1. - epsilon) pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred)) pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred)) fl = -alpha * ((1. - pt_1) ** gamma) * tf.math.log(pt_1) \ - (1-alpha) * (pt_0 ** gamma) * tf.math.log(1. - pt_0) return tf.reduce_sum(fl) return focal_loss_fixed ``` 上述代码适用于二分类或多分类场景下的深度学习框架 TensorFlow 中的应用[^5]。 --- ### 应用案例 Focal Loss 广泛应用于图像分割、目标检测等领域。例如,在医学影像分析中,由于病变区域通常较小且稀疏,传统方法可能无法有效捕捉这些微弱信号。引入 Focal Loss 后可以显著提升模型对于罕见病灶的检出率[^6]。 此外,在自动驾驶技术开发过程中也经常遇到类似的挑战——远处的小型车辆或行人往往占据较少像素比例却至关重要。因此采用该优化策略能够帮助提高整体性能表现水平[^7]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值