☰
目标检测核心技术:RPN原理与工程实践全解析
2026/10/6 13:22:37 网站建设 项目流程

1. 为什么目标检测绕不开RPN:从"先找候选区"说起

做目标检测的人早晚都会撞上同一个问题:一张图摆在你面前,目标到底框在哪儿?早年的做法是滑动窗口——把整张图按不同尺寸切出几万个窗口,挨个送进分类器判断是不是目标。这个方法笨得可以,计算量爆炸不说,窗口位置稍微偏一点,分类结果就崩。后来大家改用Selective Search,靠颜色、纹理之类的底层特征把可能的目标区域先"聚"出来,再逐个分类。Selective Search比滑动窗口聪明,但问题在于它是个独立的离线模块,跟后面的检测网络完全脱节。更关键的是,它的候选区域是在CPU上跑的,一张图要折腾一两秒,放到实时场景里根本没法用。

Faster R-CNN在2015年被提出来的时候,核心思路就是把候选区域生成这件事从CPU搬到GPU上,并且让网络自己学会"哪里可能有目标"。这个承担候选区域生成的模块,就是RegionProposalNetwork,简称RPN。RPN的神奇之处在于它并不是一个独立于检测网络之外的东西,而是跟后面的检测头共享卷积特征、一起训练。这样设计之后,候选区域生成不再是"预处理步骤",而是整个检测流程里一个可学习、可微分的环节。你如果去读Faster R-CNN那篇论文,标题直接就叫《Towards Real-Time Object Detection with Region Proposal Networks》,可见RPN在当时就是奔着"提速+端到端"去的。

这篇文章我想把RPN从结构到训练、从理论到工程踩坑,完整地捋一遍。适合刚接触目标检测、想知道Faster R-CNN里面到底发生了什么的同学,也适合那些已经跑通代码、但对anchor分配和损失函数细节还一知半解的工程师。看完你应该能回答一个问题:RPN到底是怎么从一张图上"找"出可能包含目标的候选框的。

1.1 传统候选区域生成的瓶颈

在RPN出现之前,主流检测框架走的都是两条腿:先用Selective Search或EdgeBoxes生成大约2000个候选区域,再对每个区域做缩放、分类。这里面有个致命的效率问题:2000个候选区域有大量重叠,每个区域都要单独走一遍卷积网络提取特征,计算冗余非常严重。Fast R-CNN虽然通过RoI Pooling让2000个区域共享整图的卷积特征,但候选区域的生成依然在CPU上,一张图仍要花掉1~2秒。整条pipeline被Selective Search卡着,变成"CPU拖GPU后腿"的尴尬局面。你可以试想一下:你的GPU利用率可能只有20%,剩下的时间全在等CPU把候选框算出来,这放到现在简直是灾难。

更重要的是,Selective Search的候选框是基于颜色、纹理、尺寸等底层视觉线索生成的,它根本不知道"目标长什么样"。它可能在一个大目标的内部切出几十个小窗口,也可能把前后景杂糅在一起。这种"盲目"生成的候选区域,质量上限就摆在那里,分类器再强也救不回来。RPN的思路恰恰相反:让网络先学会"这东西看着像目标",再根据这些粗筛结果去做精确分类。候选区域生成从"手工特征工程"变成了"网络学习的任务",这是质的改变。

1.2 Faster R-CNN选择RPN的核心理由

Faster R-CNN之所以坚持用RPN而不是继续优化Selective Search,理由其实很朴素:要让整个检测框架真正端到端可训练,唯一的办法就是把候选区域生成也变成一个网络模块。RPN本质上是一个轻量的全卷积网络,它输入的是共享的特征图,输出的是候选框以及每个框的"前景分数"。因为卷积特征已经被前面的骨干网络算好了,RPN在上面做操作几乎不增加额外计算量。整张图的前向过程,从图像输入到最终检测结果,全部发生在GPU上,没有CPU参与,没有离线步骤。

