YOLO 之外的另一半:RF-DETR 检测实战

介绍:认识 RF-DETR

    • [0.1 它是什么](#0.1 它是什么)
    • [0.2 YOLO 用户为什么要多看它一眼](#0.2 YOLO 用户为什么要多看它一眼)
    • [0.3 环境与素材(本机实测口径)](#0.3 环境与素材(本机实测口径))
  • [第一章 关键点推理:从检测框到人体骨骼](#第一章 关键点推理:从检测框到人体骨骼)
    • [1.1 Keypoint Preview:一个模型,17 个关节](#1.1 Keypoint Preview:一个模型,17 个关节)
    • [1.2 单图推理与 KeyPoints 输出结构](#1.2 单图推理与 KeyPoints 输出结构)
    • [1.3 四个骨骼标注器(两个是新的)](#1.3 四个骨骼标注器(两个是新的))
    • [1.4 视频 / 摄像头 / RTSP 帧循环](#1.4 视频 / 摄像头 / RTSP 帧循环)
    • [1.5 与姊妹篇 yolo11n-pose 的路线对照](#1.5 与姊妹篇 yolo11n-pose 的路线对照)
    • [1.6 实测:RTX 5060 上的关键点推理](#1.6 实测:RTX 5060 上的关键点推理)
    • [1.7 本章方法速查](#1.7 本章方法速查)
  • [第二章 微调:训练自己的模型](#第二章 微调:训练自己的模型)
    • [2.1 训练前置:extra 与数据格式](#2.1 训练前置:extra 与数据格式)
    • [2.2 `model.train()`:一行微调](#2.2 model.train():一行微调)
    • [2.3 训练产物:五种 checkpoint 的分工](#2.3 训练产物:五种 checkpoint 的分工)
    • [2.4 `model.evaluate()`:一次评测,三种返回](#2.4 model.evaluate():一次评测,三种返回)
    • [2.5 实验一:迷你数据集烟测(全程离线)](#2.5 实验一:迷你数据集烟测(全程离线))
    • [2.6 实验二:关键点微调烟测(伪标注骨骼)](#2.6 实验二:关键点微调烟测(伪标注骨骼))
    • [2.7 本章方法速查](#2.7 本章方法速查)
    • [2.8 导出部署速览](#2.8 导出部署速览)

本教程是《OpenCV 之外的另一半工具箱:Supervision 视觉工程实战》的姊妹篇。讲"检测结果从哪来"------认识并驾驭一个比 YOLO 更适合微调的检测器:RF-DETR。

0.1 它是什么

RF-DETR 是 Roboflow 2025 年开源的实时目标检测器,名字里的 RF 是 Roboflow,DETR 是 Detection Transformer------也就是检测领域的 Transformer 架构家族。它用 DINOv2 预训练骨干网络 + DETR 式解码器的设计,主打一个卖点:微调之后的精度-速度平衡。官方在 COCO 预训练模型的对比图里,它坐在"精度-延迟"帕累托曲线的前沿;而真正拉开差距的是微调场景------用自有数据集微调后,同量级模型的精度对比里 RF-DETR 常年领先 YOLO 系一个身位,这也是它敢在文档标题里写 "state-of-the-art fine-tuning" 的底气。

模型规格分档清晰:Nano / Small / Medium / Large 四档为主力(另有 Seg 分割、Keypoint 关键点变体),从边缘设备到服务器都能找到对应的档位;预训练权重基于 COCO 80 类,加载即用。几个常被引用的官方基准数字:检测档 COCO AP50:95 从 Nano 48.4 到 2XLarge 60.1(作为对照,YOLOv11-X 只有 50.9,而 RF-DETR-L 的 56.5 还比它快三分之一);本教程用到的两个数------关键点 Preview 71.8 AP、Nano 2.3 ms------分别见第一章与 2.8。

读官方基准数字前先看口径 ,三条值得学走的规矩(官方 benchmarks 页自己交代的方法论,比数字本身更值钱):① 延迟全部测自 T4 + TensorRT 10.4 + FP16 + batch 1 ,且两次前向间垫 200 ms 防降频------换硬件、换精度、换批量,数字都不能直接套;② 精度和延迟用同一份权重、同一精度测 ------拿 FP32 的精度配 FP16 的延迟对比竞品是行业惯用障眼法,朴素 FP16 转换可能明显掉精度;③ 全部模型(含竞品)用 pycocotools 在同一协议下重测 而非照抄厂商报告,官方页上与厂商数字有出入属正常。另外检测表里还有一组 RF100-VL 列(100 个跨领域数据集的平均精度):RF-DETR 全档位领先 YOLO 系 2--5 个点,衡量的是换域泛化------预训练模型直接拿到陌生领域还有多少底子,对工业场景选型很有参考价值。

协议是 Apache-2.0,免费商用------这一点与 ultralytics 的 AGPL-3.0 形成直接对照,也是很多团队认真评估它的第一原因。

0.2 YOLO 用户为什么要多看它一眼

如果你已经用过 YOLO,RF-DETR 值得纳入武器库的理由有四个:

  1. 协议干净。Apache-2.0 没有强Copyleft约束,商用、闭源、二次分发都不需要像使用 AGPL 的 ultralytics 那样反复确认边界。整套教程的合规组合(supervision MIT + RF-DETR Apache-2.0)在姊妹篇里论证过,这里直接继承。
  2. 微调是它的主场。DETR 系架构 + DINOv2 大规模预训练骨干,让它在小数据集微调时收敛快、上限高------"只有几百张标注图也要训自己的检测器"正是工业落地的常态,这个场景下它的优势最明显。
  3. 端到端的另一种范式。YOLO 是"锚框/无锚框 + NMS 后处理"的 CNN 路线,DETR 系是"集合预测"的 Transformer 路线。两条路线的踩坑点完全不同(后者没有 NMS 调参的烦恼,但对数据量、学习率更敏感),多会一种,选型时才不会被单一路线绑架。
  4. 与 supervision 原生一体predict() 直接返回 sv.Detections,姊妹篇的全部下游技能(标注、切片、追踪、评测)零成本复用。

0.3 环境与素材(本机实测口径)

与姊妹篇同一台机器、同一套环境,实测数字均可复现:

项目 配置
显卡 RTX 5060 Laptop(Blackwell 架构,sm_120)
关键依赖 torch 2.11.0+cu128(Blackwell 必须 CUDA ≥ 12.8)、supervision 0.30
检测库 rfdetr 1.10.1(pip install rfdetr)、ultralytics(对照实验用)
素材原则 公开素材(街景图、公开行人视频)

全文代码基于 rfdetr 1.10+ 口径编写:网上旧教程大量使用的 RFDETRBaseoptimize_for_inference() 等写法已在新版弃用或移除,抄旧代码报错时先对版本;1.4→1.10 的完整升级对照见官方 Migration 指南。


第一章 关键点推理:从检测框到人体骨骼

1.1 Keypoint Preview:一个模型,17 个关节

RF-DETR 关键点模型目前只有一个预览版RFDETRKeypointPreview------在 COCO person 关键点上预训练,每个人输出 17 个骨骼关节(K=17,COCO 标准关键点定义)。

规格 数值
COCO AP50:95(person 关键点,OKS sigmas) 71.8
延迟(T4 / TensorRT FP16 / batch 1) 9.7 ms
参数量 40.7 M
输入分辨率 576×576
协议 Apache-2.0

官方口径:同延迟下超过 YOLO26-pose X 与 YOLO11-pose X。两点使用前提要知道:

  1. 仅 rfdetr 包提供(inference 包暂不支持);
  2. Preview = 早期访问:API 与权重在正式版前可能变动,且官方明说"微调自定义关键点数据集才是主要用途"------预训练模型是起点,不是终点。姿态分析类需求(跌倒检测、作业姿势评估)微调自有数据时走的就是它。

1.2 单图推理与 KeyPoints 输出结构

python 复制代码
import cv2
import supervision as sv
from rfdetr import RFDETRKeypointPreview

model = RFDETRKeypointPreview()

image_bgr = cv2.imread("dog.jpeg")
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)   # ⚠️ 必须 RGB(第一章铁律)
kp = model.predict(image_rgb, threshold=0.5)

annotated = sv.EdgeAnnotator().annotate(image_rgb, kp)

predict() 返回的是 sv.KeyPoints (不是 sv.Detections)------姊妹篇第五章用 ultralytics 姿态模型时经 KeyPoints.from_ultralytics 转过一次,这里 rfdetr 是原生直出。逐字段拆解(N=检出人数,K=17):

字段 形状 说明
kp.xy (N, 17, 2) 每人每个关节的像素坐标
kp.keypoint_confidence (N, 17) 关节级可找到度得分------过滤低置信关节就靠它
kp.detection_confidence (N,) 实例级 检测分,threshold 过滤的就是它;注意它包含默认的不确定性融合项,归一到 [0, 1)
kp.data["xyxy"] (N, 4) 每人对应的检测框------关键点模型也自带框,下游想接框类标注器/追踪器不用自己拼
kp.data["class_name"] (N,) 类名解析
kp.data["source_image"] list 源图存一份,N 个条目指向同一数组,取 [0]

⚠️ 本章最大的坑在 class_id :COCO 预训练权重用的是稀疏类别 ID(1--90 的 COCO 原始编号) ,而且关键点模型存在"背景槽位"的历史版本差异(新版 one-class 是 0=前景、1=__background__;旧版背景优先则是 0 号槽位给背景)。实测直接踩中 :本机加载 Preview 权重推理,输出的 class_id=[1]class_name=['person']------前景 person 落在 1 号槽位 (背景优先的老式编号),按"0=前景"的直觉去索引就会拿错。结论:永远用 data["class_name"] 解析类名,不要拿 class_id 去索引自己的类别表

另一个语义差异要留意:ultralytics 的 conf 是单一检测分,rfdetr 关键点模型的置信度分关节级和实例级两层 ,过滤时机不同------实例级过滤靠 threshold 参数(推理时),关节级过滤靠 keypoint_confidence(推理后,见 1.3)。

顺带一个实用特性:批量推理predict() 除了单图还接受图片列表 ,多图打包进一次前向传播,返回对应长度的结果列表------检测模型返回 Detections 列表,关键点模型返回 KeyPoints 列表(本机实测确认两者都支持)。离线批量处理图片集时,这一条比逐帧循环省不少吞吐;官方 Pretrained Models 页专门给了示例代码。

1.3 四个骨骼标注器(两个是新的)

supervision 提供四个关键点标注器,均自动跳过 visible=False 的关节:

标注器 画什么 备注
sv.EdgeAnnotator 骨架连线(关节间连接线) 姊妹篇第五章已实测
sv.VertexAnnotator 每个关节一个圆点 姊妹篇第五章已实测
sv.VertexEllipseAnnotator 每个关节一个协方差椭圆(来自 data["covariance"] 新增:把逐关节不确定度画成"椭圆脚印"
sv.VertexEllipseHaloAnnotator 同上 + 柔光晕 新增:复杂背景上对比度更好

椭圆两个标注器是官方文档新出现的玩法------不是把关节画出来,而是把模型对每个关节位置的不确定程度可视化,做低置信关节诊断时比纯圆点直观。四个标注器在本机 supervision 0.30 均已就位(hasattr 逐一验证通过)。

一个实测发现要先泼盆冷水 :协方差椭圆的大小直接反映不确定度------当人物被严重遮挡(关节基本靠猜)时,椭圆会被撑得巨大、互相叠满整个画面(1.6 的实测图就是活例)。所以椭圆标注器适合人物基本完整可见的画面做不确定度诊断,光晕版在复杂背景上更醒目,但救不了遮挡场景。

手动隐藏低置信关节的官方写法:对 keypoint_confidence 做阈值,把低于阈值的关节在 kp.visible 里写成 False------标注器会自动跳过,无需自己改坐标。

1.4 视频 / 摄像头 / RTSP 帧循环

官方三段循环(视频文件 / 摄像头 / RTSP)骨架完全一致,只有 VideoCapture 的源不同:

python 复制代码
video_capture = cv2.VideoCapture("video.mp4")     # 摄像头传 0,RTSP 传流地址
edge = sv.EdgeAnnotator()
vertex = sv.VertexAnnotator()

while True:
    ok, frame_bgr = video_capture.read()
    if not ok:
        break

    frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)   # ⚠️ 全章唯一的硬坑
    kp = model.predict(frame_rgb, threshold=0.5)

    annotated = edge.annotate(frame_rgb, kp)
    annotated = vertex.annotate(annotated, kp)
    cv2.imshow("RF-DETR Keypoint", annotated)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

三点说明:

  1. BGR→RGB 是静默坑:不转不报错,但检出率悄悄下降(第一章检测实验实测过同一现象),多路接入时建议在取流层统一转好。
  2. 姊妹篇的 sv.process_video 同样可用;裸循环的好处是摄像头 / RTSP 只换源不换逻辑,适合快速验证。
  3. 标注在 RGB 图上做、展示存盘前转回 BGR------官方示例里两个通道混着用没出问题(绘制不挑通道),但要保证推理输入的通道顺序正确。

1.5 与姊妹篇 yolo11n-pose 的路线对照

环节 ultralytics(姊妹篇第五章) rfdetr(本章)
加载 YOLO("yolo11n-pose.pt") RFDETRKeypointPreview()
推理输出 Resultssv.KeyPoints.from_ultralytics() 转换 原生直出 sv.KeyPoints
检测框 需另取 results.boxes kp.data["xyxy"] 直接带
关节过滤 手动按 conf 掩码 visible 布尔,标注器原生支持
不确定度可视化 协方差椭圆两个标注器
协议 AGPL-3.0 Apache-2.0

技能完全迁移:姊妹篇第五章的 as_detectionsDetectionsSmoother 平滑、Edge/Vertex 标注在 rfdetr 输出上原样可用。

1.6 实测:RTX 5060 上的关键点推理

以下全部数字来自本机的实测输出(RTX 5060 Laptop / cu128 / rfdetr 1.10.1 / supervision 0.30)。

加载与权重 :权重文件 rf-detr-keypoint-preview-xlarge.pth(约百 MB 级,首次自动下载,MD5 校验),进程内就绪 1.3 秒。加载日志里两条警告值得读:checkpoint 按 1 类 配置(模型骨架按 90 类构建,加载时用 checkpoint 的 1 类)、keypoint schema 从 [17] 临时调整为 checkpoint 的 [0, 17]------0 是背景槽位 + 17 个关节,正好印证 1.2 的 class_id 坑不是文档危言。

单图推理(dog.jpeg,人被狗遮挡大半的街景)

threshold 检出人数 detection_confidence
0.25 2 0.666 / 0.253
0.50 1 0.666
0.75 0 ---

阈值 0.5 检出的那 1 个人,17 个关节里 12 个置信度低于 0.5 (被遮挡的下半身基本靠猜),而右肩 / 右耳 / 右肘 / 右腕高达 0.96--1.00------"实例检出了,但一半关节不可信",正是 visible 过滤的用武之地(1.3)。不过滤直接画骨架就是下面这样------猜测关节的连线画成离谱锯齿:

开了 visible 过滤之后,猜测关节连同锯齿线一起消失,只剩可信的上半身------同一个模型、同一张图,正反两版对照:

另注意 0.75 阈值下全军覆没:关键点模型的实例分普遍比检测模型低(含不确定性融合项),阈值不宜照搬检测习惯的 0.5+

视频循环(people-walking.mp4,341 帧广场俯拍)

  • 未做推理优化(日志提示 Model is not optimized for inference):单帧延迟均值 77.5 ms / 中位 76.7 ms / P95 93.5 ms,等效 12.9 FPS 。对比官方 T4 + TensorRT FP16 的 9.7ms------差距大头在 fp16 与 TensorRT(官方称优化后 T4 可再快约 8 倍),model.inference(dtype=float16) 的优化实验留给部署章。
  • 逐帧人数:均值 7.29 / 最大 12 / 最小 4,100% 的帧都有人------全程无追踪断链。
  • 画面里行人远多于骨骼数(见上方样帧):远处小目标要么实例分过不了 0.5,要么关节置信度低被隐藏。姿态模型"只管抓得住的人"------远景人群分析要么降阈值、要么换更高分辨率输入,这组数字就是选型依据。

椭圆光晕的实测教训 :dog.jpeg 那个被遮挡人物的 VertexEllipseHaloAnnotator 输出里,巨大光斑铺满画面------不确定度可视化诚实地暴露了"这半个人是猜的",再次印证 1.3 的提醒:椭圆标注器只适合人物完整可见的画面。

1.7 本章方法速查

方法 干什么 关键参数(默认值) 返回值 / 要点
RFDETRKeypointPreview() 加载关键点模型(COCO person 17 关节) 无必填参 首次运行自动下载权重;Preview 版 API/权重可能变动;仅 rfdetr 包提供
model.predict(image, threshold=0.5) 关键点推理 必须喂 RGBthreshold 过滤的是实例级 detection_confidence(含不确定性融合项,归一 [0,1)) 返回 sv.KeyPoints,不是 sv.Detections
kp.xy / kp.keypoint_confidence 关节坐标 / 关节级置信度 形状 (N,17,2) / (N,17) 关节级过滤:阈值后写 kp.visible,标注器自动跳过 False
kp.data["xyxy"] 每人对应检测框 --- (N,4) 数组;接框类标注器/追踪器不必自己拼框
kp.data["class_name"] 类名解析 --- ⚠️ class_id 是稀疏 COCO 编号(1--90)且有背景槽位差异,不要拿它索引类别表
sv.EdgeAnnotator / VertexAnnotator 骨架连线 / 关节圆点 annotate(image, key_points) 姊妹篇第五章已实测;visible=False 的关节自动跳过
sv.VertexEllipseAnnotator / VertexEllipseHaloAnnotator 协方差椭圆 / 椭圆+光晕 依赖 data["covariance"] 官方新增:逐关节不确定度可视化,supervision 0.30 已就位
cv2.VideoCapture(...) 视频源接入 文件路径 / 摄像头索引 0 / RTSP 地址 官方三段循环只差源;cvtColor(BGR2RGB) 是唯一硬坑

第二章 微调:训练自己的模型

2.1 训练前置:extra 与数据格式

训练依赖不在基础包里,先装:

bash 复制代码
pip install "rfdetr[train]"            # 训练栈(PyTorch Lightning 等)
pip install "rfdetr[train,loggers]"    # 可选:TensorBoard / W&B / MLflow 实验追踪

数据格式自动检测 ,不用手动指定------train() 按目录结构认格式:

格式 检测依据 说明
COCO train/_annotations.coco.json Roboflow 导出(dataset_file="roboflow")开箱即用
YOLO data.yaml + train/images/ YOLO 姿态数据集须在 data.yaml 声明 kpt_shape

两种格式的口径速览

复制代码
COCO                                  YOLO
dataset/                              dataset/
├── train/                            ├── data.yaml          # names / nc / train / val / test
│   ├── _annotations.coco.json        ├── train/
│   └── *.jpg                         │   ├── images/
├── valid/(同 train 布局)           │   └── labels/        # 每图一个同名 .txt
└── test/(同 train 布局)            ├── valid/ ...  └── test/ ...

标注口径的四个差异点:

  • 框的表示 :COCO bbox=[x, y, w, h]------左上角原点、像素值;YOLO 每行 class_id x_center y_center w h------中心点表示且全部归一化到 0--1
  • 类别 ID :COCO 的 category_id 必须与 categories 数组对得上(可以从 1 起,实验 A 建库时重映射成连续 ID 就是这个原因);YOLO 的 class_iddata.yamlnames0 起下标
  • 分割 :COCO 在标注里加 segmentation 键(多边形坐标的扁平列表);YOLO 在行尾直接接多边形顶点(同样归一化)。
  • 关键点 :COCO 走 keypoints=[x,y,v]*K,category 里声明关节名单与 skeleton(实验 B 建库用的就是这套);YOLO pose 在 data.yaml 声明 kpt_shape: [17, 3]flip_idx(左右翻转置换)会被自动换算成 keypoint_flip_pairs------2.6 说的"schema 能推断出来就带上"就是这条链路;kpt_shape: [K, 2] 时可见性由库合成(非零点记 2,(0,0) 记 0)。

空标注图(负样本图,"这张图没框"也要能表达):

格式 做法
COCO 图片照常进 images 数组,annotations 里不加它的标注
YOLO 建一个 0 字节的空 .txt,或干脆不放标签文件

格式互转不用重标------supervision(姊妹篇主角)四个方法包办:

python 复制代码
import supervision as sv

# YOLO → COCO
ds = sv.DetectionDataset.from_yolo(
    images_directory_path="yolo/images", annotations_directory_path="yolo/labels",
    data_yaml_path="yolo/data.yaml")
ds.as_coco(images_directory_path="coco/images",
           annotations_path="coco/annotations.json")

# COCO → YOLO
ds = sv.DetectionDataset.from_coco(
    images_directory_path="coco/images", annotations_path="coco/annotations.json")
ds.as_yolo(images_directory_path="out/images",
           annotations_directory_path="out/labels", data_yaml_path="out/data.yaml")

选型口径(官方原话):两种格式 RF-DETR 处理得一模一样,手头是哪种就用哪种,不为模型迁就格式。

版本口径提醒:rfdetr 1.10 起 grad_accum_steps 默认为 1(1.4 时代默认 4)------网上旧教程的"有效批大小"算法和现在不同,照抄会得到不一样的优化行为。

2.2 model.train():一行微调

python 复制代码
from rfdetr import RFDETRNano

model = RFDETRNano()   # 实例化即自动下载 COCO 预训练权重,微调从这里起步

model.train(
    dataset_dir="dataset/",   # COCO 或 YOLO 格式,自动检测
    epochs=10,
    batch_size="auto",        # 官方推荐的移植起点
    lr=1e-4,
    output_dir="output/run1",
)
参数 默认 说明
dataset_dir 必填 数据集根目录(含 train/valid 划分)
epochs --- 轮数;微调场景 10--50 常见
batch_size "auto" 探测当前 GPU 显存 → 定物理 batch,并给出梯度累积建议值;CPU / MPS 必须传整数
grad_accum_steps 1 梯度累积;1.10 默认 1,设大可放大有效批大小
lr 1e-4(检测/分割) 关键点 Preview 官方示例用 2e-5;另有 lr_encoder 单独控骨干学习率
output_dir --- 训练产物目录(2.3 详解)

train() 的完整参数有 40 多个,微调最常碰的可选项挑这些:

参数 默认 说明
lr_encoder 1.5e-4 骨干编码器专属学习率,想"管住骨干慢慢调"就压低它
resolution 模型相关 输入分辨率(须满足模型整除规则);实验 B 自动升到 576、检测 384,就是各模型的这个默认值
warmup_epochs 0.0 线性学习率预热轮数,长周期训练建议开
seed None 全局随机种子,复现实验时定死
early_stopping 三件套 False / patience=10 / min_delta=0.001 早停默认 (2.3 有实锤);开了记得配 best_model_metric"map" / "mar"
skip_best_epochs 0 微调预训练权重时建议设几轮,防止最初波动把"最佳"记录与早停计数带偏
checkpoint_interval 10 周期 checkpoint 间隔(实验 B 的 checkpoint_9.ckpt 就是它落盘的)
resume None 断点续训:.ckpt 恢复优化器/调度器全状态,轻量 .pth 则重启优化器
wandb / mlflow / project / run False / None W&B / MLflow 实验追踪,可同时开(配 project 分组、run 命名单次训练,不指定自动随机名;需 rfdetr[train,loggers])。⚠️ clearml=True 尚未实装,传了直接 NotImplementedError------要用 ClearML 得在训练前手动 Task.init() 借 SDK 自动绑定
eval_interval 1 每 N 轮跑一次完整验证,长训练省时间
compute_val_loss "auto" 验证 loss 计算(2.5 日志速读里有条目)

还有两类参数容易踩混:

  • 构造器参数gradient_checkpointing=True8GB 卡救星 :省 30--40% 显存,代价是慢约 20%,RFDETRNano(gradient_checkpointing=True) 这样传)、num_keypoints_per_classkeypoint_flip_pairs 都在模型构造函数 里传,不进 train()
  • 已废弃参数 :网上旧代码里的 eval_ema_onlylr_droplr_min_factor 已被移除或改道(分别换 eval_base_modellr_scheduler + lr_scheduler_kwargs------后者接受 "step" / "cosine" 预设或任意 PyTorch 调度器导入路径),照抄会被忽略或报错。优化器同理可换:TrainConfig.optimizer 接受 "adamw" / "sgd" 短名、导入路径或可调用对象,但换了之后 fused_optimizer"auto" 显存估算都不再生效。

batch_size="auto" 的机制值得知道:它先探测硬件能塞下的物理 batch,再对照配置的有效批目标给出累积建议------官方明说这不保证优化等价(物理 batch 变大本身就会改变吞吐与行为),但在换卡、换分辨率时是省心的默认值。

⚠️ 实测坑(8GB 级笔记本 GPU)"auto" 的探测从大候选起跳,逐级回退到能塞下的尺寸------但探测的前提是显存基本空闲 。两个叠加因素会让探测阶段直接 CUDA out of memory(连 torch.cuda.empty_cache() 都失败):① 同一进程里上一步加载的模型没释放(比如先用 Medium 伪标注、再训 Nano------del model + torch.cuda.empty_cache() 必须做);② 探测本身首跳过大,8GB 卡没有回退余地。结论:显存 ≤8GB 的卡不要用 "auto",直接给整数 (如 batch_size=4, grad_accum_steps=1,还不够就 2),稳定且行为可预期。补充:探测行为受几个 auto_batch_* 参数控制(目标有效批 auto_batch_target_effective=16、探测时的每图合成目标上限、EMA 显存预留比例 0.7)------显存紧张的卡也可以保留 auto 但把目标有效批调小,让探测从更小的候选起跳。

官方也给了显存档位参考配置 (按默认 Medium 模型口径;Nano 更小可以更宽------我们 8GB 卡 batch_size=4 跑 Nano 毫无压力,比官方 8GB 档还激进):

显存 配置
8GB batch_size=1, grad_accum_steps=16, gradient_checkpointing=True, resolution=576
12GB batch_size=2, grad_accum_steps=8, gradient_checkpointing=True
16GB batch_size=4, grad_accum_steps=4
24GB batch_size=8, grad_accum_steps=2
40GB+ batch_size=16, grad_accum_steps=1, resolution=768

⚠️ 实测坑(Windows + 多进程 DataLoader) :训练时 DataLoader 会启动 worker 子进程加载增强后的批次,Windows 上走的是 spawn 模式------子进程会重新执行你的脚本顶层代码 。如果整个流程(伪标注 → 建库 → 训练)平铺在脚本顶层而没有 if __name__ == "__main__": 守卫,子进程会把脚本从头再跑一遍、再跑一遍(日志里第 1 步、第 2 步反复刷屏就是症状),最终抛 RuntimeError: DataLoader worker exited unexpectedly。Linux 默认 fork,这个问题完全隐形,所以官方示例从不提------Windows 用户务必把逻辑包进 main() 函数再加守卫。

四个进阶口径,真实项目迟早用上:

  • 断点续训resume="output/last.ckpt" 加载的是全状态 ------模型权重、优化器、学习率调度器、训练轮数全部续上;而 checkpoint_best_total.pth 这类轻量 .pth故意省掉优化器/调度器 的小体积存档,拿它续训优化器从零开始,且 best 分数追踪还要求 output_dir 与当初完全一致 。口径一句话:接着上次练用 resume,拿旧权重开新训练用 pretrain_weights
  • 多 GPU :训练脚本照写,model.train(..., devices="auto"),然后用 torchrun --nproc_per_node=4 train.py 启动。最大的坑:devices 必须显式传 ------默认 devices=1,就算 torchrun 拉起多进程也依然静默单卡。有效批 = batch_size × grad_accum_steps × GPU 数,换卡数时等比换算;关键点模型多卡建议 grad_accum_steps=1(手动优化下每个 microbatch 都会同步一次梯度,累积只多付通信费),且不支持 FSDP/DeepSpeed 分片策略。
  • 自定义增强 :默认 torchvision 增强(缩放抖动 + 50% 水平翻转)零配置;传非空 aug_config 字典即切到 Albumentations 栈(需装 rfdetr[train,augment])------框会随几何变换自动旋转平移、像素级变换(模糊/噪声/色彩)不动坐标,联动完全自动不用管;augmentation_backend 可强制管线:"torchvision" 钉死默认行为、"kornia" 走 GPU 批处理、"auto" 有 CUDA 时优先 Kornia。官方内置四档预设按数据规模选:AUG_CONSERVATIVE(<500 图,翻转+轻度亮度对比)、AUG_AGGRESSIVE(2000+ 图,旋转/仿射/色彩抖动)、AUG_AERIAL(遥感俯拍)、AUG_INDUSTRIAL(制造/检测场景直接抄);预设是普通字典,可展开改({**AUG_AGGRESSIVE, "VerticalFlip": {"p": 0.1}})。aug_config={} 传空字典只是关掉可选项 (水平翻转),必备的缩放归一化仍在;要连随机裁剪分支也关,另有独立的 scale_jitter=False------贴边目标的标注就不会被裁掉。两条官方经验:几何变换别上太猛,旋转角度过大会把框推出画面(增强后框消失就是它);强增强下训练 mAP 低于验证 mAP 是正常现象 不是 bug------训练吃的是增强后的难图,验证用的是原图。2.5 日志速读里那条"增强后端 Albumentations → torchvision"的警告,装上这个 extra 并传 aug_config 就能复刻旧行为。
  • 拆开训练栈model.train() 内部其实只有三步------RFDETRModelModule + RFDETRDataModule + build_trainer,然后 trainer.fit(),全是公开的标准 PyTorch Lightning 类。要加自定义回调/日志器、接管多卡策略、深度定制训练循环时,把这三步拆出来自己组装就是官方推荐路径。顺带解释了 2.5 日志里那些 Lightning 消息从哪来;产物 metrics.csv 的列名也走 Lightning 指标口径(val/mAP_50_95、关键点 val/keypoint_map_50_95test/loss 恒记),翻 CSV 时按这个找列。

2.3 训练产物:五种 checkpoint 的分工

训练结束,output_dir 里躺着一堆文件,该拿哪个去推理是新手最容易懵的点:

文件 里面有什么 用途
last.ckpt 模型权重 + 优化器 + 调度器 + 元数据(最大 断点续训(Resume)
checkpoint_<epoch>.ckpt 同上,每 10 epoch 存一次 周期性续训点
checkpoint_best_ema.pth EMA 权重(验证分最优),轻量 ---
checkpoint_best_regular.pth 原始权重(验证分最优),轻量 ---
checkpoint_best_total.pth EMA 与非 EMA 中验证分更高者,轻量 推理 / 评测的最终选择
  • EMA(指数滑动平均)是训练过程中参数的平滑版本,通常泛化更好------所以默认最优选择逻辑是"EMA 和原始谁验证分高用谁"。
  • 轻量 best 系列有意不带优化器/调度器状态 (文件小一个量级),只用于推理和评测;要续训回 last.ckpt
  • 关键点 Preview 模型的最优选择按 COCO 关键点 AP(val/keypoint_map_50_95)判定,且 checkpoint 持久化了关键点 schema------RFDETR.from_checkpoint() 能原样重建类别/关节槽位。
  • 训练默认带 EMA 权重use_ema=True)与最优 checkpoint 追踪,不用手动开;早停默认是关的early_stopping=False,实验 A/B 都跑满了 max_epochs 收场)------要开就配 early_stopping_patience(默认 10)和 best_model_metric(mAP/mAR 二选一);微调预训练权重建议设 skip_best_epochs,防止最初几轮的指标波动把"最佳"记录和早停计数带偏。

2.4 model.evaluate():一次评测,三种返回

python 复制代码
metrics = model.evaluate(dataset_dir="dataset/", split="test")
print(metrics["test/mAP_50_95"])

一次跑完数据集划分,返回并打印 mAP、mAR、macro-F1 扫描 全套 COCO 指标。内存里已有的权重直接被评测(训练完当场调不重载文件),也不往 output_dir 写任何东西。

⚠️ split 参数的行为矩阵------本教程实测挖出的坑

数据格式 split="test" 遇到没有 test 划分时 后果
Roboflow 导出 COCO 直接 FileNotFoundError 好事,明确报错
YOLO 格式 静默回退到 valid/ ,返回键仍叫 test/* 坏事:你以为在测 test,实际测的是 valid
COCO / Objects365 原生 无 test 概念,静默测 valid/ 同上

结论:看数字之前先看日志 ------回退发生时会有 warning,但返回键名不会变。想稳妥就用 split="val"(永远直取 valid/)。另外 evaluate() 虽然接受与 train() 相同的关键字参数,epochs/lr/ema 等训练字段全是摆设------评测走的是 eval-only 流程。

2.5 实验一:迷你数据集烟测(全程离线)

实验设计(诚实声明) :用预训练 Medium 模型给公开素材(dog.jpeg + people-walking 视频抽帧共十余张)伪标注 出 COCO 迷你数据集,三划分后微调 Nano。这是机制烟测 ------验证"伪标注 → 建库 → 训练 → checkpoint → 评测 → 回载推理"全链路走得通,mAP 数字本身没有业务含义;把这套流程换成你的真实数据集,就是真实微调------结构完全不变,变的只是数据和轮数

配套脚本,五步:

  1. 伪标注建库:预训练模型打标 → 类别重映射为连续 ID → 按 Roboflow COCO 布局写出 train(8)/valid(2)/test(2)
  2. model.train():Nano × 10 epochs(迷你数据集,分钟级)
  3. 列出 output_dir 实际产物,对照 2.3 的表
  4. 加载 checkpoint_best_total.pth 推理两张图------dog.jpeg 和标注框最多的一张行人帧;注意标签已从 COCO 80 类变成数据集自己的类别表
  5. evaluate(split="test") 正常出数 → 把 test 文件夹拿掉再跑一次,实测 COCO 格式的 FileNotFoundError(2.4 坑的活体演示)

实测结果(RTX 5060 Laptop 8GB)

  1. 建库:12 张素材伪标注出 5 类(dog、car、person、backpack、handbag)共 102 框 → train 8 图 65 框 / valid 2 图 15 框 / test 2 图 22 框,类别表重映射为连续 ID。
  2. 训练 :10 epochs 共 62.1 秒 (batch_size=4,2.2 那两条 Windows 实测坑就是这实验第一次跑出来的)。验证 mAP(50:95) 逐轮 0.3284 → 0.4164 → 0.4041 → 0.4268 → 0.3816 → 0.4203 → 0.4563 → 0.4931 → 0.4699 → 0.5905 :前六轮在 0.38--0.46 震荡,第 7 轮起 mAR 冲上 0.93、第 10 轮收在全程最高------曲线后段发力,和 5 epochs 版(终值 0.3765)对比,多训几轮的效果一目了然。最优 checkpoint 仍由 EMA 判定(Best total checkpoint saved from EMA (regular=0.0000, ema=0.5905))。
  3. 产物清单 (对照 2.3 的表):checkpoint_best_ema.pth / checkpoint_best_total.pth / last_ema.pth 各 120.9 MB,last.ckptcheckpoint_9.ckpt 各 483.4 MB,外加 metrics.csvtraining_config.json。两点与表有出入的实测细节:checkpoint_<epoch>.ckpt 周期存档点按每 10 epoch 落盘,恰好撞上最后一轮才出现一个;checkpoint_best_regular.pth 始终没有------regular 权重没算验证分,best_total 由 EMA 承担。表是官方口径,实际产物以日志为准。
  4. 双图回载推理 (本轮最大看点):加载 checkpoint_best_total.pth(自动以 checkpoint 的 5 类为准,反向警告一条)后------
    • 行人帧 (12 个伪标注框):检出 10 个 person,置信度 0.58--0.95------样本最多的类,学得又快又稳;
    • dog.jpeg (在训练集里!):只检出 1 个------car 0.56 。看了输出图会发现更妙:这个框框住的是画面右侧背景里一辆真车,不是认错;画面主体的狗反而没检出。单样本的 dog 类在新头里还没学会,模型只敢报样本充足、学得动的 car------"训练时见过"不等于"认得出",检测头随机重初始化后,类别学习速度和样本量直接挂钩。真实项目里稀有类别要么补样本、要么调采样策略,而不是指望多训几轮自己开窍。
  1. evaluate(split="test") :mAP 50:95 0.8939 、mAP 50 0.9941 、precision 1.0000 、F1 0.9767,比 5 epochs 版(0.8677)更高。数字高得可疑?------是必然的:test 集的标注也是伪标注模型自己打的,学生做老师的考卷,评测基准与模型输出同分布。换成真实人工标注数据集,这个虚高会立刻消失;用伪标注建库时,务必清楚自己看的是什么口径的数字。
  2. FileNotFoundError 坑复现 :把 test/ 划分拿掉再跑,COCO 格式如 2.4 所述直接 FileNotFoundError: ...test\_annotations.coco.json------本教程实测口径确认。

附:一次训练日志速读------首次跑微调会被十几行日志糊脸,逐条翻译(按出现顺序):

日志原文(节选) 人话
not loading DINOv2 backbone weights(两条 WARNING) 本机推理 patch 16 与 DINOv2 原生 patch 14 不同,骨干不吃 DINOv2 原始权重------RF-DETR 自己的 COCO 预训练权重正常加载,微调不受影响,官方原话"this is not a problem"
already exists with correct MD5 hash 权重文件已在本地且校验通过,跳过下载
Model is not optimized for inference... 没切 FP16 推理模式,延迟偏高;跑速度基准前先 model.inference(dtype=torch.float16)(第一章实测时切过)
detection head will be re-initialized to 5 classes 90 类旧头丢弃、5 类新头随机初始化------微调的真实起点,也是 4 里"背景车捞出来了、主体的狗没认出"的根源
TensorBoard logging disabled 没装 tensorboard 包。TensorBoard 本来是默认开启 的(要关得显式传 tensorboard=False),没装包就静默关闭并出这条警告------装 rfdetr[loggers] 后跑 tensorboard --logdir output 浏览器开 6006 端口看曲线。不想装也没损失:metrics.csv 由 CSV 日志器永远在写,每次验证步追加一行全部指标
augmentation backend ... Albumentations → torchvision 新版默认训练增强后端换了(旧版 cv2 插值 → 新版 torchvision 抗锯齿),像素级行为略有差异;要复刻旧行为装 rfdetr[augment] 并传 aug_config
square resize at resolution 384 / scales: [544] 训练分辨率 384 方图,多尺度增强上探 544
uniform sampler because dataset is too small: 8 < 20 训练图少于 20 张,放弃类别均衡采样,改均匀抽样
training batches (5) smaller than log_every_n_steps=50 日志默认每 50 步记一次,但整个 epoch 才 5 步------无害提示
Triton linear-assignment ... using SciPy on CPU 标签分配的 Triton 加速核在该 CUDA 环境不可用,退回 SciPy CPU 实现,训练略慢,Windows 上常见
Skipping validation-loss computation 默认验证只算 mAP 不算 loss;想记 loss 曲线传 compute_val_loss=True
Best total checkpoint saved from EMA (regular=0.0000, ema=0.5905) checkpoint_best_total.pth 由 EMA 权重当选;regular 没参与评选(本轮未出分)
Checkpoint has 5 classes but model is configured for 90 回载微调权重时的反向 警告:库自动以 checkpoint 的 5 类为准,想消掉就传 num_classes=5

至此"伪标注 → 建库 → 训练 → checkpoint → 评测 → 回载"全链路实测打通;换上你的真实数据集,把第 1 步换成人工标注,其余结构原样不动。

2.6 实验二:关键点微调烟测(伪标注骨骼)

第一章的 Keypoint Preview 模型同样走 model.train(),且关节数不再限 17 ------由你数据集的关键点标注(COCO keypoints 或 YOLO pose 的 kpt_shape)决定,schema 自动推断。

实验设计 :和实验 A 同一套伪标注思路------手头没有标注好的自定义关键点数据集,就用第一章的 KeypointPreview 给同一批素材(dog.jpeg + 视频抽帧)伪标注 person + 17 关节,导出成 COCO 关键点格式(categorieskeypoints 关节名单与 skeleton 骨架,annotationskeypoints=[x,y,v]*17num_keypoints),三划分后微调。官方口径里关键点微调的特有配置全部落地:

python 复制代码
from rfdetr import RFDETRKeypointPreview
from rfdetr.datasets._keypoint_schema import infer_coco_keypoint_schema

schema = infer_coco_keypoint_schema(DATASET / "train" / "_annotations.coco.json")

model = RFDETRKeypointPreview(
    num_classes=len(schema.class_names),
    num_keypoints_per_class=schema.num_keypoints_per_class,
    pretrain_weights=str(KP_WEIGHTS),
)
model.train(
    dataset_file="roboflow",
    dataset_dir=str(DATASET),
    class_names=schema.class_names,
    keypoint_oks_sigmas=schema.keypoint_oks_sigmas,
    epochs=10, batch_size=2, grad_accum_steps=2,   # 40.7M 模型,8GB 卡从 2 起步
    lr=1e-4,                                       # 烟测口径;官方 2e-5 属长周期保守学习率
    output_dir=str(run_dir),
)

要点:官方关键点示例的学习率 2e-5 比检测的 1e-4 小一个量级,且默认配 50+ epochs 的长周期------烟测的时间预算内跑不动(第一轮实测见下),所以脚本改用检测级 1e-4;真实项目请恢复 2e-5 。左右对称关节要配 keypoint_flip_pairs(水平翻转增强时交换左右标签,schema 能推断出来就带上);YOLO pose 数据集用 infer_yolo_keypoint_schema(data.yaml)。2.2 那两条 Windows 实测坑(显存释放、main 守卫)在本实验同样适用。

配套脚本,五步:

  1. 伪标注建库:KeypointPreview 打标 person + 17 关节(关节置信度 ≥0.5 记 v=2 可见、否则 v=1)→ 按 COCO 关键点布局写出 train(8)/valid(2)/test(2)
  2. 关键点微调:10 epochs,schema 自动推断 → lr=1e-4(烟测口径)
  3. 列出 output_dir 实际产物
  4. 阈值扫描(0.05--0.5 各档人数与最高检测分)→ 加载 checkpoint_best_total.pth 骨骼推理两张图(dog.jpeg + 行人帧),Edge + Vertex 标注器出图,出图阈值 0.2
  5. evaluate(split="test") 出关键点指标

第一轮实测(官方 2e-5 口径) :建库 85 人 × 17 关节 (train 8 图 53 人 / valid 2 图 18 人 / test 2 图 14 人);训练 10 epochs 共 175.6 秒,分辨率自动升到 576 方图(检测是 384------关键点模型吃更高分辨率);验证曲线前 7 轮全程 0.0000 ,第 8--10 轮才爬到 0.1188 → 0.3366 → 0.3926;checkpoint 逻辑还现出一个新变体------最优记录从未被触发时,日志 EMA metric never improved 之后库把最后一轮 EMA 权重 直接当 best_ema 存档。最要命的是:predict(threshold=0.5) 两张图都检出 0 人 (行人帧也是),而 evaluate 却给出 keypoint_map_50_95 0.3665 / box mAP 0.4486------评测管线不吃 predict 的阈值截断,低分预测照样参与 OKS 匹配,这是继"学生做老师考卷"之后第二个评测口径坑。诊断:链路全通,但 2e-5 在烟测时间预算内学不出可用的置信度,所有检测分都压在 0.5 以下。

第二轮实测(lr=1e-4 重训,其余不动)

  1. 训练 :10 epochs 共 178.4 秒 ,曲线彻底换相:第 1 轮 0.0000 → 第 2 轮 0.2158 → 第 3 轮 0.5682 → 一路爬到第 8 轮 0.9309、第 10 轮收 0.8986。与第一轮"7 轮全零"对照,学习率提一个量级的差距一目了然。
  2. checkpoint 怪癖复现EMA metric never improved 在两轮里都出现(检测实验没有)------看起来是关键点 Preview 的结构性怪癖,best_ema / best_total 都落在最后一轮 EMA 权重上。用它之前先知道这一点。
  3. 阈值扫描(行人帧) :0.05 → 70 人 / 0.10 → 36 人 / 0.20 → 12 人 / 0.30 → 9 人 / 0.50 → 0 人 ,最高检测分 0.475 ------重训后置信度天花板仍差 0.025 才够 0.5。这坐实了本节的核心经验:微调后别拍脑袋用 0.5,先扫描、让工作阈值跟着模型的实际分数带走
  4. 骨骼出图(阈值 0.2) :行人帧 12 人骨骼齐全 (10 个伪标注人 + 2 个低分多检),关节置信度均值 0.938 ;dog.jpeg 2 人(与第一章"dog.jpeg 画面含 2 人"口径一致),关节置信度均值 0.495。两张图都"看得到骨骼",烟测闭环。
  1. evaluate(split="test") :keypoint_map_50_95 0.8654、keypoint_map_50 0.9436、keypoint_mAR 0.9429,box mAP 50:95 0.9381------比第一轮的 0.3665 翻了一倍还多(口径提醒同实验 A:test 标注出自伪标注模型,数字按"学生做老师考卷"口径看)。
  2. 两轮对比就是一节现场课:官方 2e-5 没有错,但它默认长周期;短周期烟测要按时间预算调学习率(第二轮 1e-4),并让阈值跟着模型实际分数带走(0.2 而非 0.5)。真实项目恢复 2e-5 + 50+ epochs,阈值照扫不误。

2.7 本章方法速查

方法 干什么 关键参数(默认值) 返回值 / 要点
pip install "rfdetr[train]" 装训练栈 loggers extra 可选 Lightning 等依赖,基础包不含
model.train(dataset_dir=..., ...) 一行微调 batch_size="auto"(探测物理 batch + 累积建议)、lr=1e-4(关键点 2e-5)、grad_accum_steps=1(1.10 起默认,旧版 4)、epochsoutput_dir COCO/YOLO 格式自动检测;默认带 EMA + 早停 + 最优 checkpoint
output_dir 产物 五种 checkpoint last.ckpt / checkpoint_<epoch>(含优化器,续训用);best_ema / best_regular / best_total(轻量) 推理评测拿 checkpoint_best_total.pth(EMA 与非 EMA 验证分择优)
RFDETR.from_checkpoint(path) 从 checkpoint 重建模型 --- 关键点 schema 已持久化,槽位原样恢复
model.evaluate(dataset_dir, split="test") 一次评测出 mAP / mAR / macro-F1 split="test" / "val" 内存权重直接评;关键点模型额外返回 keypoint_map_50_95 / keypoint_map_50 / keypoint_mAR;⚠️ YOLO 格式无 test 时静默回退 valid 但键仍叫 test/* ,COCO 无 test 则 FileNotFoundError;训练字段传了也不生效;评测不吃 predict 的阈值截断
infer_coco_keypoint_schema(json路径) 关键点 schema 自动推断 对应 infer_yolo_keypoint_schema(data.yaml) 返回 class_names / num_keypoints_per_class / oks_sigmas;keypoint_flip_pairs 记得配对称关节
model.export() 导出部署模型 format="onnx"(默认,opset 17、batch_size=1)、fp16=True(TRT 默认半精度) 训练产物直接可导;ONNX 输出是原始张量需自解码------详见 2.8

2.8 导出部署速览

训练好的模型不必困在 Python 训练环境里------model.export() 一行默认导出 ONNX(opset 17、batch_size=1):

python 复制代码
model = RFDETRNano(pretrain_weights="output/run/checkpoint_best_total.pth")
model.export()                    # → output/ 下的 .onnx
model.export(format="tensorrt")   # NVIDIA GPU 上延迟最低(官方口径 Nano 2.3 ms)

格式按部署目标选(导出前各自装 extra:rfdetr[onnx] / [tflite] / [executorch] / [coreml],CoreML 仅 macOS):

目标 格式 要点
跨平台通用 format="onnx"(默认) ONNX Runtime / OpenVINO 直接吃;自定义分辨率须被 patch_size × num_windows 整除
NVIDIA GPU format="tensorrt" 先出 ONNX 再转 .trt引擎绑定构建机的 GPU 架构与版本,换卡要重导
移动端 / 边缘 format="tflite" FP32/FP16/INT8 三档,INT8 必须喂真实图片 做校准(calibration_data,随机噪声校准等于精度崩);实验性格式,锁版本
端侧 PyTorch / Apple format="executorch" / "coreml" 均不支持动态批;ExecuTorch 按后端选 xnnpack/coreml/qnn,QNN 需源码编译

最重要的一个坑:ONNX 输出是原始张量,不是现成的检测结果 ------dets 是 cxcywh 格式、labels 是没过 sigmoid 的 logits,要自己加 sigmoid、剔除背景槽位、转 xyxy;且必须按输出名匹配 取结果,不能按形状猜(类别数少时两个输出的末维可能一样大,猜形状必乱)。背景槽位下标还和训练时的类别映射挂钩:连续 ID 映射是 -1,官方 COCO 稀疏 ID 是 None。想省掉手写解码,可用官方推荐的 inference-models 库(PyTorch / ONNX / TensorRT 统一 API,TensorRT 引擎由它内部管理------这时别再传 format="tensorrt",会白构建一遍引擎)。

配套脚本,五步:加载实验一 best_total → export() 导出 → onnxruntime 会话体检(输入/输出名与形状)→ PyTorch 后端同图基线对照 → 手写解码出图 + CPU 延迟测量。

实测结果(RTX 5060 Laptop 8GB,ONNX Runtime CPU 路径)

  1. 导出export()3.4 秒 ,产物 rfdetr-nano.onnx 113.0 MB (Nano 权重 120.9 MB 的 .pth 转纯图后略小)。注意 export() 默认 verbose=True 会把整张 ONNX 计算图逐节点刷屏(几百行 onnx::MatMul / onnx::GridSample)------不是报错,嫌吵传 verbose=False
  2. 会话体检 :输入名 input,形状 [1,3,384,384](Nano 默认分辨率);输出名 dets(末维 4)+ labels(末维 6 = 5 类 + 1 背景槽)------"背景槽挂在末维最后"实测吻合,300 个 query 也与官方口径一致。按名匹配的两条输出判定一次通过。
  3. 两后端对照 (dog.jpeg,微调烟测权重):PyTorch top-5 为 car 0.5568 / car 0.3433 / backpack 0.3121 / car 0.2804 / car 0.2043;ONNX 解码 top-5 为 car 0.5566 / car 0.3385 / car 0.2502 / car 0.2109 / car 0.1625。top-1 对到千分位(0.5568 vs 0.5566),证明 ImageNet 归一化输入口径和 cxcywh→xyxy 解码链路写对了;中低分段两边有交换(PyTorch 的 backpack 0.31 在 ONNX 里掉出前五)------浮点后端差异在低置信候选上会重排名,属正常现象,判读时以 top 结果为准。阈值 0.25 检出 3 个框全是 car(背景那辆红车),与实验一"car 类学得动、dog 单样本没学会"的结论延续一致。
  1. 延迟 :ONNX Runtime CPU 路径 69.2 ms/帧,与 PyTorch CUDA 路径的 77.5 ms 基本打平------乍看反常,其实合理:predict() 默认走 FP32、且日志明确警告"未做推理优化";ONNX Runtime 的图优化把算子融合做得很足。工程结论:部署阶段换 ONNX Runtime,不依赖 GPU 也能拿到接近 GPU 的延迟,这是导出的真正价值。

相关推荐
YOLO数据集集合1 天前
无人机低空影像语义分割数据集 | 语义分割 遥感影像 无人机低空 地物分类 Potsdam Vaihingen LoveDA 9080期
人工智能·深度学习·yolo·目标检测·计算机视觉·语义分割·无人机数据集
智购科技自动贩卖机1 天前
自动售货机嵌入式系统时钟同步与时间管理实战:从RTC校准到断网时间保持的工程实践
大数据·linux·数据库·人工智能·yolo
计算机编程-吉哥2 天前
深度学习:我用YOLO11-L做了一个水下垃圾检测系统 对比YOLOv8-L/Faster R-CNN【计算机毕业设计选题推荐】
人工智能·深度学习·yolo·课程设计·计算机毕业设计选题
AI棒棒牛2 天前
YOLO26最新创新改进系列:融合 E3AD 认知注意力 Neck:具身认知增强的 FPN/PAN 特征选择机制,高效创新!
人工智能·yolo·计算机视觉·yolo26
hans汉斯2 天前
数据挖掘|基于BP神经网络的少数民族村寨文化型旅游体验产品潜在游客挖掘
深度学习·神经网络·算法·yolo·软件工程·bp·汉斯出版社
JAI科研3 天前
YOLO 完全指南(七):YOLO识别工程化 (上)
人工智能·深度学习·神经网络·yolo·目标检测·计算机视觉·transformer
JarmanYuo3 天前
YOLO 涨点研究(十二):具身 CV 进阶篇——Sim2Real 域随机化与真机部署
人工智能·pytorch·python·yolo·计算机视觉
YOLO数据集集合3 天前
无人船视角水面目标检测数据集 |无人船 USV 水面目标检测 自主航行 避障 水域监测 目标检测9076期
深度学习·yolo·目标检测·无人机·无人机视角·无人船·自主航线
YOLO数据集集合3 天前
渔船船只检测数据集 | 船只检测 渔船识别 拖船检测 海事监管 目标检测 YOLO格式 深度学习数据集 计算机视觉9076期
人工智能·深度学习·yolo·目标检测·计算机视觉