1. 为什么DAMO-YOLO值得单独拿出来聊
目标检测这个圈子,过去五六年基本是YOLO系列的天下。从YOLOv3开始,每隔一段时间就有新版本刷榜,大家一边追新一边吐槽:精度上去了,速度掉下来;速度保住了,小目标又漏检。工业界真正落地的时候,往往不是选那个榜单第一的模型,而是选那个在自家数据上“够准、够快、够好部署”的模型。
阿里达摩院开源的DAMO-YOLO,就是在这个背景下进入视野的。它没有走“堆参数换精度”的老路,而是从网络结构搜索、重参数化、训练策略三个方向同时下手,在COCO上做到了同精度下更快、同速度下更准。我第一次跑通它的推理脚本时,最直观的感受是:这玩意儿在T4上跑640分辨率,吞吐量确实比同级别的YOLO变体要舒服,而且导出ONNX之后部署链路很干净。
这篇文章不打算复述论文,而是从一个实际使用者的角度,把DAMO-YOLO的核心设计、环境搭建、训练调参、部署落地、踩坑记录完整讲一遍。适合两类人看:一类是想找一个能直接上生产的检测模型,另一类是好奇它到底“超越”在哪里、值不值得从YOLOv5/v8迁移过来。全文基于我自己的实操记录和常见工程实践补充,参数和步骤都可以直接抄。
2. DAMO-YOLO整体设计思路拆解
2.1 它到底“超越”在哪个维度
很多人看到“超越一众YOLO”第一反应是精度又刷高了。实际上DAMO-YOLO的卖点更偏向精度-速度-部署成本这个三角的平衡。官方给出的对比里,DAMO-YOLO-T在COCO上约42% AP,推理速度比同精度YOLOv5-s快不少;DAMO-YOLO-S在约46% AP时,速度依然压着同级别对手。这个“同精度更快”比“同速度更准”在工程上更有价值,因为产线往往卡的是延迟和吞吐。
它做到这一点的核心手段有三个:MAE-NAS骨干搜索、RepGFPN颈部结构、ZeroHead检测头。这三个词听起来唬人,拆开看其实都是很务实的工程选择。
2.2 MAE-NAS:不靠人工堆叠,靠搜索找骨干
传统YOLO的骨干(Backbone)基本是人工设计的,比如CSPDarknet。人工设计的问题是,你很难穷举所有通道组合和层间连接方式。DAMO-YOLO用MAE-NAS(一种基于最大熵原理的神经架构搜索方法)去搜骨干,搜索空间里包含卷积类型、通道数、层数、连接方式。搜出来的结构在同等FLOPs下特征提取能力更强。
这里有个关键点:NAS搜出来的结构往往“不规则”,不像人工设计那样整齐。但DAMO-YOLO把搜出来的结构做了工程化整理,保证它能在常见推理引擎上跑得动。这一点很重要,我见过不少NAS模型论文精度漂亮,但导出ONNX一堆算子不支持,根本没法用。
2.3 RepGFPN:把特征融合做“重”再“轻”回来
FPN+PAN是YOLO系列的标配,负责把不同尺度的特征融合起来。DAMO-YOLO用的是RepGFPN,核心思想是训练时用多分支、多尺度的重结构,推理时通过重参数化合并成单分支。训练阶段多分支能提升特征表达能力,推理阶段合并后不增加延迟。
这个思路和RepVGG一脉相承。实际用下来,RepGFPN对小目标检测的提升比较明显,因为多尺度融合更充分。但要注意,重参数化对训练显存有一定要求,batch size太小的时候收益会打折。
2.4 ZeroHead:把检测头做到极简
检测头(Head)是最后输出分类和框回归的地方。DAMO-YOLO的ZeroHead设计理念是“解耦但轻量”,分类分支和回归分支分开,但每个分支的卷积层数压到很低。配合前面强力的骨干和颈部,检测头不需要太复杂就能出好结果。
这个设计带来的直接好处是推理时延低。检测头往往是推理瓶颈之一,尤其是高分辨率输入时。ZeroHead把这块的成本压下来了。
2.5 为什么这套组合值得关注
把这三个模块放一起看,DAMO-YOLO的思路很清晰:骨干负责强特征,颈部负责好融合,头部负责快输出。每一块都在“够用”的前提下追求效率,而不是无脑堆。这种设计哲学对工业落地非常友好,因为产线要的不是论文里的极限指标,而是稳定、可预测、好部署。
3. 环境搭建与快速跑通实操
3.1 硬件与基础环境选择
我实测用的是一张T4(16G显存)和一张1080Ti(11G显存)。T4适合推理和中等batch训练,1080Ti训练时batch size要压小一点。系统用Ubuntu 20.04,CUDA 11.3,cuDNN 8.2,这套组合在T4上比较稳。
Python环境建议3.8或3.9,太新的版本有些依赖包会出问题。我习惯用conda建独立环境,避免污染系统Python。
conda create -n damoyolo python=3.8 conda activate damoyoloPyTorch版本选1.10到1.12之间比较稳,对应CUDA 11.3。官方仓库对PyTorch版本有一定要求,太新或太旧都可能遇到算子不兼容。
pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 -f https://download.pytorch.org/whl/torch_stable.html3.2 拉取代码与安装依赖
从官方仓库拉代码,注意分支选择。我一般用主分支,但如果你要复现论文指标,建议切到对应release tag。
git clone https://github.com/tinyvision/DAMO-YOLO.git cd DAMO-YOLO pip install -r requirements.txt依赖里比较关键的是pycocotools、onnx、onnxsim、tensorrt(如果要做TRT部署)。pycocotools在Windows上编译经常出问题,建议在Linux下搞。
安装完后跑一下自带的demo,确认环境没问题:
python tools/demo.py image -f configs/damoyolo_tinynasL20_T.py --path assets/000000000139.jpg --conf 0.5 --infer_size 640 640如果能看到检测结果图输出,说明基础环境通了。
3.3 数据集准备:COCO格式与自定义数据
DAMO-YOLO默认用COCO格式。如果你有自己的数据,需要转成COCO的json标注。我常用labelme或CVAT标完再转,转换脚本网上很多,但要注意类别id从1开始还是从0开始,这个坑我踩过,导致训练时loss一直不降。
目录结构建议这样组织:
datasets/ mydata/ annotations/ instances_train.json instances_val.json train/ xxx.jpg val/ xxx.jpg然后在config里改dataset相关路径。注意num_classes要和你的类别数一致,改错了会报维度不匹配。
3.4 配置文件关键参数解读
DAMO-YOLO的config是Python文件,不是yaml。以damoyolo_tinynasL20_T.py为例,几个关键参数:
img_size:训练输入尺寸,默认640。显存不够可以降到512,但小目标会受影响。batch_size:T4上T版本可以到32,S版本建议16。epochs:默认300,实际微调100左右就够。lr:初始学习率,默认0.01,微调时建议降到0.001。num_classes:必须和数据集一致。
注意:改完config后,最好先跑1个epoch看看loss曲线,确认没有nan或爆炸再正式训。
4. 训练调参与核心环节实现
4.1 从预训练权重开始微调
除非你有几十万张标注数据,否则不要从零训。官方提供了T/S/M/L各版本的预训练权重,下载后放到pretrained/目录,在config里指定pretrained_model路径。
微调时我一般冻结骨干前几层,只训颈部和头部,训几十个epoch后再解冻全部。这样收敛快,也不容易过拟合小数据集。
# 在config里可以设置冻结层 model = dict( backbone=dict( frozen_stages=2, # 冻结前2个stage ), )4.2 损失函数与正负样本分配
DAMO-YOLO用的损失包括分类损失(Quality Focal Loss)、回归损失(GIoU Loss)和DFL(Distribution Focal Loss)。正负样本分配用的是SimOTA的变体。这套组合在YOLOX里已经被验证过,DAMO-YOLO做了适配。
实际训练时,如果发现正样本太少导致召回低,可以调center_radius和topk参数。但这两个参数比较敏感,建议一次只调一个,观察验证集AP变化。
4.3 数据增强策略
默认开启了Mosaic、MixUp、HSV增强、随机翻转。Mosaic对小目标提升明显,但训练后期建议关闭,让模型适应真实分布。我一般在前80% epoch开Mosaic,后20%关掉。
# 关闭Mosaic的epoch阈值 mosaic_epoch = 240 # 总300epoch时,240之后关闭实操心得:如果你的数据集里小目标特别多,Mosaic可以一直开着;如果都是大目标,早点关掉反而更好。
4.4 训练过程监控与日志解读
训练日志里重点看几个指标:loss_cls、loss_iou、loss_dfl、lr、验证集AP。正常情况loss_cls应该稳步下降,如果震荡剧烈,可能是学习率太大或batch size太小。
我习惯用TensorBoard看曲线:
tensorboard --logdir=work_dirs/如果验证集AP在某个epoch后不再上升甚至下降,说明过拟合了,可以早停或加正则。
4.5 多卡训练与显存优化
如果你有多张卡,可以用torch.distributed启动:
python -m torch.distributed.launch --nproc_per_node=2 tools/train.py -f configs/xxx.py单卡显存不够时,可以开混合精度(AMP),DAMO-YOLO默认支持。开了AMP后显存能省30%左右,速度也有提升。但要注意,AMP有时会导致loss nan,遇到这种情况把loss_scale调小或关掉AMP。
5. 模型导出与部署落地
5.1 导出ONNX及常见坑
训练完的模型要部署,第一步是导出ONNX:
python tools/converter.py -f configs/xxx.py -c weights.pth --batch_size 1 --img_size 640 640导出时常见的坑:
- 动态轴设置:如果要做变分辨率推理,需要设置dynamic_axes,否则ONNX固定输入尺寸。
- 算子不支持:某些自定义算子导出后ONNX不认,需要用onnxsim简化。
- 输出节点名:导出后确认输出节点名,后面TRT或推理引擎要用。
python -m onnxsim damoyolo.onnx damoyolo_sim.onnx5.2 TensorRT加速实测
在T4上,我把DAMO-YOLO-T导出TRT FP16,640分辨率,batch=1时单帧推理约3ms左右,batch=8时吞吐能到200+FPS。这个数据在同精度模型里相当能打。
TRT转换步骤:
trtexec --onnx=damoyolo_sim.onnx --saveEngine=damoyolo.engine --fp16 --workspace=4096注意:TRT版本要和CUDA、cuDNN匹配,版本不对会报各种奇怪的错。我一般用TRT 8.x配CUDA 11.3。
5.3 多路视频流推理的算力估算
有人问T4 1080p25帧用TRT跑640分辨率能支持多少路。粗算一下:单帧3ms,理论单卡能跑300+FPS。1080p25帧每路需要25FPS,所以理论上限是12路左右。但实际要考虑解码、预处理、后处理开销,一般打对折,6路左右比较稳。如果开batch推理,效率还能再高一些。
| 场景 | 单帧延迟 | 理论路数 | 实际建议路数 |
|---|---|---|---|
| T4 FP16 batch=1 | ~3ms | 12 | 6-8 |
| T4 FP16 batch=8 | ~2ms/帧 | 15+ | 8-10 |
| 1080Ti FP16 batch=1 | ~5ms | 8 | 4-5 |
5.4 边缘设备部署注意事项
如果要在边缘设备(如Jetson系列)上跑,建议用T版本,输入降到416或320。导出时用FP16甚至INT8量化。INT8量化需要校准集,校准集要从你的实际数据里采样,不能用COCO随便凑,否则精度掉得厉害。
6. 常见问题与排查技巧实录
6.1 训练不收敛或loss nan
这是最常见的问题。排查顺序:
- 检查学习率是否太大,先降到0.001试试。
- 检查数据标注是否有问题,比如框超出图像边界、类别id错误。
- 检查是否有空标注图片,空标注会导致某些loss计算出nan。
- 关掉AMP试试,排除混合精度问题。
6.2 验证集AP远低于训练集
典型过拟合。解决办法:加数据增强、加正则(weight decay)、减小模型规模、早停。如果数据集本身很小(几千张),建议直接用预训练权重做微调,不要解冻全部层。
6.3 导出ONNX后推理结果不对
先确认预处理是否一致。DAMO-YOLO训练时的归一化参数是mean=[0,0,0], std=[1,1,1],但有些部署代码默认用ImageNet的mean/std,这就导致输入分布不对。另外确认letterbox的填充值,训练时用的是114,部署时也要用114。
6.4 TRT推理速度不如预期
检查是否用了FP16,是否开了cudaGraph,workspace是否够大。另外,TRT首次推理有构建开销,要warmup几次再测。如果batch=1速度上不去,试试batch=4或8,吞吐会明显提升。
6.5 小目标漏检严重
DAMO-YOLO本身对小目标做了优化,但如果你的数据里小目标占比极高,可以:提高输入分辨率(640→800)、在config里调整anchor或正样本分配参数、增加小目标的数据增强(如小目标复制粘贴)。
| 问题现象 | 可能原因 | 排查方向 |
|---|---|---|
| loss nan | 学习率过大/AMP问题/标注异常 | 降lr、关AMP、查标注 |
| AP不升 | 过拟合/数据量不足 | 加增强、早停、冻结层 |
| ONNX结果错 | 预处理不一致 | 对齐mean/std/letterbox |
| TRT慢 | 未开FP16/未warmup | 开FP16、warmup、调batch |
| 小目标漏检 | 分辨率低/正样本少 | 提分辨率、调分配参数 |
6.6 一些独家避坑技巧
- config改完先跑1个epoch:别一上来就训300epoch,先确认能跑通、loss正常。
- 权重保存频率别太高:每10个epoch存一次就够,存太勤磁盘很快满。
- 验证集要独立:别从训练集里随便抽几张当验证集,分布不一致会导致AP虚高。
- 导出前先eval:确认PyTorch推理结果正常再导出,否则出了问题不好定位是训练问题还是导出问题。
7. 它适合哪些场景,不适合哪些场景
DAMO-YOLO适合对延迟敏感、需要快速部署、数据量中等的场景,比如工业质检、安防监控、自动驾驶感知的辅助模块。它的部署链路成熟,ONNX和TRT支持好,这是很多学术模型比不了的。
不太适合的场景:需要开放词汇检测(它不支持)、需要实例分割(它只做检测)、数据量极小且没有预训练权重的领域(微调效果有限)。如果你要做开放词汇检测,得看Grounding DINO那类模型;要做分割,得看YOLOv8-seg或Mask R-CNN。
我个人在实际项目里的体会是,DAMO-YOLO最大的价值不是某个指标刷了多高,而是它把“搜出来的结构”真正做成了能落地的工程件。很多NAS模型死在部署这一步,DAMO-YOLO没死,这就够了。后续如果要做模型压缩,可以在这个基础上继续剪枝或量化,空间还很大。