这个设计带来的另一个好处是:RPN和后面的检测头能"互相促进"。RPN需要的特征是"哪里有目标"——这是粗粒度的、语义级别的信息;而检测头关心的"这个目标具体是猫还是狗"——这是细粒度的。两者共享同一个特征提取器,训练时梯度会同时优化这两方面的能力,结果就是特征表达比单独训练任何一个任务都更鲁棒。后来大量实验也证明,在VOC和COCO上,RPN+Fast R-CNN的联合训练效果显著优于任何"外部候选区域方法+分类器"的组合。

1.3 RPN的输入输出:先弄清楚边界

RPN的输入和输出听起来很简单,但很多初学者会在这一步懵掉。输入部分:RPN接收的是骨干网络(比如VGG16或ResNet)最后一层卷积输出的特征图。假设输入图像是800×600,经过VGG16的4次池化(stride 16),特征图尺寸就是50×37左右,通道数是512。

输出部分:RPN输出两类东西。一类是每个anchor作为"前景"的概率分数,另一类是anchor相对于ground truth的坐标修正量。也就是说,RPN并不直接输出"最终的候选框坐标",它输出的是"预设框(anchor)的偏移量"。这两者在训练过程中的角色完全不同:分数用来筛选哪些anchor值得留下来,偏移量用来把这些anchor"推"到更准确的位置。RPN之后的RoI Pooling层拿到的,就是经过筛选和坐标修正后的候选框。

2. RPN的骨架:anchor机制与全卷积设计

RPN的核心在设计思想上就两件事:一个叫anchor,一个叫全卷积。理解了这两个词,RPN的一半就算拿下了。anchor解决的是"框从哪来"的问题,全卷积解决的是"怎么高效地处理这些框"的问题。这两件事配合起来,RPN才能在保持精度的同时做到几乎不拖慢整体速度。

2.1 anchor到底是什么:滑动窗口上的"预设框"

anchor这个概念,第一次看特别容易绕晕,但你只要抓住一句话:anchor就是预先铺在特征图每个位置上的、尺寸比例固定的矩形框。RPN在特征图上做3×3的卷积滑窗,滑窗的中心点对应到原图上的位置,就在那个位置放置k个不同尺寸、不同长宽比的anchor。Faster R-CNN原文里k=9,也就是3种尺度(128、256、512像素)乘以3种长宽比(1:1、1:2、2:1)。这9个框cover了图像里常见的物体大小和形状——从瘦高的人,到矮胖的车,再到方方正正的标志牌,基本都逃不出这个组合。你可以把anchor理解成一组"先验假设":网络不需要从零开始预测目标的绝对位置和大小,只需要在预设框的基础上做微调。这个"先验+微调"的范式后来被几乎所有现代目标检测器继承,包括YOLOv2之后的YOLO系列。

那anchor到底有多少个?算一下:特征图上每一个滑窗位置都有k个anchor,整张特征图有H×W个位置,所以anchor总数为H×W×k。拿前面说的50×37的特征图来算,9倍之后大概有16650个anchor。一张800×600的图会产生超过一万六千个"候选位置",这还只是在RPN阶段。听起来很多,但由于这些anchor之间共享卷积计算,实际增加的耗时并没有想象中那么可怕。

这里有个细节值得注意:RPN在做滑窗的时候,3×3卷积的每个位置并不是"每次拿一个框去卷积",而是把整个特征图统一过一遍卷积,再在每一个位置接上两条1×1卷积的分支。这样设计的好处是:anchor的数量再多,计算量也只跟特征图大小有关,跟anchor数量无关。这就是全卷积设计最巧妙的地方——空间上共享权重,计算上独立于anchor数量。

2.2 为什么RPN是全卷积网络:共享计算的工程智慧

