{"notes":[{"id":"object-detection/rt-detr","category":"object-detection","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"RT-DETR","subtitle":"把 NMS 算进秒表","author":"Z. Yuan","paperDate":"2023-04-17","publishedOn":"2025-01-29","world":"external/rt-detr","paperTitle":"DETRs Beat YOLOs on Real-time Object Detection","paperUrl":"https://arxiv.org/abs/2304.08069","bibliography":{"title":"DETRs Beat YOLOs on Real-time Object Detection","authors":["Yian Zhao","Wenyu Lv","Shangliang Xu","Jinman Wei","Guanzhong Wang","Qingqing Dang","Yi Liu","Jie Chen"],"url":"https://arxiv.org/abs/2304.08069","pdfUrl":"https://arxiv.org/pdf/2304.08069v3","codeUrl":"https://github.com/lyuwenyu/RT-DETR","preprint":{"id":"2304.08069","submittedOn":"2023-04-17","url":"https://arxiv.org/abs/2304.08069"},"publication":{"venue":"CVPR","year":2024,"kind":"conference","url":"https://openaccess.thecvf.com/content/CVPR2024/html/Zhao_DETRs_Beat_YOLOs_on_Real-time_Object_Detection_CVPR_2024_paper.html"},"citation":"@misc{objectdetectionrtdetr2023,\n  title = {{DETRs Beat YOLOs on Real-time Object Detection}},\n  author = {Yian Zhao and Wenyu Lv and Shangliang Xu and Jinman Wei and Guanzhong Wang and Qingqing Dang and Yi Liu and Jie Chen},\n  year = {2023},\n  eprint = {2304.08069},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2304.08069}\n}\n","citationPath":"/content/papers/citations/object-detection/rt-detr.cbe42f7a5b6c.bib"},"thumbnail":{"src":"/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png","width":1360,"height":332},"locale":"zh-hans","path":"/content/papers/zh-hans/object-detection/rt-detr.694145ddec22.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"nms-要花多少时间","text":"NMS 要花多少时间？","depth":3},{"id":"端到端的秒表","text":"端到端的秒表","depth":3},{"id":"detr-慢在哪里","text":"DETR 慢在哪里？","depth":3},{"id":"解决问题","text":"解决问题","depth":2},{"id":"先看全貌","text":"先看全貌","depth":3},{"id":"encoder-的账","text":"Encoder 的账","depth":3},{"id":"aifi只在-s5-做自注意力","text":"AIFI：只在 S5 做自注意力","depth":3},{"id":"ccff跨尺度的融合交给卷积","text":"CCFF：跨尺度的融合交给卷积","depth":3},{"id":"挑出-300-个查询","text":"挑出 300 个查询","depth":3},{"id":"decoder去掉后面几层","text":"Decoder：去掉后面几层","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"和-yolodino-比","text":"和 YOLO、DINO 比","depth":3},{"id":"阈值要怎么设","text":"阈值要怎么设？","depth":3},{"id":"换一台机器","text":"换一台机器","depth":3},{"id":"偶尔还是有重复框","text":"偶尔还是有重复框","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"object-detection/detr","relation":"referenced","topic":""},{"id":"object-detection/deformable-detr","relation":"referenced","topic":""},{"id":"feature-fusion/panet","relation":"referenced","topic":""}]},{"id":"object-detection/detr","category":"object-detection","legacyPath":"object-detection/2005-detr","legacySlug":"2005-detr","legacyPaths":[],"title":"DETR","subtitle":"跨领域的奠基者","author":"Z. Yuan","paperDate":"2020-05-26","publishedOn":"2024-06-04","paperTitle":"End-to-End Object Detection with Transformers","paperUrl":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php","bibliography":{"title":"End-to-End Object Detection with Transformers","authors":["Nicolas Carion","Francisco Massa","Gabriel Synnaeve","Nicolas Usunier","Alexander Kirillov","Sergey Zagoruyko"],"url":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php","pdfUrl":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/papers/123460205.pdf","codeUrl":"https://github.com/facebookresearch/detr","preprint":{"id":"2005.12872","submittedOn":"2020-05-26","url":"https://arxiv.org/abs/2005.12872"},"publication":{"venue":"ECCV","year":2020,"kind":"conference","url":"https://www.ecva.net/papers/eccv_2020/papers_ECCV/html/832_ECCV_2020_paper.php"},"citation":"@misc{objectdetectiondetr2020,\n  title = {{End-to-End Object Detection with Transformers}},\n  author = {Nicolas Carion and Francisco Massa and Gabriel Synnaeve and Nicolas Usunier and Alexander Kirillov and Sergey Zagoruyko},\n  year = {2020},\n  eprint = {2005.12872},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2005.12872}\n}\n","citationPath":"/content/papers/citations/object-detection/detr.5258ffe0b9a0.bib"},"thumbnail":{"src":"/content/papers/assets/dd7e8441e6460ff562cf558374789924518fafaed7ecde0e3e35ee778c316330.jpg","width":1024,"height":266},"locale":"zh-hans","path":"/content/papers/zh-hans/object-detection/detr.99d0f3b81385.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"模型架构","text":"模型架构","depth":3},{"id":"损失设计","text":"损失设计","depth":3},{"id":"数据集","text":"数据集","depth":3},{"id":"技术细节","text":"技术细节","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"这次行吗","text":"这次行吗？","depth":3},{"id":"模型组件分析","text":"模型组件分析","depth":3},{"id":"模型行为分析","text":"模型行为分析","depth":3},{"id":"对未见过目标数量的泛化能力","text":"对未见过目标数量的泛化能力","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"object-detection/deformable-detr","relation":"next","topic":"集合预测与注意力检测器"},{"id":"object-detection/smca-detr","relation":"comparison","topic":"让 Transformer 检测器更快收敛"}]},{"id":"object-detection/deformable-detr","category":"object-detection","legacyPath":"object-detection/2010-deformable-detr","legacySlug":"2010-deformable-detr","legacyPaths":[],"title":"Deformable DETR","subtitle":"可变形的注意力机制","author":"Z. Yuan","paperDate":"2020-10-08","publishedOn":"2024-09-20","paperTitle":"Deformable DETR: Deformable Transformers for End-to-End Object Detection","paperUrl":"https://arxiv.org/abs/2010.04159","bibliography":{"title":"Deformable DETR: Deformable Transformers for End-to-End Object Detection","authors":["Xizhou Zhu","Weijie Su","Lewei Lu","Bin Li","Xiaogang Wang","Jifeng Dai"],"url":"https://arxiv.org/abs/2010.04159","pdfUrl":"https://arxiv.org/pdf/2010.04159","codeUrl":null,"preprint":{"id":"2010.04159","submittedOn":"2020-10-08","url":"https://arxiv.org/abs/2010.04159"},"publication":{"venue":"ICLR","year":2021,"kind":"conference","url":"https://arxiv.org/abs/2010.04159"},"citation":"@misc{objectdetectiondeformabledetr2020,\n  title = {{Deformable DETR: Deformable Transformers for End-to-End Object Detection}},\n  author = {Xizhou Zhu and Weijie Su and Lewei Lu and Bin Li and Xiaogang Wang and Jifeng Dai},\n  year = {2020},\n  eprint = {2010.04159},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2010.04159}\n}\n","citationPath":"/content/papers/citations/object-detection/deformable-detr.df721a30472e.bib"},"thumbnail":{"src":"/content/papers/assets/36edfc5595a85c73fcdc9a4bbb9e1ca512e1f100676eb7c37203d71c84905c05.jpg","width":1224,"height":752},"locale":"zh-hans","path":"/content/papers/zh-hans/object-detection/deformable-detr.d2987152d10d.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"可变形注意力","text":"可变形注意力","depth":3},{"id":"多尺度计算","text":"多尺度计算","depth":3},{"id":"模型架构","text":"模型架构","depth":3},{"id":"程式码拆解","text":"程式码拆解","depth":3},{"id":"训练策略","text":"训练策略","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"与-detr-的比较","text":"与 DETR 的比较","depth":3},{"id":"消融实验","text":"消融实验","depth":3},{"id":"sota-比较","text":"SOTA 比较","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"object-detection/detr","relation":"background","topic":"集合预测与注意力检测器"},{"id":"object-detection/h-detr","relation":"next","topic":"集合预测与注意力检测器"},{"id":"object-detection/smca-detr","relation":"comparison","topic":"让 Transformer 检测器更快收敛"}]},{"id":"feature-fusion/panet","category":"feature-fusion","legacyPath":"feature-fusion/1803-panet","legacySlug":"1803-panet","legacyPaths":[],"title":"PANet","subtitle":"给我一条捷径","author":"Z. Yuan","paperDate":"2018-03-05","publishedOn":"2024-04-06","paperTitle":"Path Aggregation Network for Instance Segmentation","paperUrl":"https://arxiv.org/abs/1803.01534","bibliography":{"title":"Path Aggregation Network for Instance Segmentation","authors":["Shu Liu","Lu Qi","Haifang Qin","Jianping Shi","Jiaya Jia"],"url":"https://arxiv.org/abs/1803.01534","pdfUrl":"https://arxiv.org/pdf/1803.01534","codeUrl":null,"preprint":{"id":"1803.01534","submittedOn":"2018-03-05","url":"https://arxiv.org/abs/1803.01534"},"publication":{"venue":"CVPR","year":2018,"kind":"conference","url":"https://arxiv.org/abs/1803.01534"},"citation":"@misc{featurefusionpanet2018,\n  title = {{Path Aggregation Network for Instance Segmentation}},\n  author = {Shu Liu and Lu Qi and Haifang Qin and Jianping Shi and Jiaya Jia},\n  year = {2018},\n  eprint = {1803.01534},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1803.01534}\n}\n","citationPath":"/content/papers/citations/feature-fusion/panet.31d49af45ee9.bib"},"thumbnail":{"src":"/content/papers/assets/549012fa5498c4bbe44cfad4f4c54ed4eac5e7f0cdc71ae6308bb1ee6a4942ed.jpg","width":1024,"height":348},"locale":"zh-hans","path":"/content/papers/zh-hans/feature-fusion/panet.23f705df24df.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"panet-模型设计","text":"PANet 模型设计","depth":3},{"id":"路径聚合网络path-aggregation-fpn","text":"路径聚合网络（Path Aggregation FPN）","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"比起基本的-fpn-如何","text":"比起基本的 FPN 如何？","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"feature-fusion/fpn","relation":"background","topic":"检测用的多尺度特征融合"},{"id":"feature-fusion/bifpn","relation":"next","topic":"检测用的多尺度特征融合"}]}],"text":"2023 年 4 月，百度和北京大学的作者在 arXiv 上传了一篇论文，标题写着 DETRs Beat YOLOs，DETR 在实时目标检测上赢过 YOLO。\n\n他们提出的模型叫 RT-DETR（Real-Time DEtection TRansformer）。它读入一张 640×640 的照片，输出 300 个预测，每个预测是一个框、一个类别和一个分数；使用时用分数阈值筛掉低分的框就行，后面不必接 NMS。它要抢的是 YOLO 的活，像论文开头举的目标跟踪、视频监控和自动驾驶，一秒要处理几十张图像。这篇后来发表在 CVPR 2024。\n\n在当时，这个标题口气很大。本篇 Table 2 里最准的 DETR 是 DINO，ResNet-50 版本在 COCO 上有 50.9 AP，在 T4 GPU 上一秒却只跑得动 5 张（输入 800×1333）。YOLO 的大型模型在 COCO 上同样有 52、53 AP，一秒几十张起步。\n\n要说 DETR 赢，得先讲好 YOLO 的速度怎么测。YOLO 的输出要经过 NMS 才能用，NMS 的时间算不算、用什么阈值算，测出来的速度会差很多。这篇论文第一步先把 NMS 放回秒表里，再回头拆解 DETR 慢在哪里。\n\n## 定义问题\n\n### NMS 要花多少时间？\n\nYOLO 在特征图的每个位置都会猜框。以 640×640 的输入来说，YOLOv8 在步长 8、16、32 的三层特征图上，一共有 80×80＋40×40＋20×20＝8,400 个位置，每个位置一个框；YOLOv5 每个位置放 3 个 anchor，就是 25,200 个。同一个物体附近的好几个位置都会报出框，所以要靠 NMS（non-maximum suppression，非极大值抑制）清掉重复的框。\n\nNMS 有两个阈值。先用置信度阈值删掉分数太低的框；接着在每个类别里，留下分数最高的框，把和它 IoU 超过阈值的框删掉，再对剩下的框重复这件事。IoU 是两个框的交集面积除以并集面积。\n\n所以 NMS 要做多少事，要看有多少框通过置信度阈值。作者拿同一张输入，数了 YOLOv5 和 YOLOv8 在不同置信度阈值下还剩几个框。横轴是置信度阈值，纵轴是框数，蓝色是 anchor-based 的 YOLOv5，橙色是 anchor-free 的 YOLOv8：\n\n[![柱状图，横轴是置信度阈值 0.001、0.005、0.01、0.05、0.1、0.25，纵轴是剩下的框数，从 0 到 1 万。蓝色柱子是 YOLOv5，在 0.001 时约九千多个，随阈值升高逐步降到约六百个；橙色柱子是 YOLOv8，在 0.001 时约三千多个，降到约四百个。每个阈值下蓝色都比橙色高。](/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png)](/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png)\n\n*原论文 Figure 2，Zhao et al.，取自 [**v3 PDF 第 3 页**](https://arxiv.org/pdf/2304.08069v3#page=3)。同一张输入在不同置信度阈值下剩下的框数。*\n\n置信度阈值 0.001 时，YOLOv5 留下九千多个框，YOLOv8 三千多个；阈值拉到 0.25，两者都只剩几百个。每一个阈值下，YOLOv5 的框都比 YOLOv8 多。\n\n接着作者在 COCO val2017 上测 YOLOv8 的 AP 和 NMS 的执行时间。NMS 用 TensorRT 的 efficientNMSPlugin，在 T4 GPU、TensorRT FP16 上执行：\n\n| 置信度阈值 | IoU 阈值 | AP | NMS 时间（ms） |\n| ---: | ---: | ---: | ---: |\n| 0.001 | 0.5 | 52.1 | 2.24 |\n| 0.001 | 0.6 | 52.6 | 2.29 |\n| 0.001 | 0.7 | 52.9 | 2.36 |\n| 0.001 | 0.8 | 52.8 | 2.46 |\n| 0.01 | 0.7 | 52.4 | 1.73 |\n| 0.05 | 0.7 | 51.2 | 1.06 |\n\n*表：整理自原论文 Table 1。原表分成固定置信度阈值、固定 IoU 阈值两半，这里合成一张。表上没写 YOLOv8 的尺寸，52.9 AP 和 Table 2 的 YOLOv8-L 相同。*\n\n先看前四行。置信度阈值固定在 0.001，IoU 阈值从 0.5 拉到 0.8，NMS 时间从 2.24 增加到 2.46 ms。IoU 阈值越高，每一轮删掉的框越少，要跑的轮数就越多。AP 在 0.7 时最高。\n\n再看 IoU 阈值固定 0.7 的三行。置信度阈值从 0.001 拉到 0.05，NMS 时间从 2.36 降到 1.06 ms，少了一半多；AP 则从 52.9 掉到 51.2。\n\n最高的 52.9 AP 出现在置信度 0.001、IoU 0.7，这组设置的 NMS 时间在表上排第二长。YOLO 想拿到这个 AP，就得付这笔时间；想省时间，就得让出一点 AP。\n\n表上的时间还只算了一部分。efficientNMSPlugin 里有 EfficientNMSFilter、RadixSort、EfficientNMS 等好几个 kernel，Table 1 只列了 EfficientNMS 这一个。\n\n附录另外画了 YOLOv8-L 在几组阈值下的预测。置信度阈值太低，画面上冒出一堆多余的框；IoU 阈值设低，互相遮挡的物体会被当成重复框删掉，设高了，重叠的重复框又留下来。作者认为置信度阈值还算好调，IoU 阈值很难设得准。\n\n偏偏 YOLO 报告速度时，通常只测模型本身，不含 NMS（§3.1）。速度表上没有 NMS，AP 却是接上 NMS、用很低的置信度阈值算出来的。\n\n### 端到端的秒表\n\n作者于是定了一套端到端的测法（§3.2）：\n\n- 数据用 COCO val2017，逐张测、取平均，因为 NMS 的时间会随输入改变。\n- YOLO 后面接上 TensorRT 的 NMS 插件，阈值用各家拿到报告 AP 时的设置。官方测速脚本给 YOLOv8 的默认值是置信度 0.001、IoU 0.7、最多输出 300 个框。\n- 不计 I/O 与内存拷贝，在 T4 GPU、TensorRT FP16 上测。\n\n用这块秒表测下来，作者发现准确率相当时，anchor-free 的 YOLO 比 anchor-based 的快，因为后者输出的框比较多，NMS 要花更多时间。他们测的几款里，anchor-based 的框数是 anchor-free 的三倍，和前面算的 25,200 对 8,400 一致。\n\n### DETR 慢在哪里？\n\nDETR 这边没有 NMS，这段时间本来就省下了。它的麻烦在模型本身。\n\n\n> [!TIP]\n> \n> 如果你没读过 DETR，先补一点背景。DETR 用 Transformer 做目标检测，准备固定数量的查询（query），每个查询输出一个框和一个类别。训练时用匈牙利算法把预测和标注一对一匹配，同一个物体只有一个查询负责，推理时就用不着 NMS。后来的 Deformable DETR 把多尺度特征送进 encoder，注意力改成只看少数采样点，收敛快了很多。两篇可以参考我们的笔记：\n> \n> - **[[20.05] DETR：跨领域的奠基者](/blog/papers/object-detection/detr)**\n> - **[[20.10] Deformable DETR：可变形的注意力机制](/blog/papers/object-detection/deformable-detr)**\n\n\n多尺度特征让 DETR 收敛更快、也更准，代价是 encoder 要处理的序列一下子变长。可变形注意力虽然已经降低了计算量，encoder 还是成了计算瓶颈。作者引用 D²ETR 的分析，在 Deformable DETR 里，encoder 占了 49% 的 GFLOPs，对 AP 的贡献却只有 11%。\n\n那 encoder 要怎么砍？整个拿掉，准确率会掉多少？只留一部分的话，该留哪一部分？\n\n## 解决问题\n\n### 先看全貌\n\nRT-DETR 由骨干网络、混合 encoder 和 decoder 三段组成。骨干网络取最后三个 stage 的特征 $S_3$、$S_4$、$S_5$；混合 encoder 把它们整理成一串图像特征；查询选择从里面挑出固定数量的特征，当作查询的起点；decoder 再一层一层修正这些查询，输出类别和框。\n\n我们拿一张 640×640 的图像，把每一段的大小画出来：\n\n[![RT-DETR 的数据流示意图。640×640 的图像经过 ResNet 骨干网络，取出 S3、S4、S5 三层特征，大小分别是 80×80、40×40、20×20，对应 6,400、1,600、400 个位置。三层先用 1×1 卷积换成 256 个通道。只有 S5 进入 AIFI，展平成 400 个 token 做一层自注意力，输出 F5；S3 与 S4 不做自注意力，直接往下。三者一起进入 CCFF，用卷积先自顶向下、再自底向上融合相邻尺度，输出 80×80、40×40、20×20 三层，展平拼接成 8,400 个 256 维特征。查询选择按分数取前 300 个，特征当内容，预测框当起点。decoder 有 6 层，每层都接一组预测头；图中以一条红线示意推理停在第 4 层，后两层不算。最后输出 300 个框、类别与分数，用分数阈值筛选，不接 NMS。](/content/papers/assets/56fc846b508b33e0919ae9e2bee863288b2af1d139f1800196006d404b7b7004.png)](/content/papers/assets/56fc846b508b33e0919ae9e2bee863288b2af1d139f1800196006d404b7b7004.png)\n\n*图：本文整理。以 ResNet-50 骨干网络、640×640 输入为例；decoder 停在第 4 层只是举例。*\n\n接下来沿着这张图，从 encoder 一路走到 decoder。\n\n### Encoder 的账\n\n先算一下三层特征各有多少个位置。展平之后，每个位置就是一个 token：\n\n```python\nH = W = 640\nstrides = {\"S3\": 8, \"S4\": 16, \"S5\": 32}\ntokens = {k: (H // s) * (W // s) for k, s in strides.items()}\ntotal = sum(tokens.values())\n\nfor k, n in tokens.items():\n    side = H // strides[k]\n    print(f\"{k}: {side}×{side} = {n} 个 token，占 {n / total:.0%}，两两配对 {n * n / 1e6:.2f}M 对\")\nprint(\"三层合计\", total, \"个 token\")\n\npairs_each = sum(n * n for n in tokens.values())\npairs_s5 = tokens[\"S5\"] ** 2\nprint(f\"三层各自做自注意力：{pairs_each / 1e6:.2f}M 对；只做 S5：{pairs_s5 / 1e6:.2f}M 对，相差 {pairs_each / pairs_s5:.0f} 倍\")\n```\n\n```text\nS3: 80×80 = 6400 个 token，占 76%，两两配对 40.96M 对\nS4: 40×40 = 1600 个 token，占 19%，两两配对 2.56M 对\nS5: 20×20 = 400 个 token，占 5%，两两配对 0.16M 对\n三层合计 8400 个 token\n三层各自做自注意力：43.68M 对；只做 S5：0.16M 对，相差 273 倍\n```\n\nS3 一层就占了 76% 的 token。一般的自注意力要让每个 token 和同一层的所有 token 配对，S3 一层就有四千多万对；只做 S5 的话，16 万对就够了。\n\n作者用一组 encoder 变体检验这笔账。图中从左到右是 A 到 E 五种 encoder，每一格底下的三根箭头代表三层特征；SSE 是单尺度 Transformer encoder，MSE 是多尺度 Transformer encoder，CSF 是跨尺度融合：\n\n[![五个并排的方块，代表 encoder 的五种变体。A 只有 Concat；B 是 SSE 再接 Concat；C 是 Concat 再接 MSE；D 是 SSE 再接 CSF；E 是 AIFI 再接 CCFF。底下的箭头标示 A 到 B 加入层内交互，B 到 C 加入跨尺度交互，C 到 D 把两者拆开，D 到 E 是加强版。](/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png)](/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png)\n\n*原论文 Figure 3，Zhao et al.，取自 [**v3 PDF 第 4 页**](https://arxiv.org/pdf/2304.08069v3#page=4)。五种 encoder 变体的结构。*\n\n每一种变体都以 DINO-Deformable-R50 为基础，换上 RT-DETR 较轻的数据读取与 decoder，训练 12 个 epoch。表上多了一行 $\\mathrm{D}_{S_5}$，它和 D 的结构相同，只是 SSE 只处理 S5：\n\n| 变体 | encoder 的做法 | AP | 参数（M） | 延迟（ms） |\n| --- | --- | ---: | ---: | ---: |\n| A | 去掉 encoder，三层直接拼接 | 43.0 | 31 | 7.2 |\n| B | 三层共用一层单尺度 Transformer，各自做层内交互，再拼接 | 44.9 | 32 | 11.1 |\n| C | 把 B 的结果拼接，送进多尺度 Transformer encoder | 45.6 | 32 | 13.3 |\n| D | 层内交互交给单尺度 Transformer，跨层融合交给 PANet 式的结构 | 46.4 | 35 | 12.2 |\n| $\\mathrm{D}_{S_5}$ | 同 D，但只有 S5 做层内交互 | 46.8 | 35 | 7.9 |\n| E | AIFI＋CCFF，也就是 RT-DETR 的做法 | 47.9 | 42 | 9.3 |\n\n*表：原论文 Table 3；「encoder 的做法」一列整理自 §4.2。*\n\n一行一行往下看：\n\n1. **A → B**：AP 多 1.9，延迟多 54%。层内交互有用，但每一层都做自注意力很贵。\n2. **B → C**：AP 再多 0.7，延迟再多 20%。跨尺度的交互也有用，多尺度 encoder 却更贵。\n3. **C → D**：把层内交互和跨层融合拆开，AP 多 0.8，延迟反而少 8%。\n4. **D → $\\mathrm{D}_{S_5}$**：只留 S5 的自注意力，延迟从 12.2 降到 7.9 ms，少了 35%，AP 还多 0.4。\n5. **D → E**：换成 AIFI 和 CCFF，AP 多 1.5，参数多 20%，延迟少 24%。\n\n第 4 步把 S3、S4 的自注意力拿掉，也就是刚才算出来的四千多万对配对，延迟少了 4.3 ms。最后的 E 和完全没有 encoder 的 A 相比，延迟只多 2.1 ms，AP 高了 4.9。\n\n为什么只留 S5？作者认为，高层特征带着物体的语义，在这一层做自注意力，可以抓到画面里不同物体、概念之间的关系，帮助后面的模块定位和识别；低层特征缺乏语义，在里面做层内交互是多余的，还可能和高层的交互重复、混淆。$\\mathrm{D}_{S_5}$ 那一行支持这个说法，少算了那么多，AP 还高了 0.4。\n\n### AIFI：只在 S5 做自注意力\n\n论文把混合 encoder 写成三行：\n\n$$\n\\begin{aligned}\n\\mathcal{Q} = \\mathcal{K} = \\mathcal{V} &= \\mathrm{Flatten}(S_5) \\\\\nF_5 &= \\mathrm{Reshape}(\\mathrm{AIFI}(\\mathcal{Q}, \\mathcal{K}, \\mathcal{V})) \\\\\n\\mathcal{O} &= \\mathrm{CCFF}(\\{S_3, S_4, F_5\\})\n\\end{aligned}\n$$\n\nAIFI 就是一层标准的 Transformer encoder。把 S5 展平成序列，Q、K、V 都来自它，做完自注意力和前馈网络，再折回 20×20 的形状。我们让同一张图像接着走下去，骨干网络的输出先用随机数代替：\n\n```python\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\ntorch.manual_seed(0)\n# ResNet-50 最后三个 stage 的输出，这里用随机数代替\nS3 = torch.randn(1, 512, 80, 80)\nS4 = torch.randn(1, 1024, 40, 40)\nS5 = torch.randn(1, 2048, 20, 20)\n\n# 先用 1×1 卷积把三层都换成 256 个通道\nproj = nn.ModuleList(nn.Conv2d(c, 256, 1) for c in (512, 1024, 2048))\nS3, S4, S5 = (p(x) for p, x in zip(proj, (S3, S4, S5)))\n\n# AIFI：只把 S5 展平成序列，过一层 Transformer encoder\naifi = nn.TransformerEncoderLayer(d_model=256, nhead=8, dim_feedforward=1024, batch_first=True)\nseq = S5.flatten(2).transpose(1, 2)\nF5 = aifi(seq).transpose(1, 2).reshape(1, 256, 20, 20)\nprint(\"AIFI 输入\", tuple(seq.shape), \"→ F5\", tuple(F5.shape))\n```\n\n```text\nAIFI 输入 (1, 400, 256) → F5 (1, 256, 20, 20)\n```\n\n这里的大小依照附录 Table A，嵌入维度 256、8 个头、前馈层 1024，只有一层。官方代码在 Q、K 上还加了 2D 的 sin-cos 位置编码，示例里省略了。\n\n### CCFF：跨尺度的融合交给卷积\n\nCCFF 沿用 PANet 的路线，先自顶向下、再自底向上，每一步把相邻两层的特征融合成新的一层。融合块（Figure 5）把相邻两层的特征拼接，分成两路各过一个 1×1 卷积；其中一路再接 N 个 RepBlock，最后两路逐点相加，RT-DETR 用 N＝3。\n\nRepBlock 由 RepConv 组成，也就是 RepVGG 那种训练时多分支、推理时合并成单一 3×3 卷积的设计。下面的示例用普通的 3×3 卷积代替，也省略了 BN、SiLU，以及官方代码在放大之前多做的一次 1×1 卷积：\n\n```python\nclass Fusion(nn.Module):\n    \"\"\"Figure 5 的融合块：两路 1×1 卷积，其中一路再接 N 个卷积块，最后逐点相加\"\"\"\n    def __init__(self, n=3):\n        super().__init__()\n        self.a = nn.Conv2d(512, 256, 1)\n        self.b = nn.Conv2d(512, 256, 1)\n        self.blocks = nn.Sequential(*[nn.Conv2d(256, 256, 3, padding=1) for _ in range(n)])\n\n    def forward(self, x, y):\n        z = torch.cat([x, y], dim=1)            # 两个相邻尺度，通道 256 + 256\n        return self.a(z) + self.blocks(self.b(z))\n\nup = lambda x: F.interpolate(x, scale_factor=2, mode=\"nearest\")\ndown = nn.ModuleList(nn.Conv2d(256, 256, 3, stride=2, padding=1) for _ in range(2))\nfuse = nn.ModuleList(Fusion() for _ in range(4))\n\n# 自顶向下：F5 放大两倍和 S4 融合，再放大和 S3 融合\nT4 = fuse[0](up(F5), S4)\nT3 = fuse[1](up(T4), S3)\n# 自底向上：再缩小回去，依次和 T4、F5 融合\nB4 = fuse[2](down[0](T3), T4)\nB5 = fuse[3](down[1](B4), F5)\nfor name, x in [(\"T3\", T3), (\"B4\", B4), (\"B5\", B5)]:\n    print(name, tuple(x.shape))\n\nmemory = torch.cat([x.flatten(2) for x in (T3, B4, B5)], dim=2).transpose(1, 2)\nprint(\"编码器输出\", tuple(memory.shape))\n```\n\n```text\nT3 (1, 256, 80, 80)\nB4 (1, 256, 40, 40)\nB5 (1, 256, 20, 20)\n编码器输出 (1, 8400, 256)\n```\n\nT3、B4、B5 是示例里取的名字，论文没有给中间结果命名。输出还是三层，大小和输入一样，通道都是 256；展平拼接之后，就是一串 8,400 个特征。\n\n这个数字和前面 YOLOv8 的 8,400 个框一样，因为两者都在步长 8、16、32 的三层网格上预测。接下来两者就分道扬镳了。YOLO 把每个位置的框全部交给 NMS，RT-DETR 只从里面挑 300 个交给 decoder。\n\n\n> [!TIP]\n> \n> CCFF 的两条路径和 RepBlock 各有来历，可以参考我们的笔记：\n> \n> - **[[18.03] PANet：给我一条捷径](/blog/papers/feature-fusion/panet)**\n> - **[[21.01] RepVGG：让 VGG 再次伟大](/blog/papers/reparameterization/repvgg)**\n\n\n### 挑出 300 个查询\n\nDETR 原本的查询是一组可学习的向量，和输入图像无关，很难优化。后来的做法改从 encoder 的输出里挑。Deformable DETR 的两阶段版本和 DINO，都按分类分数挑出前 K 个特征来初始化查询（DINO 只拿它们当位置查询）。RT-DETR 取 K＝300，挑中的特征当内容查询，它们预测的框当位置查询的起点。\n\n接着上面的例子：\n\n```python\nscore_head = nn.Linear(256, 80)    # COCO 的 80 个类别\nbox_head = nn.Linear(256, 4)\n\nlogits = score_head(memory)                       # 每个位置对 80 类的分数\ntop_score, top_idx = logits.max(-1).values.topk(300, dim=1)\nidx = top_idx[..., None]\ncontent = memory.gather(1, idx.expand(-1, -1, 256))           # 内容查询\ninit_box = box_head(memory).sigmoid().gather(1, idx.expand(-1, -1, 4))  # 初始框\nprint(\"分数\", tuple(logits.shape), \"→ 选出\", tuple(content.shape), \"与\", tuple(init_box.shape))\n```\n\n```text\n分数 (1, 8400, 80) → 选出 (1, 300, 256) 与 (1, 300, 4)\n```\n\n示例里的两个预测头都是随机权重。官方代码在预测头前面还有一层线性变换和 LayerNorm，框的预测也会加上每个位置的 anchor；挑选本身就是一个 topk。\n\n问题出在挑选的依据。分类分数高，表示这个位置像有物体，却不保证它预测的框准。检测器要同时分对类别、框对位置，只看分类分数，定位不准的特征也可能被选进来，decoder 就得从一个不好的起点开始修。\n\n作者把这种落差称为不确定性，定义成定位与分类两个预测分布之间的差距，再把它放进分类损失里一起最小化：\n\n$$\n\\mathcal{U}(\\hat{\\mathcal{X}}) = \\lVert \\mathcal{P}(\\hat{\\mathcal{X}}) - \\mathcal{C}(\\hat{\\mathcal{X}}) \\rVert, \\quad \\hat{\\mathcal{X}} \\in \\mathbb{R}^D\n$$\n\n$$\n\\mathcal{L}(\\hat{\\mathcal{X}}, \\hat{\\mathcal{Y}}, \\mathcal{Y}) = \\mathcal{L}_{box}(\\hat{\\mathbf{b}}, \\mathbf{b}) + \\mathcal{L}_{cls}(\\mathcal{U}(\\hat{\\mathcal{X}}), \\hat{\\mathbf{c}}, \\mathbf{c})\n$$\n\n其中 $\\hat{\\mathcal{X}}$ 是 encoder 的特征，$\\hat{\\mathbf{c}}$、$\\hat{\\mathbf{b}}$ 是预测的类别与框，$\\mathbf{c}$、$\\mathbf{b}$ 是标注。\n\n公式写得很抽象，官方代码的做法具体得多。它用 Varifocal loss 训练分类分数。一个预测若在匈牙利匹配中匹配到标注，它在该类别的训练目标从 1 改成它的框和标注框的 IoU；没匹配到的，目标是 0。举三个被选中的特征为例：\n\n| 特征 | 匹配到的标注 | 预测框和标注的 IoU | 一般的分类目标 | RT-DETR 的分类目标 |\n| --- | --- | ---: | ---: | ---: |\n| 甲 | 狗 | 0.45 | 1 | 0.45 |\n| 乙 | 猫 | 0.90 | 1 | 0.90 |\n| 丙 | 没匹配到 | — | 0 | 0 |\n\n*表：本文举例。*\n\n甲的框和狗只重叠 0.45，它的分类分数就被往 0.45 拉，不会像以前一样被推向 1。分类分数被训练成反映框的质量，按分数挑出来的前 300 个，就会偏向框也准的特征。这个损失同时用在 encoder 选出的 300 个预测，以及 decoder 每一层的输出上。\n\n\n> [!TIP]\n> \n> 如果你到官方代码里找 uncertainty-minimal 这个名字，会找不到。2024 年 8 月就有人在 GitHub 上问过，另一位用户指出它写在损失函数 `loss_labels_vfl` 里（[RT-DETR #438](https://github.com/lyuwenyu/RT-DETR/issues/438)）。论文 v1 把这个设计叫 IoU-aware query selection，这个名字比较接近代码的写法。\n\n\n效果怎么样？作者在 COCO val2017 上，把两种选法挑出来的特征画成散点图。横轴是框和标注的 IoU，纵轴是分类分数，只画分类分数超过 0.5 的点；紫色是新的选法，绿色是原本按分类分数的选法，上方和右侧的曲线是点的密度：\n\n[![散点图，横轴 IoU score 从 0 到 1，纵轴 Classification score 从 0.5 到 1。紫色点是 Uncertainty-minimal，大量集中在右上角，IoU 约 0.6 到 0.9、分类分数 0.7 以上；绿色点是 Vanilla，数量较少，集中在右下角，分类分数多在 0.5 到 0.65 之间。上方与右侧的密度曲线，紫色都明显高于绿色。](/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png)](/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png)\n\n*原论文 Figure 6，Zhao et al.，取自 [**v3 PDF 第 6 页**](https://arxiv.org/pdf/2304.08069v3#page=6)。两种查询选择挑出的 encoder 特征，其分类分数与 IoU。*\n\n越靠右上角的点，类别和框都越可能是对的。紫点大量集中在右上角；绿点集中在右下角，框不差，分类分数却偏低，数量也少得多。Table 4 把它量化成比例（RT-DETR-R50，训练 12 个 epoch）：\n\n| 查询选择 | AP | 分类分数 > 0.5 的比例 | 两项都 > 0.5 的比例 |\n| --- | ---: | ---: | ---: |\n| 按分类分数（原本） | 47.9 | 0.35% | 0.30% |\n| uncertainty-minimal | 48.7 | 0.82% | 0.67% |\n\n*表：原论文 Table 4。*\n\n两个比例都提高到两倍以上，AP 多了 0.8。\n\n### Decoder：去掉后面几层\n\nRT-DETR 的 decoder 几乎照搬 DINO，6 层、300 个查询，cross-attention 用可变形注意力，采样点数设为 4。训练时也带着 DINO 的去噪练习，附录 Table A 列的去噪数量是 200。\n\n\n> [!TIP]\n> \n> 去噪练习是把加了噪声的标注框当成额外的查询喂给 decoder，要模型还原成原本的框，推理时整个拿掉。官方配置文件写的是 `num_denoising: 100`；代码会把每组做成正、负两份，实际送进 decoder 的去噪查询在 200 个上下，随同一批里标注最多的那张图变动。这套做法的来历可以参考：\n> \n> - **[[22.03] DN-DETR：今天配狗，明天配猫](/blog/papers/object-detection/dn-detr)**\n> - **[[22.03] DINO：靠近，但不够近](/blog/papers/object-detection/dino-detr)**\n\n\ndecoder 的每一层后面都接着自己的预测头，训练时每一层的输出都拿去算损失。所以每一层都会吐出一组完整、可以直接用的预测。官方代码在推理时用 `eval_idx` 指定要用哪一层的输出，循环跑到那一层就停，后面的层不会执行。\n\n作者把 decoder 分别训练成 4 到 7 层，再看推理时停在每一层的结果（RT-DETR-R50，训练 72 个 epoch）：\n\n| 推理用到第几层 | Det4 | Det5 | Det6 | Det7 | 延迟（ms） |\n| ---: | ---: | ---: | ---: | ---: | ---: |\n| 7 | | | | 52.6 | 9.6 |\n| 6 | | | 53.1 | 52.6 | 9.3 |\n| 5 | | 52.9 | 53.0 | 52.5 | 8.8 |\n| 4 | 52.7 | 52.7 | 52.7 | 52.1 | 8.3 |\n| 3 | 52.4 | 52.3 | 52.4 | 51.5 | 7.9 |\n| 2 | 51.6 | 51.3 | 51.3 | 50.6 | 7.5 |\n| 1 | 49.6 | 48.8 | 49.1 | 48.3 | 7.0 |\n\n*表：原论文 Table 5。Det k 表示训练时用 k 层 decoder，格子里是 AP；延迟一列只看推理用了几层。*\n\n先看 Det6 这一列。从 6 层退到 5 层，AP 只少 0.1，延迟少 0.5 ms；退到 4 层，AP 是 52.7，延迟 8.3 ms。每多算一层大约多 0.4 到 0.5 ms，越后面的层对 AP 的帮助越小。\n\n再横着比。Det6 停在第 4 层是 52.7，和直接训练 4 层的 Det4 一样；停在第 5 层是 53.0，比直接训练 5 层的 Det5 还高 0.1。在这张表上，训练一个 6 层的模型再截短，和另外训练一个浅的模型差不多。至于 7 层，最好也只有 52.6，比 6 层差。\n\n调整范围有多大？只用第 1 层是 7.0 ms，用满 6 层是 9.3 ms。作者在 GitHub 上回答用户时提过，现在的 RT-DETR 各段相对均衡，时间主要花在骨干网络和 decoder（[RT-DETR #266，2024-04](https://github.com/lyuwenyu/RT-DETR/issues/266)）。decoder 的层数又不必重训就能调，等于多了一个速度旋钮。\n\n官方发布的模型就是这样用的。附录 Table B 的缩小版 RT-DETR-R50 把 RepBlock 的通道减半，同一个模型停在第 2 到第 6 层，可以从 50.3 AP、154 FPS 一路调到 52.2 AP、125 FPS；同表的 YOLOv8-M 是 50.2 AP、97 FPS。官方代码库里的 RT-DETR-R50-m（51.3 AP、145 FPS），配置文件写着 `eval_idx: 2`，用的是第 3 层的输出。\n\n## 讨论\n\n### 和 YOLO、DINO 比\n\nTable 2 把 RT-DETR 和 YOLO 的 L、X 尺寸放在一起比。数据是 COCO val2017；RT-DETR 和 YOLO 都用 640×640 输入，其他 DETR 用 800×1333；FPS 在 T4、TensorRT FP16、批大小 1 下测，YOLO 用官方权重，按前面的端到端测法接上 NMS：\n\n| 模型 | 参数（M） | GFLOPs | FPS | AP | AP<sub>S</sub> |\n| --- | ---: | ---: | ---: | ---: | ---: |\n| YOLOv6-L | 59 | 150 | 99 | 52.8 | 34.4 |\n| YOLOv7-X | 71 | 189 | 45 | 52.9 | 36.9 |\n| YOLOv8-L | 43 | 165 | 71 | 52.9 | 35.3 |\n| YOLOv8-X | 68 | 257 | 50 | 53.9 | 35.7 |\n| DINO-Deformable-DETR-R50 | 47 | 279 | 5 | 50.9 | 34.6 |\n| RT-DETR-R50 | 42 | 136 | 108 | 53.1 | 34.8 |\n| RT-DETR-R101 | 76 | 259 | 74 | 54.3 | 36.0 |\n\n*表：原论文 Table 2 节选。AP<sub>S</sub> 是小目标的 AP。*\n\n挑几组来看：\n\n- **RT-DETR-R50 对 YOLOv8-L**：AP 53.1 对 52.9，只高 0.2；速度 108 对 71 FPS，换成每张的时间是 9.3 对 14.1 ms。GFLOPs 也少一些，136 对 165。\n- **RT-DETR-R101 对 YOLOv8-X**：AP 高 0.4，速度 74 对 50 FPS。\n- **RT-DETR-R50 对 YOLOv6-L**：AP 只高 0.3，速度 108 对 99 FPS，差距小很多。\n\n小目标是 RT-DETR 输的地方。RT-DETR-R50 的 AP<sub>S</sub> 是 34.8，比 YOLOv8-L 的 35.3 低 0.5；R101 的 36.0 比 YOLOv7-X 的 36.9 低 0.9。作者把这点写进局限性，说这是 DETR 共同的弱点。\n\n训练条件也不一样。RT-DETR 的骨干网络先在 ImageNet 上预训练，再在 COCO 上训练 72 个 epoch。官方代码加载的 R50 权重，是 PaddleClas 用知识蒸馏训练的 ResNet50-vd（`ssld_v2`），[PaddleClas 的模型表](https://paddleclas-doc.readthedocs.io/zh/latest/models/ResNet_and_vd_en.html)上 ImageNet top-1 是 83.0%，原版 ResNet-50 是 76.5%。表上的 YOLOv7、YOLOv8 则是从头训练，YOLOv10 的论文附录就写明它比照 YOLOv8、YOLOv7、YOLOv9 从头训练。这张表比的是整套系统，骨干网络的权重和训练配方都算在里面。\n\n如果再拿 Objects365 预训练、COCO 微调，R18、R50、R101 分别达到 49.2、55.3、56.2 AP，比只用 COCO 高 2.7、2.2、1.9（附录 Table C）。\n\n和 DINO 比，RT-DETR-R50 的 AP 高 2.2，速度是 108 对 5 FPS，约 21 倍。这也是整套系统的比较。DINO 的输入是 800×1333，像素是 640×640 的 2.6 倍，训练 36 个 epoch，RT-DETR 训练 72 个 epoch。混合 encoder 自己省下多少，要回去看 Table 3 的同条件对照。\n\n2024 年 6 月，有用户在 GitHub 上对这组比较提出质疑（[RT-DETR #349](https://github.com/lyuwenyu/RT-DETR/issues/349)）。他在 RTX 3090 上测，RT-DETR 的 FLOPs 约是 DINO 的一半，和论文一致，速度却只快两倍左右；他也指出两者的数据增强和骨干网络不同。作者回复，DINO 的速度要在它达到论文精度的条件下测，他们在 V100、T4、3090 上都测过，结果符合预期；不同模型之间，比最终的精度和速度才公平。来回几次之后，双方各自维持原本的立场。\n\n### 阈值要怎么设？\n\n2023 年 10 月，有用户在 GitHub 上问了一个很实际的问题（[RT-DETR #77](https://github.com/lyuwenyu/RT-DETR/issues/77)）。端到端测法用的是验证时的阈值，置信度 0.001、IoU 0.7；可是实际上线时，一般会用 0.1 左右的置信度阈值先滤掉大部分背景框，NMS 会快很多，RT-DETR 的速度优势就没那么大了。\n\n作者回复，用 0.1 的阈值，YOLO 的 mAP 就到不了报告上的数字。精度用 0.001 测、速度用 0.1 测，模型不可能同时处在这两种状态；RT-DETR 的分数阈值只是筛选输出，部署时的速度和评测时一样。\n\n两边说的都有根据。Table 1 正好给了中间的数字，置信度阈值从 0.001 拉到 0.05，EfficientNMS 的时间少 1.3 ms，AP 少 1.7。另一方面，RT-DETR 的 53.1 也是把每张图的 300 个输出全部交给评测程序算出来的；部署时套上分数阈值，AP 也只会持平或下降，差别在它的速度不跟着变。\n\n读这两张表时还要记得，Table 2 的 YOLO 时间包含整个 NMS 插件，Table 1 只列其中一个 kernel，两张表的时间不能直接相减。\n\n\n> [!TIP]\n> \n> 一年后的 YOLOv10 测延迟时，就沿用了 RT-DETR 这套端到端测法，同时让 YOLO 自己也去掉 NMS：\n> \n> - **[[24.05] YOLOv10：NMS，再见](/blog/papers/object-detection/yolov10)**\n\n\n### 换一台机器\n\n2024 年 2 月，另一位用户用 trtexec 在三张显卡上比较 RT-DETR-R18 和接上 NMS 的 YOLOv8s（[RT-DETR #214](https://github.com/lyuwenyu/RT-DETR/issues/214)）。RTX 4090 上是 1.065 对 1.90 ms，比例和论文相符；T4 上却是 5.6 对 5.4 ms，YOLOv8s 反而快一点；笔记本的 RTX 3050 上，RT-DETR 慢了将近 2 ms。\n\n作者回复，论文的 YOLO 速度是 val2017 上 5,000 张图的平均，因为 NMS 的时间随通过分数阈值的框数而变；另外 RT-DETR 用到的算子种类比 YOLOv8 多，不同版本的 TensorRT 支持程度不一样。这个讨论帖没有结论。端到端的速度和硬件、软件版本、数据都有关系，要用在自己的场景，还是得在自己的机器上测一次。\n\n### 偶尔还是有重复框\n\nRT-DETR 去掉了 NMS，重复框却没有完全消失。2024 年 7 月，有用户反馈同一个物体偶尔出现好几个框，其他人也遇到过几乎完全重叠、类别不同甚至类别相同的框（[RT-DETR #379](https://github.com/lyuwenyu/RT-DETR/issues/379)）。作者建议仔细挑分数阈值。另一位用户说，这些重复框的分数常常非常接近，阈值分不开；自己再接 NMS 可以解决，但要多花时间，模型训练得好时，这种情况比较少。\n\n\n> [!NOTE]\n> \n> 如果你用的是 Ultralytics 包里的 `rtdetr-l`、`rtdetr-x`，它们是官方代码库列出的 HGNetv2 骨干版本，分别是 53.0 AP、114 FPS 和 54.8 AP、74 FPS，也就是论文 v1 主打的两个模型。这篇 v3 改以 ResNet 骨干的 R50、R101 为主。\n\n\n## 结论\n\nRT-DETR 这篇做了两件事。一是把 YOLO 的速度连同 NMS 一起测，而且用拿到报告 AP 的那组阈值测；二是把 DETR 拆开，看时间花在哪里、哪里可以省。能带走的大概有这几点：\n\n1. **NMS 的时间跟着阈值走**。T4 上的 YOLOv8，置信度阈值从 0.001 拉到 0.05，EfficientNMS 的时间从 2.36 降到 1.06 ms，AP 从 52.9 掉到 51.2。\n2. **自注意力只留在 S5**。去掉 S3、S4 的层内交互，延迟少 35%，AP 没掉；换上 AIFI 和 CCFF 后，比多尺度 Transformer encoder 的变体 C 高 2.3 AP，延迟少 30%。\n3. **让分类分数反映框的质量**。查询选择改用 IoU 当分类目标，12 个 epoch 的设置下 AP 多 0.8。\n4. **decoder 可以截短**。每层约 0.5 ms，6 层的模型停在第 4 层，和直接训练 4 层的一样准。\n\n下次读实时检测器的速度表，可以先看 NMS 有没有算进去、用的是哪组阈值，再看是哪张卡、哪个 TensorRT 版本。RT-DETR 的速度不随阈值变动，但小目标的 AP 和骨干网络的预训练，也要一起放进比较里。\n\n这套端到端测法后来被 YOLOv10 沿用，RT-DETR 本身也成了后续实时 DETR 的起点。2024 年底的 [DEIM](/blog/papers/object-detection/deim) 在 RT-DETRv2 和 D-FINE 上改了训练方式，让这类模型学得更快。\n","imageSizes":{"/content/papers/assets/3ce51df5cdcf3f7995e63085f9c6925d29364b00decdae24bb9a6f2b628bacb1.png":{"width":664,"height":508},"/content/papers/assets/56fc846b508b33e0919ae9e2bee863288b2af1d139f1800196006d404b7b7004.png":{"width":800,"height":2044},"/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png":{"width":1360,"height":332},"/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png":{"width":632,"height":620}}}
