motionbert模型量化后精度损失

:magnifying_glass_tilted_left: 深度分析:问题不在 Softmax 本身

从新量化报告看到关键问题:

1. Softmax 相似度两极分化

Softmax 节点 相似度 问题
/blocks_st.0/attn_s/Softmax 1.000010 :white_check_mark: 正常
/blocks_st.0/attn_t/Softmax 1.000109 :white_check_mark: 正常
/blocks_ts.1/attn_t/Softmax 0.853005 :cross_mark: 严重损失
/blocks_st.2/attn_t/Softmax 0.832161 :cross_mark: 最严重
/blocks_ts.2/attn_t/Softmax 0.842229 :cross_mark: 严重损失

2. 真正问题:Softmax 输入已量化损失

/blocks_st.1/attn_t/v_linear/MatMul  → 0.946226 (int8)
                                        ↓ 量化损失传递
/blocks_st.1/attn_t/Softmax          → 0.930826 (float) ❌

/blocks_ts.1/attn_t/v_linear/MatMul  → 0.928596 (int8)
                                        ↓ 量化损失传递
/blocks_ts.1/attn_t/Softmax          → 0.853005 (float) ❌

Softmax 虽然在 CPU 上跑 float32,但输入数据已经是量化后的 int8!

3. 误差累积曲线

Layer 0: 0.999+  ✅
Layer 1: 0.97-0.99  ⚠️  (v_linear 开始掉点)
Layer 2: 0.92-0.95  ❌  (v_linear 跌破 0.93)

:hammer_and_wrench: 终极解决方案

方案 A:保护 Attention 的 V 投影层(最关键)

# config_attention_fp16.yaml
model_parameters:
  onnx_model: ./motionbert_lite_120.onnx
  march: bayes-e
  working_dir: motionbert_lite_model_output_v2
  layer_out_dump: true
  
  node_info:
    # ========== 所有 Softmax 保持 CPU + float32 ==========
    /blocks_st.0/attn_s/Softmax:
      ON: CPU
      InputType: float32
      OutputType: float32
    /blocks_st.0/attn_t/Softmax:
      ON: CPU
      InputType: float32
      OutputType: float32
    # ...(所有 Softmax 节点同上)
    
    # ========== 关键:所有 Attention 的 v_linear 保持 int16 ==========
    /blocks_st.0/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.0/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.1/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.1/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.2/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.2/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.0/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.0/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.1/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.1/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.2/attn_s/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_ts.2/attn_t/v_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    
    # ========== 可选:q_linear 和 k_linear 也保持 int16 ==========
    /blocks_st.1/attn_t/q_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    /blocks_st.1/attn_t/k_linear/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16
    
    # ========== 输出头保持 int16 ==========
    /Concat:
      ON: BPU
      InputType: int16
      OutputType: int16
    /Concat_1:
      ON: BPU
      InputType: int16
      OutputType: int16
    /Concat_2:
      ON: BPU
      InputType: int16
      OutputType: int16
    /head/MatMul:
      ON: BPU
      InputType: int16
      OutputType: int16

calibration_parameters:
  cal_data_dir: ./calibration_data_120
  cal_data_type: float32
  calibration_type: kl  # 改用 KL 散度
  max_percentile: 0.9999  # 从 0.99999 降低到 0.9999
  per_channel: true

方案 B:增加校准数据(必须配合方案 A)

# 50 条对时序 Transformer 模型严重不足
# 准备 300-500 条校准数据

# 校准数据生成要点:
# 1. 覆盖完整动作空间(静止、行走、跑步、跳跃等)
# 2. 包含遮挡场景
# 3. 包含不同视角
# 4. 确保 2D 关键点输入分布与真实推理一致

python3 generate_calib_data.py \
  --num_samples 300 \
  --cover_actions all \
  --output_dir ./calibration_data_300

方案 C:降低 max_percentile(立即见效)

当前配置 max_percentile: 0.99999 过于激进,导致异常值影响校准:

calibration_parameters:
  max_percentile: 0.9999  # 从 0.99999 降低
  # 或进一步降低到 0.9998 测试

:clipboard: 验证步骤

# 1. 应用新配置重新量化
hb_mapper --config config_attention_fp16.yaml

# 2. 检查 v_linear 层相似度是否提升
cat motionbert_lite_model_output_v2/motionbert_lite_quant_info.json | grep "v_linear/MatMul"

# 预期:从 0.92-0.94 提升到 0.97+

# 3. 检查 Softmax 输入前置节点
cat motionbert_lite_model_output_v2/motionbert_lite_quant_info.json | grep -B2 "Softmax"

# 4. 板端测试抖动
# 录制连续 100 帧,计算关键点位置标准差

:bar_chart: 预期效果

指标 当前 方案 A 后 方案 A+B 后
v_linear 相似度 0.92-0.94 0.96+ 0.98+
低分 Softmax 0.83-0.85 0.95+ 0.98+
关键点抖动 明显 减轻 基本消除

:warning: 如果仍不满足

QAT 是最终手段,参考社区精华帖:

请先执行方案 A(保护 v_linear)+ 方案 C(降低 max_percentile),这通常能解决 90% 的 Transformer 量化抖动问题。

需要我帮你生成完整的 YAML 配置文件吗?