“全卷积网络”这个词听起来高大上,其实核心就一句话:网络里只有卷积层和池化层,没有全连接层。全连接层会把特征图压缩成一维向量,丢失空间位置信息,而卷积层的每个输出点天然对应原图的一个局部区域。RPN的判断必须基于"框里面的内容",所以空间位置信息绝不能丢。此外,全卷积网络对输入图像尺寸没有固定要求——你给它一张任意尺寸的图,它都能输出对应尺寸的特征图,这在检测任务里非常重要,因为检测框的尺寸差异太大了。

更关键的是计算共享。骨干网络已经算好了特征图,RPN接着在这张特征图上做3×3卷积和两个1×1卷积分支。如果RPN是独立的网络,就得把特征图重新喂一遍,计算量直接翻倍。但因为它是在已有特征图上"接着算",整个增加的计算量几乎可以忽略。论文里给过一个数字:RPN的额外计算量在VGG16上大约只占总计算量的10%。这就是为什么Faster R-CNN能做到接近实时的底气所在。

2.3 9个anchor的来龙去脉与平移不变性

很多人会问:为什么一定是3个尺度×3个比例,而不是5个尺度×5个比例?这个问题没有绝对答案。3×3=9是权衡了召回率和计算量的结果。如果你把anchor数量提高到25个(5×5),召回率确实会上去一点,但正样本数量大爆炸,训练时会引入大量低质量的匹配,还会让NMS的处理时间直线上升。反过来,如果只用1个尺度和1个比例(k=1),遇到长宽比极端的目标就完全抓瞎。所以9这个数字是实践出来的平衡点,后来很多工作比如Cascade RPN、GA-RPN都尝试过更复杂的anchor设计,但收敛速度、显存占用、训练稳定性都比原始的9个anchor方案更难调。

RPN另一个被反复提及的性质是平移不变性:如果你把图像里的目标平移几个像素,RPN给出的anchor对应的分类概率和回归偏移量也会平移相同像素,而不会变化。这个性质来自全卷积结构——卷积的权重在空间上是共享的,不管你滑窗滑到哪个位置,用的是同一套参数。对比一下,Selective Search就没有这个性质:你把图像平移一下,它分出来的区域完全可能变样。平移不变性意味着RPN学到的规则是"看到这个形状就认为它是前景",而不是"在坐标(100,200)附近的是前景"。这对模型的泛化能力至关重要。

3. 分类与回归:RPN如何输出"靠谱"的候选框

RPN在具体实现上分成两条分支:一条判断anchor里有没有物体(分类),一条修正anchor的位置(回归)。两条分支共享同一个3×3卷积的输出,但各自接了一个1×1卷积层。这听起来简单,实际实现的时候有不少值得展开的细节。

3.1 二分类分支:前景与背景的博弈

分类分支的输出维度是2k(对应k个anchor各自的前景分数和背景分数),但在具体实现里很多人用的是1个输出通道+ Sigmoid,也就是只输出前景概率,背景概率用1减去它。两种做法数学上是等价的,但工程上Sigmoid版本更好调——它不会像Softmax那样强制两个类别互斥,而在"这张图上几乎所有anchor都是背景"的场景下,Softmax两个输出头的梯度经常不平衡,反而更难收敛。

判断一个anchor是前景还是背景,标准很简单:它和某个ground truth框的IoU大于0.7,就是正样本;和所有ground truth框的IoU都小于0.3,就是负样本。那IoU在0.3到0.7之间的anchor呢?在训练时直接忽略掉,不参与损失计算。为什么?因为这部分anchor边界模糊,说它是正样本吧,框得不太准;说它是负样本吧,里面又确实有目标。硬塞进训练只会让分类器学得犹犹豫豫,不如直接放弃。这个"灰区忽略"的思路在目标检测里非常常见,很多trick本质上都是在界定"哪些样本值得学、哪些不值得学"。

3.2 边界框回归分支:4个偏移量的精细调节

