量化精度评估指标:量化前后精度对比方法、余弦相似度、KL散度、Top-1/Top-5准确率

做量化部署,最怕什么?

怕模型跑得飞快,但精度掉得一塌糊涂。我见过不少团队,模型量化后推理速度翻倍,结果上线一看,用户反馈全是「这AI是不是傻了?」——说白了,精度评估没做到位。

今天咱们就聊聊量化精度评估这件事。我个人习惯把这部分分成四个维度来看:全局指标(Top-1/Top-5)、分布相似度(余弦相似度、KL散度)、逐层对比,以及业务指标兜底。嗯,一个一个来。

1. Top-1 / Top-5 准确率:最直观的「体检报告」

这是最常用的指标,没有之一。你训练一个分类模型,量化前后各跑一遍验证集,对比一下准确率变化,心里就有底了。

核心公式:
Top-1 = 预测概率最高的类别 == 真实标签 ? 1 : 0
Top-5 = 真实标签是否在预测概率前5的类别中 ? 1 : 0

我在项目中遇到过一件事:某个模型量化后Top-1掉了2.3%,团队差点就要回退方案。后来我让他们看了Top-5,只掉了0.4%。这说明什么?模型其实没「傻」,只是第一选择有点犹豫,但候选集里正确答案还在。这种场景下,业务上完全可以接受。

我的建议:不要只看Top-1。尤其对于多分类任务,Top-5能帮你判断模型是「完全跑偏」还是「只是不够自信」。后者往往可以通过后处理或阈值调整来弥补。

2. 余弦相似度:逐层「照镜子」

准确率是宏观指标,但有时候模型精度没掉,中间层的特征分布却已经「变形」了。这时候就需要余弦相似度。

说白了,余弦相似度就是衡量两个向量方向是否一致。量化前后,同一层的输出特征向量,如果余弦值接近1,说明量化没怎么破坏特征表达;如果掉到0.9以下,就要警惕了。

import torch
import torch.nn.functional as F

def cosine_similarity(tensor_a, tensor_b):
    # tensor_a: 量化前输出, tensor_b: 量化后输出
    a_flat = tensor_a.view(tensor_a.size(0), -1)
    b_flat = tensor_b.view(tensor_b.size(0), -1)
    cos_sim = F.cosine_similarity(a_flat, b_flat, dim=1)
    return cos_sim.mean().item()

# 示例:对比某层输出
float_out = torch.randn(64, 256)  # 模拟浮点输出
quant_out = float_out * 0.97      # 模拟量化后微小偏差
sim = cosine_similarity(float_out, quant_out)
print(f"余弦相似度: {sim:.4f}")

你想想看,如果某一层的余弦相似度突然降到0.85以下,那这一层大概率是「精度瓶颈」。我曾经排查过一个模型,发现第7层卷积的余弦相似度只有0.82,其他层都在0.95以上。后来针对这一层做了混合精度(保留浮点),整体精度就回来了。

注意:余弦相似度对尺度不敏感。如果量化后输出整体缩放但方向不变,余弦值依然很高。所以建议配合均方误差(MSE)一起看,一个看方向,一个看幅度。

3. KL散度:量化前后的「信息损失」

KL散度衡量的是两个概率分布之间的差异。在量化场景里,我们用它来对比浮点模型和量化模型的输出分布。

公式长这样:

DKL(P || Q) = Σ P(x) · log(P(x) / Q(x))

值越小,说明量化后的分布越接近原始分布。我个人习惯在校准阶段就用KL散度来选量化参数——比如TensorRT的INT8校准,默认用的就是KL散度。

import numpy as np
from scipy.special import kl_div

def kl_divergence(p, q):
    # p: 浮点模型输出概率分布
    # q: 量化模型输出概率分布
    p = np.clip(p, 1e-10, 1.0)  # 避免log(0)
    q = np.clip(q, 1e-10, 1.0)
    return np.sum(kl_div(p, q))

# 示例
float_probs = np.array([0.1, 0.2, 0.3, 0.4])
quant_probs = np.array([0.12, 0.19, 0.28, 0.41])
kl_val = kl_divergence(float_probs, quant_probs)
print(f"KL散度: {kl_val:.6f}")

这里有个坑:KL散度是非对称的。也就是说,DKL(P||Q) 和 DKL(Q||P) 不一样。我曾经在项目里用反了方向,结果发现量化后的「异常层」怎么都找不对。后来改成以浮点分布为基准P,量化分布为Q,才定位到问题。

避坑指南:KL散度适合对比概率分布(比如Softmax输出),不适合直接对比特征图。特征图用余弦相似度或MSE更合适。

4. 综合评估流程:我的「三板斧」

在实际项目中,我不会只依赖某一个指标。我的流程一般是这样的:

  1. 先跑Top-1/Top-5:快速判断量化后模型是否「可用」。如果掉点超过1%,进入下一步。
  2. 逐层计算余弦相似度:找出「异常层」。通常余弦值低于0.9的层需要重点关注。
  3. 对异常层计算KL散度:确认分布偏移程度。如果KL散度大于0.01(经验值),考虑混合精度或调整量化参数。
  4. 业务指标兜底:比如检测任务的mAP、推荐任务的AUC。这些才是最终说了算的。
核心逻辑:量化精度评估不是「过一遍指标就完事」,而是一个定位→分析→修复的闭环。余弦相似度帮你定位,KL散度帮你分析,Top-1/Top-5帮你验证修复效果。

5. 一张图总结:量化精度评估体系

下面这张图是我自己总结的评估体系,每次做量化项目都会贴在墙上。你感受一下:

量化精度评估体系 量化模型 Top-1 / Top-5 全局准确率对比 余弦相似度 逐层特征方向 KL散度 分布信息损失 业务指标 mAP / AUC 等 ▼ 评估流程 ▼ ① 跑Top-1/Top-5 ② 逐层余弦相似度 ③ 异常层KL散度 ④ 业务指标兜底 定位 → 分析 → 修复 → 验证 量化精度调优的完整闭环

6. 一些实战中的「小九九」

最后分享几个我踩过的坑,希望能帮你省点时间:

  • 校准集要覆盖真实分布:我见过有人用100张猫图去校准一个包含狗、车、人的模型。结果KL散度算出来很好看,上线后直接崩。校准集一定要有代表性。
  • 不要只看均值:余弦相似度平均0.97,但可能有某几个batch只有0.6。建议同时看最小值方差
  • Top-1掉点0.5%以内,通常不用管:这是经验值。如果业务要求极高(比如医疗影像),那另当别论。
  • 量化后精度反而提升?:别高兴太早。有时候量化引入的噪声恰好「正则化」了过拟合的模型。这种情况在验证集上可能好看,但泛化性不一定好。建议多测几个数据集。
我的习惯:每次量化完,我会把四个指标的结果整理成一张表,贴在项目文档里。这样后续迭代时,一眼就能看出哪个版本、哪个层出了问题。比如这样:
层名 余弦相似度 KL散度 Top-1变化 Top-5变化 结论
Conv_1 0.998 0.0003 -0.1% -0.02% 正常
Conv_7 0.823 0.0150 -1.8% -0.5% 需修复
FC_out 0.971 0.0021 -0.3% -0.1% 正常

嗯,量化精度评估这件事,说白了就是「用合适的尺子,量对的地方」。Top-1/Top-5是宏观尺子,余弦相似度和KL散度是微观放大镜。结合起来用,你就能精准定位问题,而不是盲目调参。

希望这些经验对你有帮助。下次遇到量化精度掉点,别慌,按这个流程走一遍,大概率能找到根因。


公众号:蓝海资料掘金营,微信deep3321