2. 精度对比基础
做精度调优,第一步不是调,而是比。你得先知道“对”的是什么样,才能判断手里的模型偏没偏。这一章咱们就把精度对比的底子打牢——标杆精度怎么拿、对比工具怎么用、评价指标怎么看。我个人习惯把这部分叫“精度调优的锚点”,锚点稳了,后面才不会飘。
2.1 标杆精度获取方法
所谓标杆精度,就是你认为“绝对正确”的那份参考输出。我一般用业界公认的框架(比如 PyTorch、TensorFlow 在 GPU 上的 float32 推理结果)作为标杆。你想想看,如果标杆本身就有问题,后面所有对比都是白费功夫。
- 在 GPU 上用 float32 跑一遍完整推理,保存每一层/每一个算子的输出 tensor。
- 确保输入数据完全一致(包括随机种子、预处理流水线)。
- 用
torch.save或numpy.save把标杆 dump 成文件,命名带上网络名和算子名。
我在项目中遇到过好几次“假精度问题”——折腾半天发现是标杆数据没对齐,比如图像预处理时像素归一化顺序不同。所以,标杆获取一定要和待测模型走同一份预处理代码,别偷懒。
2.2 精度对比工具介绍
昇腾平台提供了几款非常顺手的对比工具。我个人最常用的是 compare_dump.py 和 accuracy_compare.sh。它们能自动加载标杆 dump 和昇腾 dump,然后逐算子算指标。
# 典型用法(昇腾工具链)
python compare_dump.py \
--baseline ./dump_gpu/ \
--target ./dump_ascend/ \
--output ./compare_result/ \
--metric cosine
除了官方工具,我也经常自己写脚本——尤其是当模型结构比较特殊时。比如用 numpy 手动加载两个 npy 文件,然后算余弦相似度。说白了,工具只是辅助,理解背后的计算逻辑才重要。
| 工具/方法 | 适用场景 | 输出形式 |
|---|---|---|
| compare_dump.py | 标准网络逐算子对比 | CSV + 日志 |
| accuracy_compare.sh | 整网精度一键对比 | 汇总报告 |
| 自定义 numpy 脚本 | 特殊算子或自定义层 | 自定义 |
2.3 精度评价指标
指标是尺子。尺子选错了,量出来的结果没有意义。我一般用三个核心指标:余弦相似度、PSNR、相对误差。它们各有侧重,下面展开说。
余弦相似度 (Cosine Similarity)
衡量两个向量在方向上的相似程度。值越接近 1,说明方向越一致。对于 feature map 或 embedding,余弦相似度非常敏感。
import numpy as np
def cosine_sim(a, b):
a_flat = a.flatten()
b_flat = b.flatten()
dot = np.dot(a_flat, b_flat)
norm = np.linalg.norm(a_flat) * np.linalg.norm(b_flat)
return dot / (norm + 1e-12)
# 我一般要求余弦相似度 > 0.99,低于 0.95 就要报警
嗯,这里要注意:余弦相似度对整体缩放不敏感。如果某个算子的输出整体乘了一个常数,余弦相似度可能还是 1.0,但实际数值已经错了。所以不能只看余弦。
PSNR (峰值信噪比)
PSNR 在图像领域用得最多,但用在 tensor 对比上也很直观。它基于 MSE,单位是 dB。PSNR 越高,差异越小。我个人习惯:PSNR > 40dB 说明精度很好,30~40dB 可以接受,低于 30dB 就要仔细查了。
def psnr(a, b, max_val=1.0):
mse = np.mean((a - b) ** 2)
if mse == 0:
return float('inf')
return 20 * np.log10(max_val / np.sqrt(mse))
PSNR > 45 dB → 几乎无差异
PSNR 35~45 dB → 微小差异,通常可接受
PSNR < 30 dB → 需要排查算子或精度模式
相对误差 (Relative Error)
相对误差是最直观的指标。我常用的是 abs(a - b) / (abs(a) + 1e-8),然后看最大值、均值、中位数。如果最大相对误差超过 1%,基本就有问题了。
def relative_error(a, b):
diff = np.abs(a - b)
base = np.abs(a) + 1e-8
return np.max(diff / base)
# 我曾经遇到一个算子,相对误差达到 5%,最后发现是精度模式没设置成 force_fp32
三个指标要配合使用。我自己的流程是:先看余弦相似度,如果低于 0.99 再看 PSNR,如果 PSNR 也低,最后用相对误差定位具体哪些位置的数值偏差大。你想想看,这样一层层筛下来,根因基本就锁定了。