ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

RT-DETR论文解读与训练实战:Paddle版与YOLO版对比

RT-DETR论文解读与训练实战:Paddle版与YOLO版对比 前阵子仔细读完了RT-DETR论文顺手把官方PaddleDetection版和ultralytics YOLO框架下的版本都完整训练了一遍。说实话这两个路径差别不小踩坑点也多但跑通之后对RT-DETR的网络结构和训练逻辑理解会深很多。这篇笔记就专门拆一下RT-DETR的核心思路以及官方版和YOLO版训练到底该怎么玩适合正在上手RT-DETR、或者想把Transformer检测器拉到实时场景里的朋友。1. RT-DETR论文核心思想解读1.1 从DETR到RT-DETR为什么要做实时Transformer检测器DETR系列把目标检测变成了端到端的集合预测问题省掉了锚框和NMS这件事本身非常吸引人。但原始DETR有两个致命痛点一是收敛速度极慢动辄几百个epoch才能看到效果二是计算量大特征图分辨率稍微拉高一点自注意力的复杂度就爆炸根本谈不上实时。RT-DETR要解决的就是这两点。它不再像DETR那样直接在整个特征金字塔上做全局注意力而是用混合编码器把多尺度特征高效融合再用IoU-aware query selection从编码器特征里挑出一批高质量的位置向量作为query最后送到Transformer decoder里做精细回归。这样既保留了端到端的简洁性又把推理速度拉到和YOLO一个量级。论文里的数据很直观RT-DETR-R50在COCO上达到53.1% mAP速度是108 FPS比同等精度的YOLOv8快不少。理解RT-DETR关键要抓住三个设计混合编码器、IoU-aware query selection、去噪训练。后面逐条拆。1.2 混合编码器内尺度交互与跨尺度融合混合编码器是整个网络加速的核心。它分成两步先在每个尺度内部用自注意力捕捉全局上下文也就是所谓的内尺度交互intra-scale interaction再用跨尺度融合模块cross-scale fusion把不同分辨率的特征进一步整合。初看你可能会觉得这不就是FPN那套吗其实不一样。FPN的融合主要靠简单的加法或concatenate而RT-DETR的跨尺度融合用的是可变性注意力deformable attention让不同尺度的特征之间能够自适应地对齐和聚合。整个过程有点像把YOLO的PANet结构换成了Attention版本全局感受野保留住了但计算量却没有像标准自注意力那样随分辨率平方增长。实操中要注意混合编码器的输出是多个尺度的增强特征这些特征会同时用于query selection和classification。所以如果你改了输入分辨率或者换backbone混合编码器的参数和训练策略都要重新适应。我自己测试下来如果直接用RT-DETR的默认权重去跑一个分辨率差距很大的数据集效果会明显下降因为跨尺度注意力学到的对齐模式是针对原先的尺度分布的。1.3 IoU-aware query selection与去噪训练传统DETR的object query是一组固定学习参数训练时每个query要自己学会去找目标。RT-DETR换了个思路不再完全随机初始化query而是从编码器输出特征里选top-K个点作为query并且使用IoU-aware分支来预测每个query和对应目标的IoU分数。这样做的好处是网络一开始就知道该关注哪些位置收敛速度大幅提升而且最终输出时还可以直接用IoU分数来做排序替代NMS。去噪训练也是从DN-DETR借来的技巧。训练过程中会随机破坏一部分GT框然后让模型学习从被破坏的query里恢复出原框。这个机制的直观理解是让模型不只是靠匹配结果学还要学会“纠错”从而稳定训练过程。实际训练里去噪部分对学习率、数据增强扰动都比较敏感尤其是如果你在自定义数据集上训练GT框很小或者物体密集去噪噪声比例调太大会导致模型过度依赖GT反而影响泛化。2. 官方版训练PaddleDetection下的RT-DETR复现2.1 环境安装PaddlePaddle的坑与解决官方RT-DETR是基于PaddlePaddle的PaddleDetection实现的所以训练第一步就是装PaddlePaddle和PaddleDetection。我用的Python 3.9、CUDA 11.8环境安装命令很简单python -m pip install paddlepaddle-gpu2.5.2.post118 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html pip install paddlepaddle-gpu git clone https://github.com/PaddlePaddle/PaddleDetection.git cd PaddleDetection pip install -r requirements.txt python setup.py install这里的坑有几个PaddlePaddle的GPU版本很容易装成CPU版本需要确认import paddle; paddle.utils.run_check()能通过。另外PaddleDetection和PaddlePaddle的版本有对应关系用最新的PaddleDetection配合老PaddlePaddle会有算子兼容问题。我一开始装了paddlepaddle 2.6但PaddleDetection还是旧的直接跑就会报rpn相关算子错误后来统一到2.5.2才稳定。如果只是做CPU环境测试可以直接pip install paddlepaddle但训练基本别想了RT-DETR哪怕是最小的模型也很吃算力。建议至少8G显存才能把batch size开到2左右。2.2 数据准备与配置文件修改官方训练默认使用COCO数据集。如果你想用自己的数据集需要把标注转成COCO格式目录结构大致是这样dataset/ custom/ annotations/ instances_train.json instances_val.json train/ (图片) val/ (图片)配置文件在configs/rtdetr/rtdetr_r50vd_6x_coco.yml。打开后要改几个关键地方num_classes: 80 dataset: type: COCODataSet dataset_dir: dataset/custom class_names: [cat, dog, ...] train: data_source: ann_file: annotations/instances_train.json eval: data_source: ann_file: annotations/instances_val.jsonnum_classes是你的类数量注意COCO类别中如果是多类class_names要保持和标注文件里类别顺序一致。训练轮数和学习率策略在文件底部可以改epochs一般自定义数据集从1x12个epoch开始调但RT-DETR的调度器和数据增强量比较大我建议先用6x的训练策略跑一遍再根据验证集表现往下减。另外PaddleDetection的训练配置里有个use_gpu标志多卡训练会在后面命令行里指定不需要提前改。warmup_iters、base_lr这些参数在_base_里如果要调整学习率需要同时改optimizer里面的内容否则只改顶层base_lr不一定生效。2.3 官方训练与评估命令配置改好后训练非常直接python tools/train.py -c configs/rtdetr/rtdetr_r50vd_6x_coco.yml --eval -o use_gpuTrue--eval表示每个epoch结束跑一次验证集方便观察mAP曲线。-o可以用来覆盖配置文件里的任意参数比如-o snapshot_epoch1每1个epoch保存一次权重防止训练中途断电丢太多进度。我有一台单卡GPURT-DETR-R50配合batch size2COCO全量训练差不多要3天。自己小数据集配合预训练权重通常10个epoch左右就能看到收敛趋势。如果显存不够可以在命令行加-o batch_size1但梯度不稳定建议配合--fp16半精度训练python tools/train.py -c configs/rtdetr/rtdetr_r50vd_6x_coco.yml --amp --evalPaddleDetection的AMP开启之后显存占用能降低将近一半但我测试过某些操作符在AMP下数值不稳定比如混合编码器里的deformable attention容易出现NaN loss。解决方法是把losses里某些loss保持float32不过新手的话还是先别开等完全能复现基准再折腾。评估和导出的命令python tools/eval.py -c configs/rtdetr/rtdetr_r50vd_6x_coco.yml -o weightsoutput/rtdetr_r50vd_6x_coco/model_final.pdparams python tools/export_model.py -c configs/rtdetr/rtdetr_r50vd_6x_coco.yml -o weightsoutput/rtdetr_r50vd_6x_coco/model_final.pdparams导出后会得到output_inference/目录里面有模型和配置文件可以直接用PaddleInference推理也可以转成ONNX再转TensorRT部署。3. YOLO版训练用ultralytics训练RT-DETR3.1 为什么要在YOLO框架里训练RT-DETR官方版本训练效果自然是最准的但PaddleDetection的生态相对封闭很多习惯用YOLO系列做项目的人更熟悉ultralytics的API。另外ultralytics团队早就把RT-DETR集成进了YOLOv8的代码库可以直接用yolo train命令训练RTDETR模型数据标注格式还是YOLO格式没有任何额外转换压力。这个“YOLO版本训练”最大的优势是工程化程度高不需要看复杂的Paddle配置数据集就是一个images/和labels/文件夹标注是txt文本训练过程中自动做缓存、数据增强、学习率调度、早停和best权重保留。适合快速迭代和部署验证。当然代价是ultralytics实现和官方PaddleDetection实现有一些细节差异比如数据增强策略、loss组合系数、训练schedule不完全一致所以同样训练轮数下精度表现会有几个点的浮动。如果你最后要上生产我会建议两个版本都训练一遍YOLO版跑通流程和做快速AB官方版作为精度上限的参考。3.2 数据格式转换从COCO到YOLO格式YOLO训练需要的数据格式是每个txt文件对应一张图片每一行是一个目标class x_center y_center width height这里的坐标是归一化到0~1之间的。如果你的原始数据是COCO格式写个小脚本转一下就行我直接用一段Python处理import os import json from PIL import Image def coco2yolo(coco_json, img_dir, out_labels): with open(coco_json, r) as f: data json.load(f) id_to_name {img[id]: img[file_name] for img in data[images]} cat_id_map {cat[id]: i for i, cat in enumerate(data[categories])} os.makedirs(out_labels, exist_okTrue) for ann in data[annotations]: img_id ann[image_id] file_name id_to_name[img_id] label_path os.path.join(out_labels, file_name.rsplit(., 1)[0] .txt) img_path os.path.join(img_dir, file_name) img_w, img_h Image.open(img_path).size x, y, w, h ann[bbox] x_center (x w / 2) / img_w y_center (y h / 2) / img_h w / img_w h / img_h cat_id cat_id_map[ann[category_id]] with open(label_path, a) as out: out.write(f{cat_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n)注意COCO的bbox格式是[x, y, width, height]左上角原点转换时一定记得归一化。标签txt文件必须和图片同名且放在labels/下。ultralytics训练时的数据集配置是# dataset.yaml path: D:/projects/rtdetr_yolo/dataset train: images/train val: images/val names: 0: cat 1: dognames里的类别索引必须和txt里的第一列严格对应。类别数说是无所谓但超过50个类时names列表要完整否则训练报错。3.3 用yolo命令训练RT-DETRYOLO版本训练RT-DETR非常简单先安装ultralytics库pip install ultralytics然后直接yolo train datadataset.yaml modelrtdetr-l.pt epochs100 imgsz640 batch8第一次运行会从官方权重库下载rtdetr-l.pt作为预训练权重。model参数也可以指定为rtdetr-l.yaml表示从零开始训练不加载预训练权重。实际中除非你的数据集和COCO差异极大否则强烈建议用预训练权重微调收敛速度和最终精度都要好很多。如果你习惯用Python脚本可以使用ultralytics的APIfrom ultralytics import RTDETR model RTDETR(rtdetr-l.pt) model.train(datadataset.yaml, epochs100, imgsz640, batch8, projectruns/rtdetr, nameexp1)这里有几个参数很重要batch根据显存调整8G显存建议batch416G可以batch8。imgszRT-DETR原始输入是640如果你的目标较小可以调到800或960但显存和训练时间会成倍增加。lr0初始学习率默认是0.01自定义小数据集时经常需要降低到0.002~0.005否则预热阶段就会有较大震荡。在训练日志里可以看box_loss、cls_loss、dfl_loss和mAP50等指标RT-DETR的loss里没有DFL我记得日志里是GIoU和Class损失不过ultralytics做了统一接口输出字段基本都是类似的。训练结束后模型会保存在runs/rtdetr/exp1/weights/best.pt直接用model.predict做推理或者用导出的ONNX做服务部署。3.4 两种训练路径的对比我用同一个自定义数据集分别跑了官方版和YOLO版数据集规模约8000张图20个类训练100个epoch。我的感受是对比项官方PaddleDetection版ultralytics YOLO版环境配置复杂度较高依赖Paddle生态低pip安装即可数据标注格式COCO格式转来转去直接用YOLO txt格式训练速度同batch略快一点后端优化好相差不大但显存占用略高默认精度略高推理时NMS策略更细致精调后也能接近默认差1~2个点部署便利性导出PaddleInference/TensorRTONNX/TensorRT/NCNN都支持很顺自定义数据友好度需要改yamljson只需要一个dataset.yaml如果你的项目原本就基于YOLO数据流建议直接用ultralytics版本快速验证效果如果追求精度上限或需要和Paddle产线集成再上官方版做一次基准。4. 训练RT-DETR时的常见坑与疑难排查4.1 显存溢出大分辨率、大batch怎么取舍RT-DETR的Transformer decoder部分显存开销比较大尤其在推理阶段和YOLO这种纯卷积网络完全不同。我在8G显存的GPU上imgsz640、batch8训练rtdetr-l直接OOM。解决办法有三个方向降低batch size到2或4开启梯度累积ultralytics直接设置batch4配合accumulate4效果相当于batch16但训练时间会拉长使用ampTrue混合精度训练RT-DETR在AMP下基本能保持精度显存可以降低约40%。如果你用的是官方PaddleDetection版感觉显存不够还可以考虑换小backbone比如rtdetr_r18vd_5x_coco.yml一样能跑只是精度低一些。YOLO版则可以直接用rtdetr-l.pt切换到rtdetr-x.pt显存需求会显著增加不建议小卡用户直接上x。4.2 损失函数调整GIoU、L1和分类损失的权重平衡RT-DETR的损失函数包含三部分分类损失的cls_loss、回归的L1 loss和GIoU loss。官方权重默认是cls_loss1、L1_loss5、GIoU_loss2。这个比例对大多数通用目标检测是合适的但有几种例外情况需要手动调整小目标很多L1 loss对小目标的位置误差比较敏感权重不变的话会过度关注小目标的边界导致大目标定位偏差。我写过官方配置文件把L1权重从5降到3GIoU权重升到2.5小目标的Recall提升比较明显。密集场景、物体互相遮挡GIoU权重可以提升到3以上让模型更重视框之间的重叠关系。类别不均衡如果某些类样本很少分类损失权重可以适当调高但不要直接调节点权重优先考虑用focal loss或者调整采样策略。在ultralytics里改权重要小心它把RT-DETR的loss挂在model.loss里想改只能改源码或者用回调函数。实际项目中我一般不动默认权重先看日志里的各类loss走势再决定要不要介入。4.3 训练不收敛学习率、数据增强与BN层的那些事我碰到最多的问题是无脑训练导致前50个epoch完全学不动或者loss直接发散。原因基本都是学习率或数据增强不匹配。官方版RT-DETR默认是在COCO上预训练过的使用6xschedulebase_lr0.0001warmup 1000步。如果你换到自定义数据集数据量只有几千张这个学习率会偏大导致一开始loss就飞。建议先用官方相同的学习率训练5个epoch看看如果loss上下跳动严重就调低到0.00002再试。YOLO版默认初始学习率是0.01配合cos_lrTrue衰减。但RT-DETR的Transformer模块对学习率比CNN敏感我试过几次降到0.005收敛更稳定。如果你用的是rtdetr-x这种大模型建议初始学习率直接乘以0.5。另外无论哪个版本都要确保输入图片做了归一化到0~1的操作。RT-DETR的backbone对输入均值方差有要求PaddleDetection内部会做normalizeultralytics库里也自动处理了。但如果你用ONNX导出后自己写预处理代码务必保持和训练一致很多部署生效不佳的案例都出在这个环节。4.4 推理部署从PyTorch到ONNX再到TensorRTYOLO版训练完部署相对简单yolo export modelruns/rtdetr/exp1/weights/best.pt formatonnx simplifyTrue导出的ONNX可以直接用ONNXRuntime跑也可以转成TensorRT engine加速。RT-DETR的ONNX导出整体比较顺利只有一点要注意dynamic批量维度默认关闭如果你的服务需要动态batch导出时加上dynamicTrue但TensorRT要先做优化。官方版导出PaddleInference再转ONNX也支持命令我前面提过。转好ONNX后TensorRT用trtexec --onnxmodel.onnx --saveEnginemodel.engine --fp16编译即可。实测RT-DETR转TensorRT之后在3080上单张图片推理时间能压到5ms以内比PyTorch原始模型快3倍以上和YOLOv8x的推理速度已经很接近。部署时还有个细节RT-DETR默认输出是[num_queries, 6]其中6个值是[x1, y1, x2, y2, score, class]已经不需要NMS。有些推理框架不了解这一点还硬是用NMS后处理反而把速度拖慢了。YOLO版本导出的模型会有(1, 300, 6)的输出这里的300就是query数量直接取置信度大于阈值的框就行。最后再分享一个小技巧当你想在自定义数据集上快速看效果时先用YOLO版训练100个epoch再把训练好的权重转成ONNX在官方PaddleDetection的config里加载不了。反过来如果你想用官方版做最终模型可以把YOLO版训练好的模型权重作为预训练不行结构有差异。最靠谱的方式是用官方COCO预训练权重在官方框架里按你的数据微调或者用YOLO版预训练权重在YOLO框架里微调两者互不干扰。我个人现在习惯是先用YOLO版快速跑通流程和验证指标确认思路没问题后再花时间用官方版做一次终版训练这样时间和算力都能最大化利用。
返回列表