motionbert模型量化后精度损失

结论

不能强制指定 MatMul 算子使用 int16。

根据社区官方确认(参考帖子):

RDK X5 / X3 平台的 MatMul 算子在 BPU 上默认只支持 int8 输入,即使在 QAT 流程中编译 HBM 模型时,如果指定 MatMul 输入为 int16 会直接报错。

这是硬件 BPU 架构的限制,不是工具链配置问题。


为什么你之前看到 “不支持 int16” 的警告?

工具链日志中的警告:

WARNING The input1 of Node(name:/blocks_st.0/attn_s/MatMul_1, type:MatMul) does not support data type: int16

这正是工具链在告诉你:MatMul 不支持 int16,已自动回退到 int8


你的当前状态分析

你说:

“输出余弦相似度达到 0.999947,其余算子余弦相似度均在 0.95 以上”

这已经是非常好的结果了! 最终输出相似度 0.999947 说明:

  • Softmax 放 CPU 的策略生效 :white_check_mark:
  • 整体量化精度损失已控制在极小范围 :white_check_mark:
  • MatMul 用 int8 并没有影响最终精度 :white_check_mark:

如果仍有抖动,问题不在 MatMul 精度

既然最终输出相似度已达 0.999947,如果板端仍有抖动,可能原因是:

1. 时序累积误差(最可能)

单帧余弦相似度高 ≠ 时序稳定。建议测试:

# 测试时序抖动
import numpy as np

def test_jitter(model, sequence_data, num_frames=100):
    predictions = []
    for i in range(num_frames):
        frame_input = sequence_data[i:i+120]  # 120 帧窗口
        pred = model(frame_input)
        predictions.append(pred)
    
    # 计算相邻帧关键点位置的标准差
    predictions = np.array(predictions)
    frame_diff = np.diff(predictions, axis=0)
    jitter_std = np.std(frame_diff, axis=0)
    
    print(f"平均抖动标准差:{jitter_std.mean():.6f}")
    print(f"最大抖动:{jitter_std.max():.6f}")
    
    return jitter_std

2. 校准数据分布问题

50 条校准数据可能未覆盖极端动作场景,导致某些帧的量化参数不准确。

3. 板端与开发机环境差异

  • 开发机用 HB_ONNXRuntime 验证 vs 板端 .bin 模型
  • 可能存在前处理对齐问题

建议下一步

方案 A:验证是否真的是 MatMul 问题(先确认)

# 1. 在开发机用 HB_ONNXRuntime 测试 quantized ONNX
python3 test_onnx_quantized.py \
  --model motionbert_lite_quantized_model.onnx \
  --test_sequence ./test_sequence.bin \
  --output_jitter_report

# 2. 对比浮点模型和量化模型的时序输出
python3 compare_temporal.py \
  --float_model motionbert_lite_original_float_model.onnx \
  --quant_model motionbert_lite_quantized_model.onnx \
  --sequence_length 100

如果开发机上 quantized ONNX 没有抖动,但板端 .bin 有抖动 → 前处理/后处理对齐问题。

如果开发机上也有抖动 → 量化本身问题,但 MatMul 用 int8 不是主因(因为相似度已 0.9999+)。


方案 B:进一步优化(如果确认需要)

既然 MatMul 不能用 int16,可以考虑:

  1. 将掉点最严重的 Attention 块整体移到 CPU

    node_info:
      /blocks_st.3/attn_t/q_linear/MatMul:
        ON: CPU
        InputType: float32
        OutputType: float32
      /blocks_st.3/attn_t/k_linear/MatMul:
        ON: CPU
        InputType: float32
        OutputType: float32
      /blocks_st.3/attn_t/v_linear/MatMul:
        ON: CPU
        InputType: float32
        OutputType: float32
      # ... 其他掉点严重的层
    
  2. 增加校准数据到 300-500 条

    python3 generate_calibration_data.py \
      --num_samples 400 \
      --cover_actions all \
      --output_dir ./calibration_data_400
    
  3. 降低 max_percentile

    calibration_parameters:
      max_percentile: 0.999  # 从 0.99999 降低
    

总结

问题 答案
MatMul 能强制 int16 吗? :cross_mark: 不能,BPU 硬件限制
当前 0.999947 相似度够好吗? :white_check_mark: 非常好,MatMul 用 int8 不是瓶颈
如果还有抖动,怎么办? 先验证是时序问题还是板端部署问题,再针对性优化

建议先做时序抖动测试,确认问题根源后再决定是否需要进一步调优或上 QAT。