在2025年9月举办的 YOLO Vision 2025 大会上,Ultralytics 就说预期十月份发布YOLO26[1]。
结果跳票了3个月,终于在昨天正式发布出来了。
Ultralytics 发布的上一代YOLO 还是YOLO11,这次直接改名YOLO26,估计是有两方面的考量:
- ultralytics要推商业化,必然要主导YOLO的命名权,如果还是按照之前的那种习惯,到时候别人又开始发论文占坑(比如YOLO12),这样做彻底把这条路堵死了。
- 作为一个长期维护的开源项目,学习苹果操作系统的命名模式,估计是打算一年做一次大版本更新,这样做也更有规律和识别度。
当然,和前几代“挤牙膏”式的性能提升略有不同,这次YOLO26比前面YOLO11的提升幅度是略大的,从下面的曲线图也能看出来,在COCO数据集上的性能表现曲线明显变高了。
这一代模型依然是n/s/m/l/x五个型号,性能和速度也比RT-DETR更好。
下面来看看主要的更新亮点。
更新内容概述
根据其博客[1]描述,YOLO26主要有以下内容更新:
DFL 移除
分布焦损 (DFL) 模块虽然有效,但导出过程通常较为复杂,且硬件兼容性有限。YOLO26 完全移除了 DFL,简化了推理过程,并扩展了对边缘计算和低功耗设备的支持。端到端无 NMS 推理
与依赖非极大值抑制(NMS)作为独立后处理步骤的传统检测器不同,YOLO26 本身就是端到端的 。它直接生成预测结果,从而降低延迟,使集成到生产系统中更快、更轻量、更可靠。ProgLoss + STAL
改进的损失函数提高了检测精度,尤其是在小目标识别方面取得了显著改进,这对于物联网、机器人、航空图像和其他边缘应用来说至关重要。MuSGD 优化器
一种结合了 SGD 和 Muon 的新型混合优化器。受 Moonshot AI 的 Kimi K2 启发,MuSGD 将 LLM 训练中的先进优化方法引入计算机视觉领域,从而实现更稳定的训练和更快的收敛速度。CPU 推理速度提升高达 43%
YOLO26 专为边缘计算而优化,可提供更快的 CPU 推理速度,确保在没有 GPU 的设备上实现实时性能。实例分割增强
引入语义分割损失以改善模型收敛性,并升级了原型模块,利用多尺度信息以获得更优的掩码质量。精确姿态估计
集成残差对数似然估计 (RLE) 以实现更准确的关键点定位,并优化解码过程以提高推理速度。改进的 OBB 解码
引入专门的角度损失来提高方形物体的检测精度,并优化 OBB 解码以解决边界不连续问题。
细节分析
深扒其开源代码[2],可以对上述内容进行更详细的分析。
NMS替代
在取消NMS之后,实际上是用 TopK 替代 NMS
在 ultralytics/nn/modules/head.py 代码中,可以看到相关代码:
defpostprocess(self,preds):"""用 TopK 替代 NMS"""boxes,scores=preds.split([4,self.nc],dim=-1)scores,conf,idx=self.get_topk_index(scores,self.max_det)boxes=boxes.gather(dim=1,index=idx.repeat(1,1,4))returntorch.cat([boxes,scores,conf],dim=-1)defget_topk_index(self,scores,max_det):"""选择 Top-K 个最高分的预测"""k=max_det ori_index=scores.max(dim=-1)[0].topk(k)[1].unsqueeze(-1)scores=scores.gather(dim=1,index=ori_index.repeat(1,1,nc))scores,index=scores.flatten(1).topk(k)idx=ori_index[...,index//nc]returnscores[...,None],(index%nc)[...,None].float(),idxTopK是通过计算每个目标框的 预测得分,选择得分最高的 max_det 个框。
例如,假设有 1000 个候选框,在推理阶段,通过 TopK 筛选出前300个具有最高置信度的框。
y=self._inference(preds["one2one"]ifself.end2endelsepreds)ifself.end2end:y=self.postprocess(y.permute(0,2,1))# TopK 后处理returny在模型训练的时候,通过一个 One2One分支 来进行一对一的目标匹配,通过这种方式,让模型自身学习如何去除多余的框。
ProgLoss
取缔NMS这步是有点激进的,为此,YOLO26使用了ProgLoss去进行渐进式损失计算,旨在通过在训练过程中逐渐调整不同损失的权重,以帮助模型更有效地学习。
在 ultralytics/utils/loss.py 文件中,E2ELoss 类实现了 ProgLoss 的核心逻辑:
classE2ELoss:def__init__(self,model,loss_fn=v8DetectionLoss):self.one2many=loss_fn(model,tal_topk=10)# 一对多分配,topk=10self.one2one=loss_fn(model,tal_topk=7,tal_topk2=1)# 一对一分配,topk2=1# 初始权重self.o2m=0.8# one-to-many 初始权重 80%self.o2o=0.2# one-to-one 初始权重 20%self.final_o2m=0.1# one-to-many 最终权重 10%def__call__(self,preds,batch):loss_one2many=self.one2many.loss(one2many,batch)loss_one2one=self.one2one.loss(one2one,batch)# 加权混合returnloss_one2many[0]*self.o2m+loss_one2one[0]*self.o2o,...defdecay(self,x)->float:"""渐进衰减公式"""returnmax(1-x/max(epochs-1,1),0)*(0.8-0.1)+0.1翻译一下代码,这个损失的变化如下表所示:
| 阶段 | one2many 权重 | one2one 权重 | 目的 |
|---|---|---|---|
| 早期 | 高 (0.8) | 低 (0.2) | 多正样本快速学习特征 |
| 中期 | 渐减 | 渐增 | 平滑过渡,逐步调整模型焦点 |
| 后期 | 低 (0.1) | 高 (0.9) | 专注一对一精确匹配,减少冗余 |
ProgLoss 通过在训练的不同阶段调整权重,模型能够在初期专注于广泛学习特征(one-to-many),而在后期聚焦于精确地进行目标匹配(one-to-one)。
STAL
STAL (Small-Target-Aware TAL)是一个针对小目标的改进,核心代码在 ultralytics/utils/tal.py 的 select_candidates_in_gts 函数中:
defselect_candidates_in_gts(self,xy_centers,gt_bboxes,mask_gt,eps=1e-9):gt_bboxes_xywh=xyxy2xywh(gt_bboxes)# 将边界框格式从 (x_min, y_min, x_max, y_max) 转换为 (x_center, y_center, width, height)# 关键:检测小于最小stride的目标wh_mask=gt_bboxes_xywh[...,2:]<self.stride[0]# stride[0] = 8,用来检测目标宽高小于stride的目标stride_val=torch.tensor(self.stride[1],dtype=...,device=...)# stride[1] = 16,为大目标的stride值# 关键优化:将小目标的宽高扩展到第二个stride尺度gt_bboxes_xywh[...,2:]=torch.where((wh_mask*mask_gt).bool(),# 如果是小目标且在mask中,则执行扩展stride_val,# 小目标 → 扩展到16gt_bboxes_xywh[...,2:]# 其他目标 → 保持原尺寸)gt_bboxes=xywh2xyxy(gt_bboxes_xywh)# 将修改后的边界框转换回 (x_min, y_min, x_max, y_max) 格式它的原理是通过将小目标的边界框虚拟扩展到16px,使得小目标能匹配更多的锚点。
例如,原始的小目标尺寸为 6x6 px,而在特征图上,锚点的尺度通常较大(如 stride=8),导致原始的小目标无法匹配足够多的锚点,可能只有一个或者没有匹配的锚点。
虚拟扩展通过扩展小目标的边界框尺寸(将 6x6 px 扩展到 16x16 px),模拟一个较大的目标。这个扩展不是物理上修改目标的尺寸,而是改变了计算过程中的目标尺寸,使得它能够匹配更多的锚点。
扩展后的效果:扩展后的虚拟目标(如 16x16 px)可以与更多的锚点进行匹配,这样就会增加正样本的数量,同时也增强了小目标的学习信号。这样一来,模型就能够更好地识别和学习小目标的特征。
MuSGD
Muon的创新点是通过Newton-Schulz迭代对梯度矩阵进行正交化,从而让收敛速度更加稳定。
MuSGD其实不是纯创新的优化器,而是Muon和SGD的加权混合。
在代码 ultralytics/engine/trainer.py 中,可以看到具体权重。
muon, sgd = (0.5, 0.5) if iterations > 10000 else (0.1, 1.0)翻译一下就是:
| 条件 | muon 权重 | sgd 权重 |
|---|---|---|
| 迭代次数 > 10000 (大数据集) | 0.5 | 0.5 |
| 迭代次数 ≤ 10000 (小数据集/微调) | 0.1 | 1.0 |
这样混合是发挥了两者各自的优势:
- Muon:提供正交化的"探索"方向
- SGD:提供稳定的更新方向
从权重上看,Muon 只有在大数据集上才会重点使用,对于小样本的数据集来说,作用不明显。
总结
YOLO26 主要的优化倾向是增加小目标的检测性能和优化推理速度,同时,在目标检测领域,YOLO依然是那个SOTA。
参考
[1] https://docs.ultralytics.com/models/yolo26/#overview
[2] https://github.com/ultralytics/ultralytics