回归分支的输出维度是4k,对应每个anchor的四个参数:tx, ty, tw, th。这四个参数不是直接回归目标框的绝对坐标,而是回归相对于anchor的偏移。具体公式如下:

tx = (x - xa) / wa ty = (y - ya) / ha tw = log(w / wa) th = log(h / ha)

其中xa、ya、wa、ha是anchor的中心坐标和宽高,x、y、w、h是ground truth框的坐标和宽高。也就是说,RPN的回归目标是"从anchor到真实框的位移和缩放"。为什么要用log而不是直接用w/ha?因为直接回归宽高比值的话,小目标的微小变化会被放大,大目标的同比例变化反而被忽略,导致训练不稳定。log变换把乘除关系变成加减关系,让不同尺度的目标回归难度保持一致。

这里有个容易踩的坑:回归分支的梯度跟anchor的尺度是耦合的。如果anchor的尺度过大,它覆盖的正样本范围就大,回归分支要去预测的位移范围也大,训练初期很难收敛。所以正样本的筛选不能只看IoU,还得对回归目标做归一化——Faster R-CNN的做法是在计算损失时用均值方差标准化,也就是把tx、ty、tw、th除以对应的标准差。后来在mmdetection等框架里,这个标准化系数被直接固化成了超参数,默认值来自COCO数据集的统计结果。你在自己数据集上如果发现loss降不下去,第一件该检查的事就是回归目标的分布,而不是急着换骨干网络。

3.3 NMS与Top-N:从2万个框到2千个框

RPN的输出在送入后续检测头之前,还得经过一道筛选。特征图上每个位置都有9个anchor,加起来约2万个框。这些框有大量重叠,如果不处理就直接送去RoI Pooling,计算量会非常浪费,而且还可能让后面的分类器看到一堆几乎一样的输入。

筛选的第一步是NMS(非极大值抑制)。具体流程是:先按前景分数从高到低排序,取分数最高的框,把所有跟它IoU大于某个阈值的框全部删掉,然后重复这个过程。在RPN里,NMS的IoU阈值一般设在0.7。阈值设太高,重叠框删不干净,后续计算压力大;设太低,可能会把一些真正的目标框误删,导致recall下降。经过NMS之后,再从剩下的框里取分数最高的Top-N。训练阶段一般取2000个,测试阶段取300个。Faster R-CNN论文里有张图展示了这个筛选过程的效果——NMS之前,一个目标上可能叠着几十个框;NMS之后,基本每个目标只剩一个质量最高的框。

需要特别注意的是,RPN阶段做完NMS和Top-N筛选后,这些框还是"候选区域",它们会经过RoI Pooling固定到统一尺寸,然后送进分类分支和回归分支做最终的类别判断和精细位置修正。所以整个检测框架其实有两层"分类+回归"结构:RPN一层,做粗筛;检测头一层,做精判。理解这个"由粗到精"的思想,是理解整个Faster R-CNN体系的关键。

4. RPN训练与正负样本分配:最容易翻车的地方

RPN的训练细节,是复现论文时最容易出问题的地方。很多人在跑通代码后,发现RPN的loss掉了但检测精度上不去,或者训练过程剧烈震荡,八成都是正负样本分配和数据采样策略没搞对。这一节讲清楚RPN是怎么训练的,附带我对这些细节的理解。

4.1 正负样本定义:IoU阈值从哪来

上面提到过:IoU大于0.7的anchor是正样本,小于0.3的是负样本,中间的直接忽略。但这里有几个细节需要展开。

第一个细节:如果一个anchor和多个ground truth框的IoU都超过了0.7,那它应该分配给哪个目标来回归?答案是:取IoU最大的那个。这个策略保证了anchor只学一个目标的位置,不会"左右逢源"学出一个四不像。实现时一般是这样:计算所有anchor和所有gt之间的IoU矩阵,对每个anchor找出与之IoU最大的gt,用它作为回归目标;当出现两个anchor抢一个gt时,按IoU排序分先后。

