[图像算法][RDK X5][YOLOv26 量化后检测框严重偏移 / 不稳定问题]

:magnifying_glass_tilted_left: 配置分析

看了你的 YAML 配置,这是官方标准模板,但有几个关键问题可能导致量化后精度崩塌:


:warning: 核心问题定位

问题 1:校准数据格式与配置不匹配

你的配置:

input_type_rt: 'nv12'      # 板端输入 NV12
input_type_train: 'rgb'    # 训练时 RGB
norm_type: 'data_scale'
scale_value: 0.003921568627451  # 1/255
cal_data_type: 'float32'   # 校准数据是 float32

关键矛盾:

  • cal_data_type: 'float32' 意味着校准数据应该是已经归一化到 0-1 的 RGB 浮点数据
  • 但你的校准数据如果是直接从训练集复制的 JPG 图片,可能是 0-255 的 uint8

验证方法:

import numpy as np
import os

cal_dir = "./calibration_data/"
for f in os.listdir(cal_dir)[:3]:
    if f.endswith('.npy'):
        data = np.load(os.path.join(cal_dir, f))
        print(f"{f}: shape={data.shape}, min={data.min():.4f}, max={data.max():.4f}")
        # ✅ 正确:min≈0, max≈1
        # ❌ 错误:min=0, max=255

问题 2:没有跳过 YOLO Head 关键层

根据社区案例 topic 34915,YOLOv26 量化后 cls 输出分布严重畸变(从 [-229, 82] 变成 [-14, -0.1]),导致置信度计算错误。

解决方案:在 optimization 中添加 skip 配置

optimization: set_Softmax_input_int8,set_Softmax_output_int8{int16_opt},set_conv_int16_pattern=model.22/cv2.*,model.22/cv3.*

或者在量化配置中指定部分层用 INT16:

# 在 calibration_parameters 后添加
compiler_parameters:
  jobs: {opt.jobs}
  compile_mode: 'latency'
  debug: true
  optimize_level: '{opt.optimize_level}'
  # 添加层精度控制
  layer_precision_config: |
    model.22/cv2/*: int16
    model.22/cv3/*: int16

问题 3:缺少精度验证步骤

建议在量化后立即验证输出分布:

# 验证量化后 ONNX 的输出分布
import onnxruntime as ort
import numpy as np

session = ort.InferenceSession('yolov26_quantized.onnx')
img = np.random.randn(1, 3, 640, 640).astype(np.float32)
outputs = session.run(None, {session.get_inputs()[0].name: img})

print("=== 量化后输出分布 ===")
for i, o in enumerate(outputs):
    print(f"Output {i}: shape={o.shape}, min={o.min():.4f}, max={o.max():.4f}")
    if o.min() < -20 or o.max() > 20:
        print(f"  ⚠️ 输出范围异常,可能是量化失真")

:white_check_mark: 推荐修改后的配置

model_parameters:
  onnx_model: '{opt.onnx}'
  march: "bayes-e"
  layer_out_dump: True  # 开启层输出,方便 debug
  working_dir: '{bpu_output_dir}'
  output_model_file_prefix: '{output_prefix}'

input_parameters:
  input_name: ""
  input_type_rt: 'nv12'
  input_type_train: 'rgb'
  input_layout_train: 'NCHW'
  norm_type: 'data_scale'
  scale_value: 0.003921568627451

calibration_parameters:
  cal_data_dir: '{cal_data_dir}'
  cal_data_type: 'float32'
  calibration_type: 'default'
  calibration_size: 200  # 建议增加到 200

optimization: set_Softmax_input_int8,set_Softmax_output_int8{int16_opt},set_conv_int16_pattern=model.22/cv2.*,model.22/cv3.*

compiler_parameters:
  jobs: {opt.jobs}
  compile_mode: 'latency'
  debug: true
  optimize_level: '{opt.optimize_level}'

:rocket: 立即执行排查

1. 验证校准数据格式

python3 -c "
import numpy as np, os
cal_dir = './calibration_data/'
for f in os.listdir(cal_dir)[:3]:
    if f.endswith('.npy'):
        d = np.load(os.path.join(cal_dir, f))
        print(f'{f}: [{d.min():.3f}, {d.max():.3f}]')
"

2. 查看编译日志中的层相似度

# 在编译日志中搜索 "Cosine Similarity" 或 "相似度"
# 重点关注 < 0.9 的层,尤其是 model.22 相关层
grep -i "similarity" compile.log

3. 如果仍有问题,补充以下信息到帖子:

  • 校准数据的生成方式(如何从训练集转换的)
  • 编译日志中的 Cosine Similarity 报告
  • 量化后 ONNX 的输出分布(min/max)

:pushpin: 社区参考

案例 问题 解决方案
topic 34915 YOLOv26 量化后 cls 输出畸变 跳过 YOLO Head 量化 + 更换校准数据
topic 34931 量化后几乎无法检测 校准数据与训练预处理不一致
topic 33350 threshold 非法导致精度崩塌 检查校准数据覆盖范围

先执行校准数据格式验证,这步最可能发现问题根源。