拓冰建站拓冰建站
首页 / 资讯中心 / 正文

YOLO26改进实操:LSB模块助力低光小目标检测与边缘端部署

很多同学现在看到“YOLO26 改进”这个关键词第一反应是下载一份源码照着网上教程把某个注意力模块塞进 YAML 里然后开训。但真正跑过几轮实验的人会明白一个残酷事实改模型结构很容易让改进真正涨点很难。尤其在低光环境检测、小目标检测、边缘端部署这类场景里很多即插即用模块加进去之后FLOPs 涨了、参数多了、推理变慢了mAP 却纹丝不动甚至出现训练震荡。这不是模块本身不好而是你选的模块和 YOLO 的架构风格不匹配。今天这篇博客想聊的是来自 CVPR 2025 论文 nnWNet 的 LSB 模块。从论文思想来看它做的不是简单堆注意力而是把局部特征以一种连续的方式向后传递让深层网络在保留细节的同时继续提取语义信息。这类模块和 YOLO26 这类单阶段检测器的结合点正好落在“轻量改进”和“低光小目标”这两个高频需求上。读完这篇文章你会得到三样东西第一理解 LSB 模块的技术本质知道它和普通残差连接、注意力模块的区别第二拿到一份在 YOLO26 中集成 LSB 模块的完整代码示例第三学会用正确的方式评估一个改进模块是否真的有效而不是被一张训练曲线图忽悠。1. 这篇文章真正要解决的问题先说实话YOLO26 的改进文章在开源社区里已经快变成“工业流水线”了。今天换一个注意力明天换一个卷积后天换一个特征融合策略但大多数改进缺乏可复现性更缺乏清晰的适用边界。做检测模型改进最大的问题不是“不知道怎么改”而是“不知道该信哪个改法”。LSB 模块之所以值得单独拿出来分析是因为它的设计动机很明确很多高分辨率特征在经过深层网络时细节信息会被逐步稀释。YOLO26 的 backbone 虽然做了多尺度特征提取但在低光、遮挡、小目标这类条件下浅层特征和深层语义之间的连续性仍然不够。LSB 的切入点就是让局部特征不要被“过一層丢一层”而是在层与层之间保持一种连续传输。这篇文章更适合谁读正在用 YOLO26 做自定义数据集训练但发现小目标和低光场景效果不理想的人。想给 YOLO 系列模型做改进却不知道从哪下手的人。需要把检测模型部署到 RK3588 这类边缘设备上既要效果又不能忍受大模块的人。换句话说这不是一篇“推荐所有项目都来用 LSB”的文章而是一篇帮你判断“LSB 适合什么场景、怎么接进 YOLO26、怎么验证效果”的文章。2. CVPR 2025 nnWNet 与 LSB 模块的核心概念2.1 nnWNet 是什么从论文方向看nnWNet 是一个面向视觉任务的网络结构重点解决特征在网络中传递时的“信息损耗”问题。传统网络加深后感受野变大、语义信息变强但局部细节会变差。nnWNet 的设计目标就是让网络在加深的同时局部细节还能“跟得上”。可以这样理解普通主干网络像一条河流水流越到下游越平稳但携带的泥沙细节会沉淀掉。nnWNet 想做的事情是增加一些支流让上游的局部特征能够绕开中间的损耗直接参与下游决策。2.2 LSB 模块局部特征连续传输LSB 的全称可以理解为“局部特征连续传输模块”。它强调的不是“跨层连接”这个表面动作而是“连续传输”这个机制。在现有网络里常见的特征融合方式有两种残差连接把输入直接加到输出上缓解梯度消失但输入和输出之间的信息交互比较粗暴。注意力机制让网络自己决定哪些特征更重要但注意力计算会带来额外开销而且容易在低光场景下关注到噪声。LSB 的思路是另一种路径它构造一个局部特征传输通道让浅层的细节特征不是通过加法或注意力加权而是沿着网络逐步传递下去每一层都接收上一层的局部信息再进行增量更新。这样做的好处是细节特征不会被深层卷积完全覆盖。模块结构相对轻量不会让模型体积暴涨。对小目标和低光环境比较友好因为这类场景特别依赖细节连续性。2.3 LSB 与常见模块的对比对比维度残差连接注意力模块LSB 模块核心机制输入输出相加特征重标定局部特征连续传输主要收益缓解梯度消失增强关键特征保留细节连续性计算开销很低中到高较低对低光场景友好度一般依赖注意力图质量较好与 YOLO 类模型集成难度简单中等中等可解释性高中中这个表格不是要得出“LSB 全面胜出”的结论而是提醒你选模块要看场景。如果你的项目是白天、大目标、样本充足的常规检测LSB 未必比一个经典注意力模块更有优势。但如果是低光环境、小目标、边缘部署LSB 的设计方向确实更对症。3. 为什么 LSB 模块和 YOLO26 能搭配起来3.1 YOLO26 本身解决不了低光小目标的所有问题YOLO 系列发展到 YOLO26已经把检测框架打磨得相当成熟。它支持灵活的网络配置、结构化 YAML 定义、丰富的训练策略也内置了不少数据增强方式。但有一个问题始终存在检测框架的通用性越强它对某一类特殊场景的针对性就越弱。低光环境检测就是一个典型例子。图像整体对比度低、噪声多、目标的边缘信息模糊。此时即使 YOLO26 的 baseline 再强浅层特征中如果缺少足够的局部细节后续的检测头也很难找回信息。从 CVPR 2025 的低光相关研究趋势来看解决低光检测一般有三条路线在输入端做图像增强比如暗光增强网络。在特征提取阶段增强细节保持能力。在检测头或损失函数层面做针对性优化。LSB 模块属于第二条路线它的优势是比图像增强更省计算比修改损失函数更直观而且不改变输入数据分布适配性更强。3.2 即插即用不是一句空话网上很多文章把“即插即用”写得很随意好像加一个模块就等于改一行 YAML。实际上一个真正合格的即插即用模块至少要满足三个条件输入输出 shape 不变能插入任意满足通道数的位置。不影响原始前向传播的主路径回退容易。模块本身轻量不显著增加训练和推理成本。LSB 模块在这三点上表现如何可以从论文结构和代码实现中看到端倪。它不是一个重型的 Transformer 式模块也不是一个复杂的多分支搜索结构而是一个可以在特征层之间反复使用的轻量模块。这决定了它有资格被称作“即插即用”。3.3 与 RK3588 边缘部署的契合度在热搜词里rk3588 yolo26是一个高频搜索方向。这说明很多人在做边缘端检测部署。RK3588 这类设备对模型的约束是明确的算力有限、内存有限、需要 C 或 RKNN 框架转换支持。如果你的改进模块是由大量标准卷积、张量加法和激活函数组成的它比 Transformer 类模块更容易部署到 RKNN 工具链里。LSB 这类基于局部特征传输的模块在结构上更接近卷积网络部署时不需要复杂的算子映射这是一个非常实际的优势。当然我没有办法在这里给出“LSB 在 RK3588 上实测多少毫秒”的数据因为具体耗时取决于模块实现方式、RKNN 版本、量化策略和输入分辨率。但从结构判断它比同体量的注意力模块更容易走通部署链路。4. YOLO26 环境搭建与基础配置在集成 LSB 模块之前先把 YOLO26 训练环境跑通。这里使用 Ultralytics 体系因为 YOLO26 的源码、结构图和训练流程都围绕这一生态展开。4.1 环境准备建议使用 Python 3.8 以上版本并创建独立的虚拟环境。GPU 训练推荐显存不低于 8GB如果显存不够可以把输入分辨率调低或减小 batch size。conda create -n yolo26 python3.10 -y conda activate yolo26 pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118安装完成后用下面的命令验证环境是否正常python -c import ultralytics; print(ultralytics.__version__)如果能够正常打印版本号说明基础环境已经就绪。不同机器的 CUDA 版本可能不同--index-url里的 cu118 可以替换成你本机对应的 CUDA 版本。4.2 准备数据集YOLO26 支持训练自定义数据集数据集格式和 YOLO 系列保持一致。目录结构如下dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/数据标注格式为每行一个目标class_id x_center y_center width height坐标是相对于图片宽高的归一化值。例如一张 640x640 的图片目标中心在 (320, 320)宽高都是 160那么标签一行为0 0.5 0.5 0.25 0.25在项目根目录下创建data.yaml# 文件路径data.yaml train: dataset/images/train val: dataset/images/val nc: 1 names: [target]如果有多类别names列表按顺序写完整nc和names长度必须一致。4.3 训练 YOLO26 Baseline先不着急改结构跑一遍 baseline得到一组对照数据。这一步必不可少因为后面判断 LSB 是否有效全部依赖这份对照结果。yolo detect train datadata.yaml modelyolo26.yaml epochs100 imgsz640 batch8 device0训练完成后会在runs/detect/train目录下生成权重文件和验证结果。建议把这一份结果标记为baseline保存好所有指标防止后续被覆盖。5. 在 YOLO26 中集成 LSB 模块5.1 集成思路在 YOLO26 中集成自定义模块一般有三种方式直接修改ultralytics/nn/modules下的 Python 文件然后在__init__.py中注册。通过任务模型注册机制把新模块注册成可用组件。直接修改yolo26.yaml对应的模型文件把模块实例化到 backbone 或 neck 中。推荐第二种方式因为它的侵入性最小后续升级 YOLO26 版本时不容易被覆盖。5.2 定义 LSB 模块下面的代码是一个 LSB 风格模块的最小实现用于演示集成思路。它通过局部特征缓存和通道混合把输入特征的一部分沿网络连续传递下去。不同论文复现版本的具体实现会有差异这里重点展示集成方法。# 文件路径ultralytics/nn/modules/lsb.py import torch import torch.nn as nn class LSB(nn.Module): LSB 风格模块局部特征连续传输。 简化实现输入输出 shape 保持一致便于即插即用。 def __init__(self, c1, c2, kernel_size3): super().__init__() assert c1 c2, LSB 模块要求输入输出通道数一致 self.conv nn.Conv2d(c1, c2, kernel_size, paddingkernel_size // 2, biasFalse) self.bn nn.BatchNorm2d(c2) self.act nn.SiLU(inplaceTrue) # 局部特征传输权重可学习 self.gate nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Conv2d(c2, c2 // 4, 1, biasFalse), nn.ReLU(inplaceTrue), nn.Conv2d(c2 // 4, c2, 1, biasFalse), nn.Sigmoid(), ) def forward(self, x): identity x out self.conv(x) out self.bn(out) out self.act(out) gate self.gate(out) # 将经过门控的局部特征与原始特征相加实现连续传输 out out * gate identity * (1 - gate) return out这段代码的关键点有两个kernel_size的 padding 设计保证输出特征图尺寸不变。gate部分采用类似通道注意力的结构但不是简单做注意力而是用它控制“局部特征传输”和“原始特征保持”的比例。在实际复现时你可以参考 nnWNet 论文中的原始实现把它替换成更严格的特征流形式。上述代码只是为了把集成链路跑通。5.3 注册模块在模块定义完成后打开ultralytics/nn/modules/__init__.py把LSB注册进去。# 文件路径ultralytics/nn/modules/__init__.py from .lsb import LSB __all__ [ LSB, # ... 其他已有模块 ]这一步会让 YOLO 的模型解析器在读取 YAML 配置时能够识别到名字为LSB的模块。5.4 修改 YOLO26 模型配置接下来新建一个模型配置文件比如yolo26_lsb.yaml。在 backbone 的合适位置插入LSB层。这里以在第 4 层后插入为例# 文件路径yolo26_lsb.yaml # 这里只展示 backbone 部分的关键结构完整配置请参考 yolo26.yaml backbone: - [-1, 1, Conv, [64, 3, 2]] - [-1, 1, Conv, [128, 3, 2]] - [-1, 3, C3k2, [256, False, 0.25]] - [-1, 1, SPPF, [1024, 5]] - [-1, 1, LSB, [256]] # 插入 LSB 模块注意通道数要和输入特征一致 - [-1, 1, Conv, [256, 3, 2]] # ... 后续结构 head: # ... 保持与 yolo26.yaml 一致注意不同 YOLO26 版本中 backbone 层的通道变化不完全一样上面这段 YAML 只是演示。实际使用时你要打开yolo26.yaml确认插入位置的上层输出通道数然后把LSB的参数填成一致。5.5 训练带 LSB 的 YOLO26模型配置文件准备好后直接执行训练命令yolo detect train datadata.yaml modelyolo26_lsb.yaml epochs100 imgsz640 batch8 device0训练完成后同样在runs/detect/train下查看结果。5.6 测试和推理验证 LSB 模块是否真正生效最直接的方法是打印模型结构确认LSB出现在配置中yolo detect export modelruns/detect/train/weights/best.pt formatonnx导出 ONNX 时如果报错找不到LSB算子说明模块在导出图里没有被正确展开。这通常意味着你定义了自定义 Python 层但没有为 ONNX 导出做算子映射。在部署到 RKNN 前这是一个要提前解决的坑。6. 运行结果与效果验证6.1 看哪些训练日志YOLO 训练日志里需要重点关注这几个指标box_loss边界框回归损失正常应逐步下降。cls_loss分类损失正常应逐步下降。mAP50IoU 阈值为 0.5 时的平均精度。mAP50-95更严格的综合精度指标。加入 LSB 模块后不能只看最终 mAP还要看损失曲线的稳定性。如果box_loss反复震荡说明模块可能与当前模型训练策略存在冲突。6.2 如何判断改进有效判断改进是否有效最稳妥的方式是控制变量对比实验组模型结构训练配置预期结论Baselineyolo26.yaml完全一致对照组YOLO26 LSByolo26_lsb.yaml完全一致与 baseline 对比如果 LSB 组在验证集上的mAP50-95比 baseline 高且推理速度没有明显下降才可以初步判断改进有效。更要紧的是要做多次重复实验避免“一次涨点”的偶然性。很多模块第一次实验涨点换一个随机种子就失效了这种情况在低光小目标数据上尤其常见。6.3 可视化验证除了数值指标还可以用 YOLO 自带的 predict 命令跑几张低光测试图观察目标框是否更稳定yolo detect predict modelruns/detect/train/weights/best.pt sourcetest_images/low_light/ imgsz640对比 baseline 和 LSB 两个模型的预测图重点看三个地方小目标是否漏检。低对比度目标是否被漏检或错检。同一目标是否出现框抖动或重复检测。可视化结果能帮助你判断 LSB 的改进到底是“指标涨了实际没好”还是“真正改善了难例检测”。7. 常见问题与排查方法集成 LSB 模块的过程中有几个问题是出现频率最高的。这里整理成一张排查表问题现象可能原因排查方式解决方案训练报错 shape mismatch插入 LSB 的通道数不一致打印模型输出的 shape检查 YAML 中相邻层通道数根据上一层的输出通道调整 LSB 构造参数模型结构里找不到 LSB注册文件没有更新或缓存未清检查__init__.py是否导入 LSB重启 Python 进程正确注册模块清空 Python 缓存训练 loss 不断震荡学习率过高、模块与 BN 冲突降低学习率检查 BN 层在哪一侧统一模块内部 BN 和激活的顺序指标比 baseline 还低插入位置不合适或模块对数据不利尝试不同插入位置进行消融实验换到 neck 层或只在深层插入低光场景效果不明显数据集本身对比度极低模块特征不足查看输入图像统计信息可考虑配合轻量图像增强或更强数据增强ONNX 导出失败自定义算子未映射打印导出错误栈查看是哪个算子不支持用标准卷积/张量操作重写模块避免过于自定义的实现RKNN 转换失败算子不支持或量化敏感先导出 ONNX再转为 RKNN分步排查优先用标准算子实现测试 INT8 量化精度损失在低光环境检测场景里还有一个容易被忽略的问题数据集的标注质量。低光图像本来就模糊如果标注框不准确任何模块都很难通过特征层面的改进来弥补。改进模型之前先确认标注质量和困难样本占比。8. 最佳实践与工程建议8.1 改进前先建立评估体系很多失败的 YOLO26 改进项目不是因为模块不行而是因为评估体系太混乱。建立三个固定版本的数据集切分、训练种子和评估脚本是改进工作的第一步。建议在项目里保存一份eval_config.yaml把训练参数、数据版本、随机种子全部固定保证每次实验可复现。否则不同实验之间的差异很难归因到模块本身。8.2 低光处理要把“增强”和“检测”分开评估低光场景检测里最怕的是一股脑把所有技术都堆上。图像增强、LSB 模块、注意力机制、损失函数调整全部一起上最后涨了不知道是哪个起了作用跌了也不知道是哪个拖了后腿。建议的做法是先用 baseline 跑一版再单独加图像增强再单独加 LSB 模块最后再考虑两者组合。每一步记录指标做成一张完整的实验表。8.3 部署 C / RKNN 时要提前考虑算子兼容性如果你想在 RK3588 上部署 YOLO26 LSB从开发第一天就要考虑算子兼容性而不是训练完再返工。具体注意以下三点尽量使用标准卷积、BN、SiLU、张量加法等常见算子。避免在自定义模块里使用过于复杂的动态控制流。训练完成后先导出 ONNX再转 RKNN分步验证每一步的结果。由于 RKNN 工具链的算子支持范围会随版本变化具体算子兼容性要以你使用的 RKNN 版本为准。8.4 模块要设计成可回退的在代码层面最佳实践是把 LSB 模块设计成可以通过配置文件开关的组件。这样做的好处是训练时可以快速做消融实验部署时也可以根据硬件条件决定是否保留模块。可以给模型配置增加一个use_lsb字段use_lsb: true在解析配置时根据这个字段决定是否在模型结构中插入 LSB。这种方式比直接改代码文件更灵活也更适合团队协作。8.5 注意模块插入位置的选择从现有检测器改进经验来看模块插入位置非常关键。同样的模块放在 backbone 浅层、深层或 neck 位置效果差异很大。一般建议按以下顺序做消融只插入 backbone 的深层。只插入 neck 的上采样特征融合处。同时插入 backbone 和 neck。每次只改一个位置记录指标。如果你发现某个位置涨点明显而另一个位置掉点严重这不一定说明模块有问题而是说明这个模块的表达方式和该位置的特征分布不匹配。9. 后续可以继续深入的方向LSB 模块只是 CVPR 2025 这部分方向的一个代表。真正有价值的学习路径是把这类模块放进 YOLO26 的源码框架里理解它的设计动机再结合自己的数据集做实验。如果你接下来要继续深入可以从以下四个方向入手。第一阅读 nnWNet 的原始实现思路理解“局部特征连续传输”在数学上到底做了什么。不要停留在“加一个模块”的层面而是搞清楚它和普通残差连接的真正区别。第二在低光检测数据集上用 LSB 做专项实验重点观察模型在低对比度、高噪声、小目标三个维度的表现。这类数据集通常需要自己构建因为公开低光检测数据集的数量相对有限。第三结合 YOLO26 的部署能力把训练好的模型走一遍 ONNX、RKNN、C 部署链路。很多人只做训练不做部署结果到项目落地阶段才发现模块无法转换或性能不达标。第四做一个正规的消融实验表把 baseline、baseline 增强、baseline LSB、baseline LSB 增强四组结果放在一起比较。这个表格最终会成为你决定“项目里是否真的需要 LSB 模块”的最重要依据。如果你目前正在做 YOLO26 的自定义数据集训练我建议你先不要追求“加最先进的模块”。先把 baseline 跑稳把评估流程搭好再花一个周末尝试集成 LSB 模块用消融实验说话。这类基于局部特征传输的轻量模块在低光和小目标场景下确实值得一试但它不是万能药。掌握正确的实验方法比复制一份源码更有价值。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门