第二个细节:如果一个gt框非常小,可能没有任何anchor跟它的IoU达到0.7,那它就会被漏掉。Faster R-CNN处理这种情况的策略是:对于那些跟任何anchor的IoU都达不到0.7的gt框,把与之IoU最大的那个anchor强行标记为正样本。这个"保底"机制保证了每个gt框至少有一个anchor负责召回。在实际工程里,如果你的数据集小目标特别多,这个保底操作几乎决定了召回率的下限。

第三个细节:0.3和0.7这两个阈值不是随便拍的。它等价于要求anchor和gt的中心距离不超过某个范围且大小比不能太离谱。你可以想象一下,当IoU刚好是0.7时,anchor和gt的大小偏差大约在30%以内,中心偏移大约在框对角线长度的20%以内。这个范围对应"粗筛"的容忍度:太严(比如0.8以上)会导致正样本太少、训练数据不足;太松(比如0.5)会导致anchor定位精度太差,回归分支压力过大,后面的检测头根本救不回来。

4.2 采样策略:为什么每张图只取256个anchor

前面说了,一张图会产生几万个anchor,但在训练时并不全用,而是从中采样256个。这里面有多个层面的考量。

第一个层面是正负样本平衡。直接拿全部anchor训练的话,正负比例大概是1:1000甚至更夸张,分类器会完全被负样本淹没,变成"永远预测背景"的废物。采样时保持正负样本1:1的比例,分类分支学到的决策边界会更合理。如果一张图里的正样本不够128个,就用负样本补足到256个。

第二个层面是Batch大小的合理分配。RPN是在特征的"每一层"上做预测,每个位置都产出一组预测。如果单张图的anchor数量太多,梯度更新幅度会被大量简单负样本主导,影响优化效率。256是经过实验验证的平衡数——既足够提供稳定的梯度估计,又不会让单张图的训练时间被RPN分支拖死。

第三个层面是随机性。如果总是挑分数最高的正样本和负样本去训练,模型会觉得"所有目标都很清晰、所有背景都很干净",泛化能力会很差。随机采样的目的就是让模型在训练时"见识"各种难度的样本,尤其是那些跟背景很像的前景和跟前景很像的背景。有些人会把Hard Negative Mining直接用在这里,但RPN的训练一般不这么做——因为RPN本身只是粗筛,太难的样本留着给后面的检测头去啃,没必要在这里就"卷"起来。

4.3 损失函数与训练轮次:细节里的魔鬼

RPN的多任务损失函数长这样:

L({pi}, {ti}) = (1/N_cls) * Σ L_cls(pi, pi*) + λ * (1/N_reg) * Σ pi* * L_reg(ti, ti*)

前半部分是分类损失,用的是一般是二分类交叉熵;后半部分是回归损失,用的是Smooth L1。Smooth L1在误差较小的时候是二次函数(梯度平滑),误差较大的时候是一次函数(梯度不爆炸),比单纯的L2损失稳健得多——因为回归目标里偶尔会有离群值,L2会对这些离群值给超大梯度,把训练带偏。

两个细节值得注意。第一,回归损失前面乘了一个pi*,意思是只有正样本才计算回归损失,负样本的回归损失置零。负样本本来就没有对应的gt框,硬让网络去回归一个"没有意义"的目标只会让特征变乱。第二,λ的作用是平衡分类和回归两个任务的量级。原文里λ=10,但因为N_cls和N_reg做了归一化(都除到底数256和正样本数量),λ=10几乎是在平衡"分类贡献"和"回归贡献"的权重。实际操作中这个值大多不用调,但如果你自己实现了RPN且发现训练时回归loss下降得异常慢,可以试着调大λ。

