{"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-hant","path":"/content/papers/zh-hant/object-detection/rt-detr.39c167c6afdb.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-hant","path":"/content/papers/zh-hant/object-detection/detr.5ef9bf1965a5.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-hant","path":"/content/papers/zh-hant/object-detection/deformable-detr.4eb78eef1d58.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-hant","path":"/content/papers/zh-hant/feature-fusion/panet.1018531c3256.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/828554a2ddb1d9726bfa7250087eda82ce289933afeb37c771d3b3dbe63315b0.png)](/content/papers/assets/828554a2ddb1d9726bfa7250087eda82ce289933afeb37c771d3b3dbe63315b0.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/828554a2ddb1d9726bfa7250087eda82ce289933afeb37c771d3b3dbe63315b0.png":{"width":800,"height":2044},"/content/papers/assets/7e2de3c38daff439f51d86ec04a7bd391c3f708b817ae539f3c4df7c5546f4d6.png":{"width":1360,"height":332},"/content/papers/assets/420e753b3717e561d473e69a1066095c23584488dab765ae7acee273b91819f8.png":{"width":632,"height":620}}}
