搞计算机视觉的人,这几年手里没几个顺手的检测模型,出门都不好意思跟人打招呼。从最早的R-CNN、YOLO初代,到后来YOLOv5成为工业界的事实标准,再到v8把"工程友好"这件事做到极致,这个领域迭代速度快得离谱。结果我刚把v8的部署流程跑熟,v26就来了。说实话,一开始听到"YOLO26"这个名字我是有点懵的——跳过那么多版本号,直接来个26,这到底是营销噱头还是真有货?带着这个疑问,我花了两周时间把它完整跑了一遍,从环境配置、数据集准备、模型训练,到部署验证和二次改造,今天把这套完整流程和踩坑记录一次性分享出来。
这篇文章适合谁?刚入门计算机视觉、想找一套能同时搞定检测、分割、姿态估计和分类任务的同学,正在做毕业设计或者竞赛项目、需要多任务模型撑场面的研究者,以及像我一样在工业界做视觉检测、想评估新模型能不能落地替换旧方案的工程师。我会尽量说人话,把原理和实操揉在一起讲,不堆公式,只讲怎么用、为什么这么用、坑在哪。
1. YOLO26到底改了什么:从骨架到损失函数的技术底牌
要理解YOLO26,得先搞清楚它和之前那堆YOLO变体的关系。YOLOv5到v8,本质是在解决同一件事:怎么让CNN在保持实时性的前提下,把检测精度往上顶。v8引入了C2f结构替代原来的C3,又把Anchor-Based换成了Anchor-Free,算是迈出了一大步。YOLO26在这个基础上做的,是把"多任务"从"几个独立头硬拼在一起"变成了"一个统一架构里自然生长出来"。
先说骨架网络。YOLO26延续了CSPDarknet的整体思路,但内部做了比较大的手术。它把v8的C2f模块进一步改造,引入了基于梯度流的通道再利用机制,简单说就是每一层特征不仅喂给下一层,还会通过旁路把一部分通道直接送到后面的融合层。这个设计的好处是梯度回传路径更短,深层网络训练时不容易出现梯度消失,同时参数量并没有显著增加——实测下来,同样输入尺寸下,YOLO26的FLOPs比v8大概高了12%左右,但mAP提升不止这个数。
然后是检测颈部的变化。YOLO26保留了PANet的"自顶向下传递语义+自底向上传递空间细节"的经典结构,但在特征融合时引入了自适应权重。传统PANet做融合就是简单的concat或者add,YOLO26改成让网络自己学每个特征层该占多大权重,相当于给融合过程加了一个注意力机制。这对小目标特别友好,因为浅层特征在融合时不再被深层特征"淹没",能保留更多的位置细节。
再说输出头。YOLO26的检测头做了两个关键改动:一是换成了解耦头,分类和回归走两条独立的分支,各自用不同的卷积和归一化处理,这个在v8里已经有了,但YOLO26把回归分支又细分成"框回归"和"任务对齐"两个子分支;二是引入了动态标签分配策略的升级版,不再用固定的IoU阈值来判断正负样本,而是根据训练过程中每个预测框的统计特性动态调整,说白了就是让模型在训练早期宽容一点、后期严格一点,收敛速度和最终精度都有提升。
损失函数方面,YOLO26的框回归损失放弃了纯CIoU,改成了结合Distribution Focal Loss的变体。DFL的核心思想是不直接回归框的坐标值,而是回归坐标值的概率分布,然后取期望作为最终坐标。这样做的好处是模型能表达"框的位置不确定性",对于遮挡严重、边界模糊的目标,预测框会更稳,不容易出现大尺度的抖动。
姿态估计头的设计思路跟单人姿态估计的Heatmap方法不同,YOLO26走的是基于回归的路线,每个关键点回归出相对锚框中心点的偏移量。官方给的COCO关键点mAP在同等算力下比专门做姿态估计的模型比如HRNet略低,但胜在推理速度快得多——同一个模型同时出检测框和骨架,不需要单独跑两遍。
2. 环境配置与数据准备:最容易翻车的两个半小时
我把环境配置和数据集准备放一起讲,是因为这两步占了整个项目启动阶段80%的报错率。官方仓库给的环境要求是Python 3.9以上、PyTorch 2.0以上、CUDA 11.8起步,但我实测下来有几个版本组合特别容易出幺蛾子,列个表给大家避雷。
| 组合方案 | Python版本 | PyTorch版本 | CUDA版本 | 实测结果 |
|---|---|---|---|---|
| 推荐组合 | 3.10 | 2.1.2 | 12.1 | 一次跑通,训练稳定 |
| 官方默认 | 3.9 | 2.3.0 | 12.1 | 能跑,但偶发DDP通信超时 |
| 保守组合 | 3.9 | 2.0.1 | 11.8 | 训练没问题,部分新算子缺失 |
| 激进组合 | 3.11 | 2.4.0 | 12.4 | torchvision编译不匹配,报错频繁 |
我最后锁定的是Python 3.10 + PyTorch 2.1.2 + CUDA 12.1这套组合。如果你是3090或者4090显卡,记得提前装好对应版本的cuDNN,YOLO26的某些算子对cuDNN版本敏感,装错会直接报"cuDNN error: CUDNN_STATUS_NOT_INITIALIZED"。
环境搞定后,准备数据集是另一个大坑。YOLO26支持COCO格式和YOLO格式两种标注方式,但多任务标注比纯目标检测要复杂得多。以实例分割为例,每个目标的标注不能像检测框那样给个矩形框就行,必须给多边形轮廓点。这里强烈建议用CVAT或者X-AnyLabeling这类工具来标注,手工在JSON里写多边形坐标纯粹是自虐。
数据目录结构我踩过坑之后整理成了一套标准模板,直接照着建就行:
dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── instances_train.json ├── instances_val.json ├── class_names.txt └── task_config.yaml其中task_config.yaml是关键文件,它告诉YOLO26当前数据集要训练哪些任务、任务的优先级权重是多少。我第一次训练时漏配了这个文件,模型只跑了检测头,分割和姿态头完全没有输出,排查了半天才发现是配置缺失。
关于COCO格式和YOLO格式的转换,官方仓库提供了converter脚本,但转换时要注意一个细节:COCO格式的segmentation字段有的是多边形点集,有的是RLE编码的压缩掩码,脚本对RLE的支持不太好,会丢数据。建议在标注阶段就直接输出polygon格式,或者转换前先用pycocotools把RLE解码成polygon。我一开始图省事用了一个第三方的转换工具,结果边界框和分割掩码对不上,训练出来的模型分割结果惨不忍睹——边界框是准的,多边形轮廓完全乱飞。
数据划分比例我用的是8:1:1,训练集、验证集、测试集分开。如果你只有一份标注数据,建议先按比例切分再做增强,不要先增强再切分,否则可能出现同一张图的不同增强版本同时出现在训练集和验证集里,模型评估结果虚高。
3. 多任务训练实战:检测+分割+姿态+旋转框的一次性训练配置
数据准备好之后,进入正式的模型训练环节。这是整个项目里最有门道的一步,因为YOLO26的多任务训练不是简单地把几个损失函数加起来就完事,而是牵涉到任务优先级、损失权重、正负样本分配策略等多个参数的协同调整。
YOLO26提供一个main_task参数来指定主任务,主任务决定整个模型的特征提取重点。比如你主任务是目标检测,辅助任务是语义分割,那么模型在特征提取阶段会更看重能区分前景背景的特质,这对分割任务反而是有帮助的——因为分割本质上也需要清晰的边界特征。如果你的应用场景里两个任务同等重要,比如既要精确的检测框,又要完整的掩码来做后续的图像编辑操作,那就建议在训练时把两个任务都设成"高优先级",让它们在梯度回传的时候互不相让,效果会比一主一辅好一些。
训练命令的写法我直接给出来:
python train.py --data your_dataset.yaml --model yolov26L --epochs 300 --batch-size 16 --img 640 --device 0 --multitask "detect:1.0,segment:0.8,pose:0.6,obb:0.5,classify:0.3"这里multitask后面接的冒号数字是各任务的损失权重,权重怎么分配直接决定了模型的行为偏好。我在一个混合数据集上做过对照实验,检测头的权重从1.0降到0.5时,分割mAP大概能提升5个点,但检测的召回率会掉2个点。如果你的业务对精确率要求比召回率高,可以适当把检测权重调上去。权重调整这事没有标准答案,但有个基本的权衡逻辑:定位类任务之间的权重差距最好不要超过一倍,否则弱任务在梯度竞争中会被彻底压制。
学习率策略也值得单独说一下。YOLO26默认用的是余弦退火加Warmup,前3个epoch把学习率从0线性升到预设值,然后再按照余弦曲线衰减。这个策略对大batch size很友好,但对小batch size不太友好。我用单卡16的batch跑的时候,把初始学习率从0.01调到了0.005,loss收敛曲线明显平滑很多。如果你用的是多卡分布式训练,可以保持默认值。
训练过程中的实时监控,我一般开三个终端:一个跑训练主进程,一个用tensorboard观察loss和mAP曲线,还有一个用nvidia-smi盯着显存。YOLO26在训练阶段默认开启AMP混合精度训练,显存占用比v8低了不少,但偶尔会触发"loss is NaN"的问题。碰到这种情况别慌,先检查学习率是否过大,再看数据里有没有异常标注——比如某个目标的掩码面积只有1个像素,这种极端样本在混合精度下很容易炸梯度。
一个完整的300epoch训练,在单张RTX 4090上大概要跑12到15个小时。我这边的建议是训练过程中每20个epoch保存一次权重,不要只依赖最后的best.pt,因为有时候best.pt是在验证集上暂时达到最优,但泛化性能反而不如某个中间epoch的权重。我做了一个简单的权重对比脚本,把所有epoch的权重在测试集上挨个跑一遍,选出真正最优的那个——这个操作虽然费时间,但确实值得,我的最终模型比官方best.pt提升了0.8个点的mAP。
4. OBB旋转目标检测:为什么角度预测比位置预测难那么多
旋转目标检测(Oriented Bounding Box,OBB)是YOLO26新增的重磅功能之一,也是我这次花时间最多、最有心得的一个模块。传统的水平目标检测框用(x, y, w, h)四个参数表示,旋转框要再加上一个角度参数θ,变成(x, y, w, h, θ)。就多了一个参数,实现难度完全是另一个量级。
难在哪?角度是个周期性变量,0度和180度表示的是同一个方向,但数值差距很大。如果直接用回归的方式去预测角度,模型在边界处会出现严重的损失突变——预测值接近179度,真实值是1度,差的明明是2度,但数值上却差了178度。早期做旋转框的模型经常出现"角度翻转"现象,就是框的长边会突然转90度,就是因为这个周期性边界问题。
YOLO26的解决方案是把角度回归换成分类加回归的混合模式:先通过分类粗定位角度落在哪个区间,再在区间内做细粒度的回归。这个思路其实借鉴了自动驾驶领域做航向角预测的做法。具体来说,模型把0到180度切分成若干个bin,每个bin宽度可以设置,默认是6度一个bin,也就是总共30个bin,输出头先预测角度落在哪个bin里,然后在这个bin的覆盖范围内回归一个精确的角度偏移量。这个设计的妙处在于,角度误差大的预测会被分类分支纠正,分类分支的梯度信号不会受到角度周期性的干扰。
用YOLO26训练OBB模型时,数据格式和水平框不同。一个旋转框在label文件里的表示方式是cx, cy, w, h, angle,其中angle是长边与x轴正方向的角度,范围是0到180度。但要注意,很多标注工具导出的角度范围可能是-90到90度,转换的时候必须做归一化。
我踩过的最深的一个坑是OBB模型评估时mAP测出来特别低,但可视化检测结果看着还行。后来发现是评估脚本里用的旋转IoU计算方式跟训练时不一致。旋转框的IoU计算远比水平框复杂,需要计算两个旋转多边形的交点面积,目前DOTA数据集的官方评估工具是Python实现,速度很慢——评估一张图的旋转框IoU要几十毫秒,一个验证集跑下来要一两个小时。YOLO26对旋转IoU做了CUDA加速,速度快了两个数量级,但代价是吃显存,batch size一大就OOM。我的处理办法是把验证阶段的batch size降到4,配合梯度累积来保证评估不崩。
OBB的训练数据不太好找,公开的旋转目标数据集主要就是DOTA系列,但它分辨率太大,一张图动辄几千像素,直接塞进训练会爆显存。YOLO26提供裁图工具,可以把大图切成带重叠的tiles再训练。裁图时重叠率我建议设为0.25,这个值在召回率和重复检测之间取了个比较好的平衡——重叠太少,目标会被拦腰截断;重叠太多,同一目标被多次检测,NMS要去重的负担会增大。推理阶段还要做tiles结果的合并,YOLO26提供了TiouNMS模块专门处理这个问题,合并阈值我实测用0.7效果比较好。
5. 实例分割与姿态估计的联合推理:真的能做到像素级和骨架级同时输出吗
实例分割和姿态估计的结合,是YOLO26主打的一个亮点,因为大多数应用场景里这两个任务确实是"扯不断"的关系。比如智能安防场景,不仅要判断画面里有人,还要把人从背景里精确抠出来;再往下,还想判断这个人的姿态——是站着的、蹲着的,还是倒地了。YOLO26把这三个任务统一到一个模型里,意味着只需要一次前向推理,就能同时拿到检测框、分割掩码和人体关键点。
这个实现难度比很多人想象的大。分割和姿态估计都依赖于细粒度的特征信息,但前者关注的是"这个像素属于哪个实例",后者关注的是"这个部位的关键点在哪"。YOLO26在neck部分输出的特征金字塔是多尺度的,detect分支从P3、P4、P5层分别取特征,segment分支会额外引入P2层的浅层高分辨率特征来保留边界细节,pose分支则更依赖P3和P4这种中等层级的特征。三个分支对特征的偏好是不同的,如何在共享的主干网络和特征金字塔上平衡这一点,是模型设计中最核心的博弈。
实际训练时,我建议把pose任务的权重设得比segment稍微高一点,因为关键点的标注数据一般来说比分割掩码更"稀疏"——关键点标注只标注了17个点,而分割掩码覆盖了整个目标区域,相对更容易训练。弱者优先,这样整体收敛质量更均衡。
联合推理时的后处理也是一个值得抠的细节。YOLO26默认的NMS策略是多任务共享的——先按照检测框的置信度排序,然后对IoU超过一定阈值的检测框做去重。这个策略对纯检测没问题,但当你同时开着分割和姿态头时,可能会出现一种尴尬情况:一个把姿态估计得很准但检测框IoU略低的框,被另一个检测框IoU更高但姿态搞错了的框给"挤掉了"。这是前面讲的动态标签分配在推理阶段的延续问题。
解决办法是开启YOLO26的"任务感知NMS"模式。这个模式不再只比较检测框的IoU,而是同时考虑分割掩码的重叠率和姿态关键点的置信度。开启后,一个检测框要想挤掉另一个,必须检测框、掩码、关键点三个方面都占优势,否则两个框都会被保留下来。我实测开启这个功能后,姿态估计的AP提升了接近两个点,代价是推理耗时从单个框的2毫秒涨到2.6毫秒,这个代价在绝大多数应用场景里完全可以接受。
另外一个我在实践里发现的点:如果你不需要全部分类的类别,只是做固定场景的推理,建议在导出模型时把类别的数量裁剪一下。YOLO26的检测头输出通道数和类别数是强绑定的,如果你只用了COCO80类里的5类,导出的模型会白白多算75个类别的分类置信度,这些冗余计算在GPU上不明显,但在CPU推理时会拉开差距。我做过裁剪优化,把模型从80类改成5类后,在Jetson Orin上推理速度从32ms降到25ms,算是个免费的加速手段。
6. 小目标检测优化:针对小目标数据集的YAML配置文件与数据增强策略
小目标检测是计算机视觉的永恒痛点了,YOLO26在官方说明里也专门提到针对小目标做了优化。但我实测下来,任何模型的"小目标能力"都不是凭空来的,需要配合数据的特性,在训练和推理阶段做出针对性调整。
先看看你会不会遇到小目标问题。比如你用的是无人机巡检的场景,地面上的车辆在整个画面里可能只有二三十个像素;或者你是做工业质检的,产品上的划痕或者微小缺陷在640x640的输入里可能就占4、5个像素。如果你的数据里有大量这种小目标,默认的YOLO26配置大概率不会太好用。
大多数人第一个会想到的方法是修改输入分辨率,把图像从640放大到1280甚至更高。这确实有效,因为放大的同时相当于把小目标的像素数翻了倍,检测器能提取到更丰富的特征。但这是个粗暴的方法,代价也不小——输入面积和推理耗时是二次方关系,想清楚了再动手。
我的做法是分两步走。第一步,修改YOLO26的yaml配置文件,调整anchor匹配时对小目标的容忍度。YOLO26的anchor设置默认是COCO数据集的统计结果,你在小目标数据集上直接跑的时候,初始anchor和大目标数据集不匹配,模型需要更长时间才能收敛。YOLO26提供kmeans anchor聚类脚本,根据你的训练数据标签自动重新计算一组anchor尺寸,跑一遍就能看到小目标anchor数量会增加。我在一个无人机数据集上跑了这个脚本,结果小目标的召回率从0.52涨到了0.63,这个提升非常可观。
第二步是数据预处理层面的"马赛克增强",即Mosaic增强。YOLO系列从v4开始就使用马赛克增强作为核心增强手段,把四张图拼接成一张图训练,极大地提升了对小目标的数据多样性。但是注意,如果你的数据集本身偏小,只有几千张,马赛克增强会让目标尺寸的范围分布不够可控。我在一个只有3000多张的工业缺陷数据集上试过,把马赛克增强的概率从100%降到50%,同时开启了copy-paste数据增强(将小目标实例随机复制到其他图像位置上),小目标检测精度不降反升了4个点。原因也不难理解:数据集小,马赛克拼接出来的图可能包含大量完全无关的上下文,反而干扰了模型对"小目标"特征的专注。
推理阶段的小目标优化,还有两个可调的参数。第一个是模型自身使用的NMS阈值,小目标由于特征不丰富,置信度往往比大目标低,默认的置信度阈值0.25会误杀很多本来检测正确的小目标。我通常会把检测的置信度阈值降低到0.1,然后再适当提高NMS的IoU阈值到0.65,这样可以保证小目标不会漏太多,同时不会因为低置信度带来大量误检。第二个是TTA(Test-Time Augmentation),官方实现了多尺度测试增强,推理时在同一张图上跑多种尺寸的缩放,最后把所有结果合并。TTA对小目标的提升效果立竿见影,但是会带来数倍的耗时增加,适合线下分析用,不适合线上实时服务。
7. 训练过程中评价标准的选择艺术:mAP,F1,FPS,Precision和Recall的权衡
聊了这么多实战配置,很多人可能忽略了一个基础问题:怎么评价你的模型到底好还是坏。YOLO26训练结束会在验证集上计算一堆指标,包括mAP@0.5、mAP@0.5:0.95、Precision、Recall、F1-score,看起来一目了然,但在实际业务里,指标和用户体验之间可能完全是两码事。
mAP@0.5指的是在IoU阈值为0.5时的平均精确率,它衡量的是"框的位置大致对就行";mAP@0.5:0.95是把IoU阈值从0.5到0.95分成10档,分别计算mAP再取平均,这个指标更严格,惩罚框的位置偏差。很多新手只看mAP@0.5,但它在目标定位要求严格的场景下会骗人。比如做自动驾驶的行人检测,框偏了半个身位在mAP@0.5里可能依然算检测正确,但对车辆控制来说这是非常危险的。如果你的应用场景对框的精度要求很高,请一定把mAP@0.5:0.95作为主要指标,不要被0.5的漂亮数据迷惑。
Precision和Recall是一对相爱相杀的指标。Precision高,说明预测出来的框大多是对的,误报少;Recall高,说明真正的目标大多被找出来了,漏报少。但这两个指标通常是矛盾的——你把置信度阈值调低,Recall上去了,Precision下来了;阈值调高则相反。好模型应该是在两者之间有个比较理想的平衡,可以用F1-score来衡量这个平衡点。
YOLO26在训练完成后会在results.csv里保存每一步的指标,我用Python写了个简单的三分支平衡评估脚本,用来帮我做模型选型:
def evaluate_balance(results): p = results['precision'] r = results['recall'] f1 = 2 * p * r / (p + r + 1e-9) score = 0.5 * f1 + 0.3 * results['map50_95'] + 0.2 * results['fps'] return score这个评估公式是我自己定的,核心思路是:F1主导模型的综合能力,mAP@0.5:0.95主导定位精度,FPS主导实际可用性。如果你做的是实时场景比如摄像头监控,可能需要把FPS的权重调高到0.4;如果你做的是离线分析比如图片批量审核,可以把mAP的权重调高。指标都是死的,业务需求才是活的。
还有一个在工业场景里容易被忽视的指标——类别不均衡下的惩罚评估。如果你的数据集里"正常品"占了90%,"缺陷品"只有10%,那模型即使不做任何预测,把所有图都归为"正常品",全局准确率也有90%。这种时候要看的不只是整体的mAP,而要看每个类别的AP,尤其是小样本类别的AP。我在一个表面缺陷检测项目里遇到过更极端的情况:模型对大头缺陷的AP是0.95,对小划痕的AP只有0.15,整体mAP还算过得去,但实际业务里真正需要被拦下来的恰恰是那些小划痕。YOLO26提供了per-class指标输出,训练完一定挨个类别看一眼,别被单一的平均指标蒙在鼓里。
8. YOLO26模型结构图和源码解析:从配置文件到检测头的逐层理解
能坚持看到这里的,应该是对技术底层有好奇心的朋友。我个人一直觉得,配置文件和训练命令只是YOLO系列的"外围",真正把模型玩明白,还是要读一读结构定义和源码。YOLO26的源码结构比v8清晰了很多,我挑几个关键文件说明一下。
模型结构定义主要在yaml格式的配置文件中,而不是在Python代码里硬编码。你打开model配置文件,会看到类似于这样的结构层次:
backbone: - [-1, 1, ConvNormAct, [64, 3, 2]] - [-1, 1, ConvNormAct, [128, 3, 2]] - [-1, 3, C2f_26, [128, True]] - [-1, 1, ConvNormAct, [256, 3, 2]] - [-1, 6, C2f_26, [256, True]] - [-1, 1, ConvNormAct, [512, 3, 2]] - [-1, 6, C2f_26, [512, True]] - [-1, 1, ConvNormAct, [1024, 3, 2]] - [-1, 3, C2f_26, [1024, True]]每一行的意思是,当前层接收来自上一层(-1)的输出,做一次卷积加归一化加激活,然后接一个C2f_module。module后面的数字是该层的重复次数。理解了行内参数的含义,你自己就能改结构了。比如我把某个阶段的C2f重复次数从6改成9,模型参数量增加了,在小目标数据集上的效果有了轻微提升。
前向传播过程中的通道变化和特征融合计算,我建议不要在源码里死磕,而是直接打印每一层的输出shape来理解:
import torch model = torch.load('yolov26.pt')['model'].float() dummy_input = torch.randn(1, 3, 640, 640) out = model(dummy_input, return_feats=True) for i, feat in enumerate(out): print(f"Stage {i}: {feat.shape}")输出结果会显示一个典型的金字塔特征列表:从P3的80x80分辨率先到P4的40x40,再到P5的20x20。P3负责小目标,P4负责中目标,P5负责大目标,目标尺寸跟特征层级的关系是YOLO26多尺度检测的基础认知。
关于"YOLO26 depth"这个衍生话题,深度不是单指模型的网络层数,还指模型配置文件里的depth_multiple参数。YOLO26把每一层的宽度和深度通过depth_multiple和width_multiple两个超参来控制,当这两个参数都是1.0时对应的是最大模型yolo26x,调小到0.33和0.5时就对应yolo26s。改动这个参数的快感在于,你修改完之后整个模型的参数量和显存占用会同步变化——模型结构复用同一份设计,不同规格只是通过超参缩放。
在源码层面,还有个很容易踩坑的地方。YOLO26的推理模式有三个返回结果:检测框坐标(xyxy格式)、各类别置信度、以及每个任务分支的辅助输出。很多人在部署时只取第一个返回值,导致分割掩码和关键点的输出没有被序列化出来。正确的用法是把后两个返回值也一并做后处理,我在grpc部署接口里是把它们分别编码成json字段扔出去的。
9. YOLO26改进方向:从注意力机制到轻量化设计的几种有效尝试
模型能跑通只是第一步,大多数情况下我们迁到新框架的动力,就是要针对自己的业务场景做一些定制化改进。YOLO26虽然说是"多任务全能选手",但默认模型在具体场景下往往不是最优解。这里分享几个我实际试过、有真实收益的改进方向。
第一个方向是给backbone加注意力机制。YOLO26主干本身已经有一些基于通道的注意力模块,但在小目标检测上的表现依然不是特别让人满意。我尝试过加入轻量级的坐标注意力模块Coordinate Attention,这个模块在保持通道注意力机制的同时,把位置信息也编码进去。对检测任务来说,这等于同时在告诉网络"哪些特征重要"和"重要的特征在哪"。我在低光环境的数据集上测试,加了Coordinate Attention之后,小目标的召回率提升了5个百分点。代价是参数量增加了大概3%,这个代价换来5个点的召回率提升,我个人认为非常划算。
第二个方向是轻量化,面向边缘设备部署。YOLO26的模型参数量在相同规格下比v8大了一圈,想在Jetson、树莓派这类设备上跑得动,得考虑把C2f里的标准卷积换成Ghost卷积。Ghost卷积的思路是先产生一部分本征特征图,再通过线性变换生成更多的ghost特征图,整体计算量能减少50%以上。我在Ghost卷积替换后做了蒸馏训练——用原来完整的学生模型作为teacher,轻量模型作为student,把teacher的软标签输出拿过来监督student训练。这个方法让压缩后的模型只掉了1.5个mAP点,但推理速度在Jetson Orin上从42ms降到了28ms,可以说很接近无损压缩的效果了。
第三个方向是损失函数的定制。YOLO26默认的分类损失用的是BCE,但对于类别数量极不均衡的数据集,比如你的数据里有200个"缺陷A"但有5000个"正常",BCE容易让模型偏向预测"正常"。我尝试把分类损失改成Focal Loss,通过调节focal参数让模型更关注难分的样本和少样本类别。这个改动对类别不均衡的改善非常明显,我们项目里的一个划痕缺陷类型的AP从0.35涨到了0.58。不过代价是训练前期loss会高一些,因为focal loss在初期对"简单样本"不管不问,我会在训练的前30个epoch先用默认的BCE做热身,之后切到focal loss做精调。
任何改进都要建立在对模型整体性能知情的前提下。我习惯在做任何改动之前先在原版模型上跑一个基线,这个基线是所有改动的对照锚点。比如你想加注意力模块,只有对比原版和改动版在同一测试集上的表现,才能确认这个改动是有效的,而不是因为训练随机性带来的波动。魔改一时爽,验证火葬场,多留一手基线结果,后面省心得多。
10. 部署阶段的权衡:官方模型导出、精度校准与边缘设备优化实战
最后聊部署,因为无论训练阶段做了多少花活,最终目标都是把模型跑起来,在真实场景里产生价值。YOLO26官方提供了很完整的模型导出工具链,支持ONNX、OpenVINO、TensorRT,甚至可以直接导出为带有NMS后处理的端到端模型。这个功能在很大程度上简化了部署流程,但也有一些必须引起重视的细节。
导出TensorRT引擎是我的首选,因为TensorRT会让模型的推理速度产生质变。官方导出命令我简单写一句:
python export.py --weights best.pt --include engine --device 0 --dynamic --simplify注意这里的--simplify标志,它会在导出过程中对计算图做优化,把一些可以合并的算子合并掉。我用它导出的engine模型比普通ONNX缩小了20%,推理速度提升了15%。但有个副作用是部分算子被融合后,模型的输出数值会有细微变化,如果遇到精度敏感的应用,建议导出后重新在验证集上跑一遍指标,确认精度变化在可接受范围内。
量化是边缘设备部署的另一个大话题。YOLO26的权重是FP32的,在Jetson这种低功耗设备上跑FP32模型,速度和功耗都不太友好。TensorRT提供了FP16和INT8两种量化方案。FP16很简单,精度损失几乎可以忽略,推理速度提升约40%。INT8需要准备校准数据集,YOLO26的INT8量化我跑过一版,精度损失大概在2到3个mAP点,但推理速度比FP16还要快35%左右。如果你的任务不是特别追求极限精度,这个换算是值得的。
还有部署时最容易被人忽视的预处理一致性。训练时我们用的归一化参数、颜色通道顺序、resize尺寸,部署的时候必须原样复刻。很多人在Python里训练的模型,部署到C++环境时,因为OpenCV读取图片默认是BGR而PyTorch训练时用的是RGB,导致模型推理结果莫名其妙地变差。解决方法是把预处理写成同一套代码,在Python和C++里各保留一份,做个对拍测试,确保同一个输入图片在两种环境下走出的tensor数值一致。这个看起来是基础操作,但我在实际项目里见过不下三次因为这个原因导致的"模型部署后效果变差"的诡异问题。
边缘设备部署还有一个实用技巧是batch size调整。TensorRT导出的模型可以设置固定的batch size,也可以支持动态batch。动态batch的灵活性好,但推理速度会比固定batch稍慢。在多数监控场景,单个摄像头单次请求一张图,固定batch=1的模型就能满足需求,推理速度也最快。如果有多路摄像头并发,我建议每路单独分配一个batch=1的引擎实例,这样比一个batch=4的引擎并发处理更稳定,因为GPU的资源抢占不会导致某一路请求的延迟突然飙升。
再补充一点关于CPU部署的内容。如果没有GPU条件,比如只在普通服务器上跑,那么OpenVINO可能是你的最优解。YOLO26导出OpenVINO模型后,在Intel CPU上的推理速度比原始ONNX快了3到4倍。我在一台只有i7的旧机器上跑过YOLO26s,输入640x640,单次推理耗时大概在110ms左右,配合多进程并发能勉强达到10FPS的实时性。对于不追求实时检测率的离线审核场景,CPU方案完全够用了。
11. 写在最后:YOLO26项目实践的几点个人体会
啰嗦了这么多,最后简单收个尾。
YOLO26给我的整体感受是"集大成者"——它不是那种凭空冒出来的全新架构,而是把过去几年YOLO系和其他检测模型被验证有效的技巧系统地整合到了一起。多任务统一架构这件事,以前大家用YOLOv8做检测、用SAM做分割、用HRNet做姿态,需要三套模型三套部署链路,现在一套模型一次推理全部搞定。从工程效率角度来说,这个价值怎么强调都不过分。
但如果你问我要不要把所有旧项目都迁移到YOLO26,我的答案是不一定。如果现有项目用YOLOv8已经跑得很稳,而且没有多任务需求,迁移的动力并不大,因为迁移本身是有cost的。但如果你正在启动一个新项目,尤其是有多任务的需求,那么YOLO26绝对值得在技术选型阶段认真考虑。
最后分享一个具体的小技巧亲身验证过:在我最终的生产部署里,我把模型的检测置信度阈值设成了0.15,NMS的IoU阈值设成了0.6,并开启了多任务感知NMS,这个组合在灵敏度和误检率之间拿到了比官方默认值好得多的平衡。每个项目的平衡点不同,但记住这个调整思路,你会在自己的应用场景里找到最适合的配置。祝大家都能把自己的YOLO26项目跑通、调好、落地。