RPN和Fast R-CNN的联合训练方式,原文用的是四步交替法:第一步,单独训练RPN;第二步,用训练好的RPN生成候选框,拿去训练Fast R-CNN检测头;第三步,固定检测头的参数,只微调RPN的共享卷积层;第四步,固定共享卷积层,微调检测头特有层。这套流程在当年GPU算力有限的情况下非常实用。现在的主流框架基本都采用端到端联合训练,一步到位——因为你有了足够大的batch size和足够多的迭代轮次,交替训练的稳定性优势不再明显。如果你在mmdetection里跑Faster R-CNN,落地训练就是一个完整pass,RPN和检测头的loss加权求和之后一起回传。

5. 工程实战:RPN的调参与边界经验

跑通RPN不是终点,真正让人头大的是把它调好。我在实际项目里踩过不少坑,也总结了一些不一定写在论文里、但真实有用的经验。这一节拿出来分享,针对几个高频问题。

5.1 anchor的尺寸和比例怎么定:不是玄学

anchor的默认配置是128、256、512三种尺度和1:1、1:2、2:1三种比例,这些值是基于PASCAL VOC数据集的统计结果设定出来的。如果你换到别的数据集,直接沿用这套配置会出问题。比如检测卫星遥感图像里的飞机场,那长宽比可能到1:5以上;检测工业质检里的微小划痕,目标尺寸可能只有8×8像素。这时候还拿512尺度的anchor去套,正样本数量会少到没法训练。

我的做法是:先拿标注数据做一次统计分析,把GT框的宽度、高度、长宽比分布画出来,然后把anchor的尺度和比例设定在分布的“主峰”附近。具体来说,anchor的尺度应该覆盖GT宽高分布的中位数上下几个数量级,最好让大部分GT框跟某个anchor的IoU都高于0.5。如果你的GT框宽度在10到50像素之间,那anchor尺度可以设成8、16、32、64四档,而不是原来那三个大尺寸。还有个trick是直接在训练中动态学习anchor的尺度和比例——这就是后面GA-RPN和自适应anchor的思路,但实现复杂度更高,训练也更不稳定,前期还是建议手工统计稳一稳。

5.2 正负样本严重失衡:为什么RPN能扛住,但别太自信

RPN的整体结构对正负样本不均衡有一定的天然鲁棒性:因为它在每个滑窗位置独立做预测,背景anchor再多,也只是增加了负样本的采样池,随机采样256个能维持一个相对均衡的训练分布。但这不意味着你可以对失衡问题完全放任不管。极端情况下,比如一张高分辨率的航拍图里只有一栋楼,正样本可能就十几个,负样本几十万,采样比例再均衡,模型能学到的目标特征也极其有限。

应对方法有几个。一是减小NMS的IoU阈值,别让正样本之间互相竞争得太狠;二是增加anchor的尺度档位,让更多anchor能跟目标框产生有效IoU;三是在采样时给正样本更高的权重,强行让正样本的比例超过0.5;四是做数据增强时多用crop和scale变换,给目标制造更多“不同尺度下的出现机会”。我自己在标注数据不足一年且类别极度不平衡的任务上,还试过用Focal Loss替换掉二分类交叉熵。Focal Loss的核心是压低“已经很好分类”的负样本的loss贡献,让模型把注意力集中在难以分类的样本上。效果确实有——至少RPN的recall上去了几个点。

5.3 NMS阈值和输出数量的影响,测试老翻车

NMS的IoU阈值在RPN里默认是0.7,但这个值不是固定的。不同数据集的最优值差异挺大。比如行人检测数据集,目标高度重叠,阈值就得放宽(调大到0.8~0.9),不然挨得近的两个人会被NMS误杀成一个。又比如像物体比较稀疏的场景,阈值保持在0.7就挺好。怎么找最优值?我的方法是:单独把RPN拎出来在验证集上测一下recall曲线——统计在IoU=0.5、0.75这两个标准下,前100/300/500个候选框能覆盖多少GT框。如果recall很高但后面检测头精度上不去,说明候选框质量虽然够但数量太多,重复框太多拖累了最终结果;如果NMS之后recall偏低,说明阈值太严了,需要调整。

