1. 背景与核心概念
1.1 为什么要在 YOLO26 上做注意力改进
YOLO 系列发展到现在,已经从最初单纯追求检测速度,逐步转向速度与精度的平衡。YOLO26 作为该系列较新的迭代版本,在网络结构上依然保持了“CSP 结构 + PAN-FPN + 解耦检测头”的经典骨架,同时吸收了近年来目标检测领域的多项成果,比如 anchor-free 检测方式、动态标签分配、以及更轻量的卷积模块。相比早期版本,YOLO26 在常规光照场景下已经拥有不错的性能,但在低光环境、遮挡密集、小目标偏多的图像中,仍然容易出现漏检和定位偏移。
为什么会这样?主要原因是卷积神经网络在进行特征提取时,更关注局部区域内的纹理和颜色差异,缺少对全局上下文信息的建模能力。低光环境下图像信噪比低,边缘和梯度信息被噪声淹没,单纯依赖卷积核的固定权重提取特征,很难有效区分目标与背景。这种情况下,引入注意力机制是一种常见且高效的改进思路。注意力机制可以让模型动态聚焦到图像中更重要的区域,增强对弱特征信号的响应。YOLO26 的改进工作,也大多围绕如何在 Neck 或 Backbone 中嵌入注意力模块展开。
1.2 HOGformer:传统特征与现代架构的融合
HOG(Histogram of Oriented Gradient,方向梯度直方图)是一种经典的手工特征,最早用于行人检测。它的核心思想是统计图像局部区域内梯度方向的分布,用直方图描述目标的形状和边缘信息。HOG 特征对光照变化有一定鲁棒性,但它本身是静态特征,无法随任务动态调整。
HOGformer 的思路比较直观:既然 HOG 能捕捉梯度方向信息,而 Transformer 又能建模长距离依赖,那么把两者结合起来,就能让网络既拥有传统特征对边缘纹理的敏感度,又具备现代注意力机制的动态建模能力。HOGformer 的典型做法是在 Transformer 的注意力计算之前,先对输入特征图做 HOG 风格的方向梯度统计,再将统计结果作为注意力权重的调制信号,引导模型关注目标轮廓和关键梯度区域。
1.3 DHOGSA:动态梯度感知注意力
DHOGSA(Dynamic HOG-aware Self-Attention,动态梯度感知注意力)是 HOGformer 中的一个关键模块。它的设计目标有两个:
- 感知梯度:利用输入特征图自身的梯度信息,在注意力计算时动态增强边缘、轮廓和弱纹理区域的响应。
- 即插即用:模块设计为独立组件,可以无缝嵌入 YOLO26 的 Backbone 或 Neck 中,不需要大幅改动原有结构。
与普通 SE 注意力或者 CBAM 不同,DHOGSA 不是简单地对通道或空间维度做重标定,而是将 HOG 特征转换为可学习的注意力偏置,在 Self-Attention 的 Q(Query)和 K(Key)相似度计算中引入梯度方向先验。这样做的好处是,在低光环境下,虽然 RGB 像素值差异变小,但相邻像素之间的梯度方向和幅值变化仍然保留了目标轮廓信息,DHOGSA 可以放大这种信号,帮助检测头更准确地定位目标。
下面,我们会在 YOLO26 源码基础上,完整实现一个用于实验的 DHOGSA 模块,并把它插入到 YOLO26 网络结构中,跑通训练与验证流程。
2. 环境准备与版本说明
2.1 运行环境
由于 YOLO26 是基于 Ultralytics 生态演进出来的项目,代码风格与 YOLOv8/v11 类似。因此,本文的演示环境以常见的深度学习环境为基准,具体版本请根据你自己项目实际情况调整,这里重点讲解配置思路。
| 依赖项 | 说明 |
|---|---|
| 操作系统 | Ubuntu 20.04 / CentOS 7 / Windows 10+ 均可 |
| Python | 3.8 - 3.11 |
| PyTorch | 1.13+ / 2.x |
| CUDA | 10.2 / 11.7 / 12.1,需与 PyTorch 对应 |
| ultralytics | 与 YOLO26 源码配套的版本 |
| 硬件 | 建议 GPU 显存大于 8GB,NVIDIA 显卡,支持混合精度训练更佳 |
如果是在 RK3588 这类边缘设备上部署,需要在宿主机交叉编译或使用 RKNN-Toolkit 转换模型,后续章节会详细说明。
2.2 获取 YOLO26 源码与项目结构
假设你已经从官方仓库或社区获取了 YOLO26 源码,并完成了依赖安装。源码目录结构大致如下:
YOLO26/ ├── cfg/ │ ├── yolov26.yaml │ └── ... ├── data/ ├── models/ │ ├── common.py │ ├── yolo.py │ ├── experimental.py │ └── ... ├── utils/ ├── train.py ├── detect.py └── requirements.txt为了不破坏原有代码,建议在models/目录下新增一个hogformer.py文件,专门存放 DHOGSA 模块及配套工具函数。这样后续升级 YOLO26 时,只需要同步新增文件即可。
3. DHOGSA 模块原理拆解
3.1 梯度特征提取
要理解 DHOGSA,首先得知道 HOG 特征是如何计算的。以二维图像特征图 ( F \in \mathbb{R}^{C \times H \times W} ) 为例,HOG 通常先计算每个像素在 x 方向和 y 方向的梯度:
[ G_x = \frac{\partial F}{\partial x}, \quad G_y = \frac{\partial F}{\partial y} ]
然后在局部小区域内统计梯度方向直方图。传统 HOG 是针对手工特征设计的,直接迁移到深度特征图上时,一般采用可微分的卷积方式来计算梯度。比如使用 Sobel 算子或 Scharr 算子。在 PyTorch 中,我们可以用torch.nn.functional.conv2d来高效计算。
计算得到的梯度幅值 ( M = \sqrt{G_x^2 + G_y^2} ) 和梯度方向 ( \theta = \arctan(G_y / G_x) ) 就是 DHOGSA 的核心基础。梯度幅值反映了边缘的强弱,梯度方向反映了边缘的走向。
3.2 动态注意力权重的生成
DHOGSA 并不直接使用完整的 HOG 直方图,而是设计一个轻量的动态感知模块,从梯度信息中学习注意力调制向量。具体步骤如下:
- 对输入特征图计算梯度图
grad_feat = concat(G_x, G_y, M, cos(θ), sin(θ)),维度变成 ( 5C \times H \times W ),或者使用较小的通道数。 - 对梯度特征做全局平均池化和全局最大池化,得到两个向量。
- 将向量拼接后,经过两层全连接层,得到一组动态权重。
- 这组权重会作为 Self-Attention 中 Q 和 K 相乘结果的偏置项,动态调整注意力矩阵。
用公式表示就是:
[ \text{Attention} = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + \lambda \cdot \text{DHOGSA}_\theta(F)\right) ]
其中 ( \lambda ) 是一个可学习的缩放因子,初始值可以设为 0.1,让网络先以常规注意力为主,逐步学习梯度先验的影响。
3.3 与多头注意力的融合
DHOGSA 可以嵌入到标准 Transformer Encoder 层的多头注意力中。它的插入位置在 QK^T 相似度计算之后、softmax 之前。这样做的好处是不会破坏原注意力机制的核心计算,只是额外增加一个梯度调制项,因此非常适合“即插即用”。
将 DHOGSA 应用到 YOLO26 时,我们通常不会把整个 Backbone 替换成 Transformer,而是选择在主干网络的某些层之后插入一个或多个 DHOGSA 增强模块,或是在 Neck 的特征融合过程中使用。这样既能提升模型对梯度信息的敏感度,又不会带来过大的计算开销。
4. YOLO26 中集成 DHOGSA 模块
4.1 实现 DHOGSA 模块代码
下面我们来实现一个完整可运行的 DHOGSA 模块。为了贴合 YOLO26 的代码风格,模块使用 PyTorch 编写,并保证输入输出张量形状不变。
# 文件路径:models/hogformer.py import torch import torch.nn as nn import torch.nn.functional as F class DHOGSA(nn.Module): """ DHOGSA: Dynamic HOG-aware Self-Attention 动态梯度感知注意力模块 输入: (B, C, H, W) 输出: (B, C, H, W) """ def __init__(self, in_channels, num_heads=8, reduction=4, lambda_init=0.1): super(DHOGSA, self).__init__() self.in_channels = in_channels self.num_heads = num_heads self.head_dim = in_channels // num_heads # 用于计算梯度的 Sobel 算子,固定不可学习 self.sobel_x = nn.Conv2d(in_channels, in_channels, 3, padding=1, bias=False, groups=in_channels) self.sobel_y = nn.Conv2d(in_channels, in_channels, 3, padding=1, bias=False, groups=in_channels) # 初始化 Sobel 算子权重 with torch.no_grad(): sobel_kernel_x = torch.tensor([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=torch.float32) sobel_kernel_y = torch.tensor([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=torch.float32) # 扩展为每组一个卷积核 kernel_x = sobel_kernel_x.view(1, 1, 3, 3).repeat(in_channels, 1, 1, 1) kernel_y = sobel_kernel_y.view(1, 1, 3, 3).repeat(in_channels, 1, 1, 1) self.sobel_x.weight.data.copy_(kernel_x) self.sobel_y.weight.data.copy_(kernel_y) self.sobel_x.weight.requires_grad_(False) self.sobel_y.weight.requires_grad_(False) # 投影层 self.q_conv = nn.Conv2d(in_channels, in_channels, 1) self.k_conv = nn.Conv2d(in_channels, in_channels, 1) self.v_conv = nn.Conv2d(in_channels, in_channels, 1) # 动态梯度感知器 hidden_dim = max(in_channels // reduction, 16) self.gradient_mlp = nn.Sequential( nn.Conv2d(in_channels * 2 + 2, hidden_dim, 1, bias=False), nn.BatchNorm2d(hidden_dim), nn.ReLU(inplace=True), nn.Conv2d(hidden_dim, 1, 1, bias=True) ) # 可学习的缩放因子 self.lambda_scale = nn.Parameter(torch.tensor(lambda_init)) # 输出投影 self.proj = nn.Conv2d(in_channels, in_channels, 1) self.avg_pool = nn.AdaptiveAvgPool2d(1) self.max_pool = nn.AdaptiveMaxPool2d(1) def forward(self, x): B, C, H, W = x.shape # 1. 计算梯度图 gx = self.sobel_x(x) gy = self.sobel_y(x) mag = torch.sqrt(gx ** 2 + gy ** 2 + 1e-8) angle = torch.atan2(gy, gx + 1e-8) cos_angle = torch.cos(angle) sin_angle = torch.sin(angle) # 2. 生成动态梯度感知调制图 grad_feat = torch.cat([gx, gy], dim=1) # B, 2C, H, W # 将幅值和角度信息编码,缩小通道数 mag_mean = mag.mean(dim=1, keepdim=True) # B, 1, H, W cos_mean = cos_angle.mean(dim=1, keepdim=True) # B, 1, H, W grad_stat = torch.cat([mag_mean, cos_mean], dim=1) # B, 2, H, W # 使用全局上下文信息调制 gx_pool = self.avg_pool(gx).view(B, C, 1, 1).expand_as(gx) gy_pool = self.max_pool(gy).view(B, C, 1, 1).expand_as(gy) gx = gx + gx_pool gy = gy + gy_pool grad_feat = torch.cat([gx, gy, grad_stat.expand(-1, C, -1, -1)[:, :2, :, :]], dim=1) # B, 2C+2, H, W attention_map = torch.sigmoid(self.gradient_mlp(grad_feat)) # B, 1, H, W # 3. 执行标准多头自注意力(简化版本) q = self.q_conv(x) k = self.k_conv(x) v = self.v_conv(x) # 将特征图转换为序列 q = q.view(B, self.num_heads, self.head_dim, H * W).permute(0, 1, 3, 2) # B, heads, L, D k = k.view(B, self.num_heads, self.head_dim, H * W).permute(0, 1, 3, 2) v = v.view(B, self.num_heads, self.head_dim, H * W).permute(0, 1, 3, 2) attn = torch.matmul(q, k.transpose(-2, -1)) / (self.head_dim ** 0.5) # B, heads, L, L # 将 attention_map 转换为调制偏置 attn_bias = attention_map.view(B, 1, H * W, 1) # 广播到所有头,每个像素一个偏置 attn = attn + self.lambda_scale * attn_bias attn = F.softmax(attn, dim=-1) out = torch.matmul(attn, v) # B, heads, L, D out = out.permute(0, 1, 3, 2).contiguous().view(B, C, H, W) out = self.proj(out) # 残差连接 return out + x if __name__ == "__main__": # 快速测试 model = DHOGSA(in_channels=64, num_heads=8) dummy = torch.randn(2, 64, 32, 32) out = model(dummy) print("Input shape:", dummy.shape) print("Output shape:", out.shape)以上代码实现了一个简化但可运行的 DHOGSA 模块。代码中有几个关键点需要说明:
- 梯度计算用分组卷积实现 Sobel 算子,避免改变通道数,计算效率高。
gradient_mlp生成的是一个空间注意力调制图,直接作用在 Attention 矩阵上。lambda_scale是学习率可调的缩放参数,让网络自己决定梯度先验的重要程度。- 注意力计算为了简化,没有使用相对位置编码,这对于目标检测任务来说通常影响不大,因为目标的位置信息本身也很重要。
4.2 在 YOLO26 的模型解析中注册 DHOGSA
YOLO26 的模型文件通常使用parse_model函数解析 yaml 配置。我们需要在models/common.py或models/yolo.py中导入 DHOGSA,并添加到模块映射字典中。以 ultralytics 风格为例,修改models/yolo.py。
# 在 models/yolo.py 中 from models.hogformer import DHOGSA # 在 parse_model 函数中,找到类似下面的字典 if m in { # 其他模块... 'DHOGSA', # 其他模块... }: # 可以设置默认参数 args = [ch[f], *args]由于不同版本的 YOLO26 解析逻辑略有差异,如果你使用的是 Ultralytics 官方生态,可以在ultralytics/nn/tasks.py的parse_model中注册。下面给出一个通用修改片段:
# 在 parse_model 函数中的模块映射字典里添加 'DHOGSA' from ultralytics.nn.modules import DHOGSA # 提前将 DHOGSA 放入 ultralytics.nn.modules # 注册字典 MODEL_MAP = { # ... 原有模块 'DHOGSA': DHOGSA, }如果源码不是这种结构,只需要保证在解析cfg时,遇到DHOGSA字符串能够构建对应的网络层即可。
4.3 创建使用 DHOGSA 的 YOLO26 配置文件
假设我们要在 Backbone 的最后一个 Stage 之后插入 DHOGSA 模块,可以修改cfg/models/v11/yolov26.yaml。下面是一个基于 YOLO11/yolo26 常见结构的示例配置:
# 文件路径:cfg/models/v11/yolov26.yaml # YOLO26 改进版:引入 DHOGSA 模块 nc: 80 # 你的类别数 scales: 0.5, 1.0, 2.0 # model scales # 注意:该示例基于 YOLO 系列的 yaml 格式,实际以你的 YOLO26 版本为准 backbone: - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 - [-1, 3, C2f, [128, True]] # 2 - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 - [-1, 6, C2f, [256, True]] # 4 - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 - [-1, 6, C2f, [512, True]] # 6 - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 - [-1, 3, C2f, [1024, True]] # 8 - [-1, 1, DHOGSA, [8]] # 9 在最后阶段插入 DHOGSA,8 表示注意力头数 - [-1, 1, SPPF, [1024, 5]] # 10 head: # 检测头部分与原始配置保持一致,这里省略具体参数 - [-1, 1, nn.Upsample, [None, 2, 'nearest']] - [[-1, 6], 1, Concat, [1]] - [-1, 3, C2f, [512]] # 13 - [-1, 1, nn.Upsample, [None, 2, 'nearest']] - [[-1, 4], 1, Concat, [1]] - [-1, 3, C2f, [256]] # 16 - [-1, 1, Conv, [256, 3, 1]] # 17 - [-1, 1, Detect, [nc]] # 18需要说明的是,不同版本的 YOLO26 配置格式可能不同,这里只是为了展示DHOGSA模块如何插入。核心思路是:在某个C2f层级后添加一行- [-1, 1, DHOGSA, [8]],并确保parse_model能解析它。
5. 完整实战教程:训练自己的数据集
5.1 数据集准备
无论是 COCO 还是自定义数据集,YOLO 系列统一使用 txt 标签格式。每张图片对应一个同名 txt 文件,每一行内容为:
class_id x_center y_center width height其中坐标均是相对于图片宽高的归一化值。目录结构建议如下:
datasets/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml文件内容:
# 文件路径:datasets/data.yaml path: datasets/ # 数据集根目录 train: images/train val: images/val nc: 2 # 类别数 names: ['person', 'car'] # 你的类别名称如果是低光环境检测,建议在训练前对低光图片进行数据增强,比如随机调整亮度、对比度、伽马校正等。Ultralytics 引擎内置了丰富的增强策略,但针对低光场景,你可以在训练参数中额外启用hsv_h、hsv_s、hsv_v增强,让模型适应光照变化。
5.2 修改训练参数
YOLO26 的训练脚本通常由train.py或yolo train命令触发。训练参数可以通过命令行传入,也可以写在配置文件里。这里给出一个低光场景下的训练参数示例:
python train.py \ --model cfg/models/v11/yolov26.yaml \ --data datasets/data.yaml \ --epochs 300 \ --batch-size 16 \ --imgsz 640 \ --device 0 \ --optimizer AdamW \ --lr0 0.002 \ --lrf 0.01 \ --warmup-epochs 3 \ --cos-lr \ --cache ram \ --amp True \ --project runs/yolov26_dhogsa \ --name low_light_exp参数说明:
model:指定我们修改后的 YOLO26 yaml 文件。imgsz:输入图片尺寸,低光场景如果目标较小,可以适当增大到 1024,但会显著增加显存占用。amp:混合精度训练可以加快速度,但要注意某些自定义算子可能与 AMP 不兼容。如果训练出现 NaN 或 loss 不下降,可以关闭--amp试试。cache ram:将图片缓存到内存,加快数据加载速度。cos-lr:余弦退火学习率,配合较长训练轮数效果更好。
5.3 模型训练与结果验证
启动训练后,你会看到类似下面的日志输出:
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 1/300 7.8G 1.674 2.312 2.148 12 640 5/300 7.8G 1.402 1.876 1.923 14 640 20/300 7.8G 1.218 1.432 1.612 18 640训练完成后,模型权重保存在runs/yolov26_dhogsa/low_light_exp/weights/best.pt。运行验证:
python val.py \ --weights runs/yolov26_dhogsa/low_light_exp/weights/best.pt \ --data datasets/data.yaml \ --task val \ --imgsz 640 \ --batch-size 16验证结果会输出 mAP50、mAP50-95、precision、recall 等指标。对比没有插入 DHOGSA 的基线模型,可以观察改进后的模型在低光验证集上的表现。
5.4 低光环境检测可视化
使用模型对低光图片做测试:
python detect.py \ --weights runs/yolov26_dhogsa/low_light_exp/weights/best.pt \ --source datasets/low_light_test/ \ --imgsz 640 \ --conf 0.25 \ --iou 0.45 \ --save-txt \ --save-conf--save-txt会保存检测结果 txt,--save-conf会输出置信度。你可以对比原始 YOLO26 和引入 DHOGSA 后的检测结果,观察低光环境下被漏检的目标是否有明显改善。
6. 常见问题与排查思路
在实际对接 YOLO26 和 DHOGSA 模块时,比较容易遇到以下几类问题。下面整理成表格,方便快速定位。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
模型解析错误,提示module not found: DHOGSA | parse_model中没有注册 DHOGSA | 在对应的模型解析文件中导入并添加到模块字典 |
| 训练时显存溢出(OOM) | 注意力机制中的H*W x H*W矩阵过大,尤其输入尺寸大、特征图分辨率高时 | 将 DHOGSA 插入到低分辨率阶段(如 P5),或使用窗口注意力大幅降低计算量 |
| 训练出现 NaN loss | AMP 混合精度下自定义算子计算出现溢出 | 在自定义模块前加@torch.cuda.amp.autocast(enabled=False),或关闭 AMP 训练 |
| loss 不下降,mAP 非常低 | lambda_scale初始化过大,梯度先验压制了原始特征 | 将lambda_init改为 0.01 或 0,让网络先学习基础特征再逐步引入梯度调制 |
| CPU 训练速度极慢 | 注意力计算对 CPU 不友好 | 建议使用 GPU;如果只有 CPU,可以把图像尺寸缩小或减少注意力头数 |
| 导出 ONNX 时算子不兼容 | 部分自定义卷积或自定义函数不支持导出 | 在导出时移除梯度计算中的非标准操作,或用torch.onnx.export的opset设置为更高版本 |
排查时,建议先使用一个小数据集(例如 500 张图片)跑通全流程,确认模块能正常收敛,再扩展到完整数据。
7. 最佳实践与工程建议
7.1 模块插入位置的选择
DHOGSA 并不是插入得越多越好。在 YOLO26 中,我更推荐在 Backbone 的深层和 Neck 的融合层各插入一个,而不是每一层都放。原因有两个:
- 浅层特征图分辨率高,注意力矩阵的计算量随着像素数平方增长,容易造成显存爆炸。
- 浅层更关注颜色、边缘细节,这种低级特征本身已经由卷积层处理得较好;DHOGSA 更适合在语义信息较丰富的深层增强目标轮廓的先验。
如果要在 RK3588 这类边缘设备上做低光检测,还必须考虑计算量。HOG 梯度计算使用分组卷积,整体开销不大,但 Self-Attention 的矩阵乘法仍是主要瓶颈。建议在部署时,将插入 DHOGSA 的层数限制在 1~2 个,并评估 FPS 变化。
7.2 训练策略与调参经验
对于这类带梯度感知的注意力模块,我建议采取“先冻结部分模块,再逐步解冻”的训练策略。具体来说:
- 在前 50 轮,保持 YOLO26 原有主干参数不动,只训练 DHOGSA 模块和检测头。
- 50 轮后,统一微调所有层。
这样做的好处是让 DHOGSA 先学会给已有特征做“注意增强”,不至于在训练早期就和随机初始化的主干“一起跑偏”。此外,学习率不宜设置过大,因为 DHOGSA 中的lambda_scale比较敏感,建议在初始值附近仔细微调。可以使用较低的学习率因子(例如 0.1)单独给lambda_scale设置lr_scale。
7.3 部署时的模型转换与量化
假设你已经验证了改进后的模型效果,下一步需要部署到边缘设备或生产环境。以 RK3588 为例,流程通常是:
- 将 PyTorch 权重转换为 ONNX。
- 使用 RKNN-Toolkit 将 ONNX 转换为 RKNN 格式。
- 在板端使用 RKNN 推理。
转换命令示例:
python export.py \ --weights runs/yolov26_dhogsa/low_light_exp/weights/best.pt \ --include onnx \ --opset 12 \ --simplify如果导出 ONNX 失败,很可能是torch.atan2、torch.sqrt等运算在低版本 OP 集上不支持。解决办法是使用更高opset,或者在代码中把这些运算替换为更稳定的近似实现,比如用x / (sqrt(x^2 + y^2) + eps)表示cos_angle。
RKNN 量化时,建议使用hybrid_quantization或i8量化,但注意 DHOGSA 中的lambda_scale如果数值很小,可能被量化误差覆盖,导致精度下降。可以尝试对包含 DHOGSA 的层单独设置量化粒度,或者先用fp16转换,上线前再权衡精度和速度。
7.4 低光环境的针对性优化
低光环境检测是 DHOGSA 的主要应用场景之一。除了模型结构改进,还应该配合数据策略和图像预处理:
- 对训练集做 MixUp、Mosaic 增强时,增加暗光模拟,比如给图像乘上随机亮度系数,增强模型对光照的鲁棒性。
- 推理时,可以对输入图像做自适应伽马校正,但注意这种预处理如果和训练数据分布不一致,反而会降低精度,需要实验验证。
- 在低光场景中,一定不要忘记开启 YOLO 的
agnostic_nms,因为暗光下目标轮廓模糊,容易产生大量重叠候选框,自适应 NMS 可以帮助减少误检。
8. 总结与下一步学习路线
本文围绕 YOLO26 改进思路,详细拆解了 HOGformer 中 DHOGSA 动态梯度感知注意力的原理、代码实现和工程部署要点。通过一个即插即用的模块设计,让 YOLO26 在低光环境、边缘弱纹理目标上获得更强的特征表达能力。你可以先拿一个小数据集跑通训练-验证-导出的完整流程,再判断是否真的适合自己的业务场景。
接下来值得深入的方向包括:
- 把 DHOGSA 扩展到 C2f 内部,替代底部 Bottleneck,形成类似 C3_DHOGSA 的结构,进一步降低计算量。
- 研究梯度特征与空间注意力、通道注意力的组合方式,比如把梯度幅值作为 CBAM 空间注意力的先验输入。
- 将 DHOGSA 与其他 YOLO26 改进点结合,如 DCNv3、动态检测头等,对比各自的增益。
- 在边缘设备上做混合精度量化实验,重点记录 DHOGSA 层在 INT8 下的精度损失,寻找可接受的量化策略。
如果你在接入 DHOGSA 时遇到问题,欢迎在评论区带上报错信息交流。动手实验比只看文章更重要,跑通一个基线版本后,再逐步调整模块位置和超参数,你会对注意力机制的调优有更深的体会。