输出数量方面,训练时用2000个候选框是因为RPN需要尽量多的高质量正样本来喂后面的检测头;测试时用300个是平衡了精度和速度。在工程落地时如果追求极致速度,可以再压到100个,你会发现mAP掉的幅度通常在1个点以内,但推理速度能提升10%以上。如果追求极致精度,可以保留2000个,但检测头的RoI Pooling会变成计算瓶颈,需要配合TensorRT之类的东西做加速。

5.4 从Faster R-CNN到现代检测器:RPN的演进方向

RPN的思想影响深远,衍生出了一大批改进方向。最直接的是FPN(特征金字塔网络):骨干网络不同层级的特征图分辨率不同,语义信息也不同,FPN把多层特征合并起来,RPN就同时在每一层特征图上做预测。这样原本只在一个尺度上做检测的RPN扩展成了多尺度检测,对小目标的召回率提升显著。目前主流检测框架里用的RPN基本都是FPN版的,原始的"在最后一层特征图上做RPN"已经成为过去式。

另一个值得关注的是Cascade RPN,它在RPN的多次迭代上做了改进:第一次RPN产生粗糙的候选框后,不直接送去检测头,而是再做一次回归精修。它的核心发现是:RPN输出的候选框质量其实不高,尤其是IoU分布在0.5左右的框占了大多数,这些框喂给后面的检测头会产生大量低质量训练样本。通过多个stage的级联回归,候选框的IoU分布被逐步推向更高区间,后面的检测头就能学到更有区分度的特征。这套思路后来也被Cascade R-CNN发扬光大。

还有GA-RPN(Guided Anchoring),它让网络先预测"目标可能出现在哪、应该用什么尺度的anchor",再根据预测结果动态生成anchor,而不是全图均匀铺anchor。这种方法在密集小目标场景下效果很惊艳,但训练也很不稳定,调参成本比较高。如果你在做一个标准的通用检测任务,我还是建议先把手动anchor的RPN调好,再考虑这些花哨的变体——baseline稳了,才有资格谈优化。

5.5 几个RPN调试的实战检查清单

最后分享一份我自己用的排查清单,当RPN表现不对时,按顺序检查这几项,大部分问题都能定位出来:

  • 检查anchor和GT的IoU分布:如果大部分GT框连最高的anchor IoU都不到0.5,说明anchor配置肯定有问题,重新统计GT尺寸并调整anchor。
  • 检查正样本数量:训练早期如果每张图的正样本数量长期停留在个位数,说明GT框太小或anchor尺度太大,召回率会非常差。
  • 检查RPN的召回率:单独测RPN阶段Top-N候选框覆盖了多少GT框。如果Top-300的recall低于0.9,检测头再强也白搭,问题铁定出在RPN。
  • 检查NMS前后的候选框分布:NMS之后如果还有大量IoU接近1的重复框,NMS阈值需要调低;如果NMS之后候选框整体偏移严重,回归分支的训练可能有问题,看看学习率和Smooth L1的sqrt_delta参数是否合理。
  • 检查RPN和检测头的loss数值比例:如果RPN的loss占了整体loss的80%以上,说明RPN任务太简单或权重失衡,导致梯度主导了共享特征的更新方向,检测头学不到有效特征,需要调低λ。

就我自己跑了这么多年检测模型的经验,RPN是最不值得你去“魔改”的模块,但也是最值得你“吃透”的模块。anchor机制、正负样本分配、NMS处理这套逻辑,几乎是所有现代检测器共享的底层语言。你把RPN的每个细节都弄明白了,后面无论去读YOLO、SSD、DETR哪一派的代码,都能快速理解它们的设计动机和差异点。说到底,目标检测这碗饭,RPN就是那张必须坐稳的饭桌。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询