Tensor Metrics
Tensor 指标说明
Tensor 本身只是一个带 shape 的数值数组。L1 norm、entropy、log_prob、logits/logistic 的含义取决于这个 tensor 表示什么,以及在哪个维度上计算。
常见分类模型输出:
| 名称 | Shape | 含义 |
|---|---|---|
logits |
[B, K] |
模型原始输出分数 |
probs |
[B, K] |
softmax 后的概率分布 |
target |
[B] |
每个样本的真实类别 |
loss |
scalar |
batch 归约后的训练目标 |
其中:
B:batch sizeK:类别数、词表大小或动作数- 最后一维通常是概率分布维度
总览
| 指标 | 本质 | 常见输入 | 常见输出 | 值域 | 是否适合比较精度 |
|---|---|---|---|---|---|
L1 norm |
数值大小或差异 | 任意 tensor | scalar / 按维度归约 | [0, +∞) |
适合数值误差、回归 |
entropy |
分布不确定性 | 概率分布 | 去掉分布维度 | [0, log K] |
不适合单独代表准确率 |
log_prob |
样本的对数概率 | 概率模型输出 | [B] 或 scalar |
离散时 (-∞, 0] |
适合概率模型评价 |
logits |
未归一化分数 | 模型原始输出 | shape 通常不变 | (-∞, +∞) |
不适合作为最终精度指标 |
logistic/sigmoid |
logit 到概率的映射 | 二分类或多标签 logits | shape 不变 | (0, 1) |
本身不是指标 |
L1 norm
L1 norm 衡量 tensor 的绝对大小:
1 | L1(x) = sum(|x_i|) |
比较两个 tensor 时,通常用 L1 distance:
1 | L1(a, b) = sum(|a_i - b_i|) |
如果取平均,就是 MAE:
1 | MAE(a, b) = mean(|a_i - b_i|) |
用途
- 比较两个 tensor 的数值差异
- 回归任务 loss
- 模型量化、推理框架转换、不同精度计算的误差检查
- L1 正则化,鼓励参数稀疏
Shape 变化
假设:
1 | x: [B, C, H, W] |
整体 L1:
1 | x.abs().sum() |
输出:
1 | scalar |
按样本计算:
1 | x.abs().sum(dim=(1, 2, 3)) |
输出:
1 | [B] |
计算平均绝对误差:
1 | x.abs().mean(dim=(1, 2, 3)) |
输出:
1 | [B] |
精度比较
如果比较数值误差,L1/MAE 是合适指标。
但原始 L1=sum(abs(diff)) 会受 tensor 大小影响,shape 越大,L1 往往越大。
更推荐:
1 | MAE = mean(abs(a - b)) |
Entropy
entropy 衡量概率分布的不确定性。
对于概率分布:
1 | p = [p1, p2, ..., pK] |
要求:
1 | pi >= 0 |
熵定义为:
1 | H(p) = -sum(pi * log(pi)) |
如果分布很集中,熵低。
如果分布很平均,熵高。
用途
- 判断分类模型是否自信
- 强化学习中鼓励探索
- 半监督学习中筛选高置信度样本
- 分析 attention 分布是否集中
Shape 变化
分类任务:
1 | probs: [B, K] |
计算:
1 | entropy = -(probs * probs.log()).sum(dim=-1) |
输出:
1 | [B] |
语言模型:
1 | probs: [B, T, V] |
对词表维度计算:
1 | entropy = -(probs * probs.log()).sum(dim=-1) |
输出:
1 | [B, T] |
值域
如果有 K 个类别:
1 | 0 <= H(p) <= log(K) |
其中:
H(p) = 0:完全确定H(p) = log(K):完全均匀
也可以归一化:
1 | H_norm = H(p) / log(K) |
值域变为:
1 | [0, 1] |
精度比较
entropy 不适合单独作为准确率指标。
原因是:
1 | 低熵只说明模型很自信,不说明模型一定正确。 |
例如模型对错误类别给出 0.99 概率,它的熵很低,但预测是错的。
因此,熵适合分析不确定性,不适合单独比较预测精度。
log_prob
log_prob 表示模型给某个样本或标签分配的对数概率:
1 | log_prob(x) = log p_model(x) |
分类任务中,如果:
1 | probs = [0.1, 0.7, 0.2] |
则:
1 | log_prob = log(0.7) |
概率越大,log_prob 越接近 0。
概率越小,log_prob 越负。
与 loss 的关系
负对数概率就是 NLL:
1 | NLL = -log_prob(target) |
对于 one-hot 分类任务,NLL 等价于 cross entropy loss:
1 | loss = -log p_model(y_true) |
Shape 变化
分类任务:
1 | logits: [B, K] |
计算:
1 | log_probs = torch.log_softmax(logits, dim=-1) |
Shape:
1 | log_probs: [B, K] |
语言模型:
1 | logits: [B, T, V] |
Shape:
1 | log_probs: [B, T, V] |
值域
离散分类中:
1 | p in [0, 1] |
注意:连续分布中的 log_prob 是 log density,不一定小于 0。
精度比较
log_prob/NLL/cross entropy 是概率模型中非常典型的评价指标。
优点是它不仅关心是否预测正确,还关心模型给正确答案的概率有多高。
例如两个模型都预测正确:
1 | 模型 A: 正确类概率 0.51 |
accuracy 一样,但 NLL 会认为模型 B 更好。
比较时需要保证:
- 同一数据集
- 同一标签空间
- 同一 tokenization
- 同一长度归一化方式
- 同一概率建模方式
语言模型中不宜直接比较整句 log_prob,因为句子越长,总 log_prob 越低。
更常用:
1 | mean token NLL |
Logits 与 logistic
logits 是模型输出的未归一化分数:
1 | logits = [2.1, -0.3, 0.7] |
它不是概率,因为:
- 可以为负数
- 不要求和为
1 - 没有固定范围
分类任务中通过 softmax 转成概率:
1 | p_i = exp(logit_i) / sum(exp(logit_j)) |
Shape 通常不变:
1 | logits: [B, K] |
值域变化:
1 | logits: (-∞, +∞) |
logistic/sigmoid
logistic 通常指 sigmoid 函数:
1 | sigmoid(z) = 1 / (1 + exp(-z)) |
用于二分类或多标签分类:
1 | logits: [B, K] |
值域:
1 | logits: (-∞, +∞) |
二分类中:
1 | logit(p) = log(p / (1 - p)) |
训练时常用:
1 | torch.nn.BCEWithLogitsLoss() |
它将 sigmoid 和 binary cross entropy 合并,数值更稳定。
精度比较
raw logits 不适合作为最终精度指标。
原因:
- logits 没有固定值域
- softmax 对整体平移不敏感
- 不同模型的 logit scale 可能不同
- logit 大不一定代表预测更准确,只可能代表更自信
更推荐从 logits 派生指标:
1 | accuracy |
比较数值一致性
适用于:
- FP32 vs FP16
- PyTorch vs ONNX
- 原模型 vs 量化模型
- 不同推理后端输出对齐
推荐指标:
1 | MAE |
如果比较的是概率分布,可以补充:
1 | KL divergence |
Tensor 差异比较指标:KL、JS、Argmax、Top-k
在模型训练、蒸馏、推理对齐、量化评估中,经常需要比较两个 tensor 的差异。例如:
1 | A.shape = [B, ..., C] |
其中:
B:batch 维度...:可选的空间维、序列维,例如[T]、[H, W]C:类别数、词表大小或特征分布维度- 通常沿最后一维
C比较两个 tensor 的分布或预测结果
下面讨论四类常用指标:
1 | KL divergence |
它们关注的差异不同:
| 指标 | 比较对象 | 是否需要概率分布 | 越大越好 | 典型值域 |
|---|---|---|---|---|
| KL divergence | 完整分布差异 | 是 | 否 | [0, +∞) |
| JS divergence | 对称分布差异 | 是 | 否 | [0, ln 2] 或 [0, 1] |
| argmax agreement | 第一预测是否一致 | 否 | 是 | [0, 1] |
| top-k agreement | 前 k 个候选是否一致 | 否 | 是 | [0, 1] |
基本设定
假设有两个 tensor:
1 | x.shape = [B, ..., C] |
如果 x 和 y 是 logits,需要先转成概率分布:
1 | p = softmax(x, dim=-1) |
此时:
1 | x, y: [B, ..., C] # logits |
其中每个位置上的最后一维满足:
1 | sum(p[..., :]) = 1 |
KL divergence 和 JS divergence 比较的是完整概率分布,因此要求输入是概率分布。
argmax agreement 和 top-k agreement 比较的是排序或预测类别,不要求归一化,所以可以直接用于 logits。
KL divergence
KL divergence,全称 Kullback-Leibler divergence,用来衡量一个概率分布 Q 相对于参考分布 P 的差异。
公式为:
1 | D_KL(P || Q) = sum_i P_i * log(P_i / Q_i) |
| 目标 KL | 样本来自 | log_ratio 应该写成 |
k3 期望 |
|---|---|---|---|
| (\mathrm{KL}(P|Q)) | (P) | log_q - log_p |
(\mathrm{KL}(P|Q)) |
| (\mathrm{KL}(Q|P)) | (Q) | log_p - log_q |
(\mathrm{KL}(Q|P)) |
如果比较的是:
1 | p.shape = [B, ..., C] |
则沿类别维 C 求和:
1 | kl.shape = [B, ...] |
如果再做平均:
1 | kl_mean.shape = [] |
即得到一个标量。
KL divergence 的值域是:
1 | [0, +∞) |
含义:
0表示两个分布完全相同- 值越大,说明两个分布差异越大
- KL 不对称:
1 | D_KL(P || Q) != D_KL(Q || P) |
这点非常重要。
例如:
1 | D_KL(P || Q) |
表示以 P 为参考,衡量 Q 对 P 的拟合程度。
在知识蒸馏中,如果 P 是 teacher 分布,Q 是 student 分布,那么常用:
1 | D_KL(P_teacher || Q_student) |
它会惩罚 student 在 teacher 高概率类别上给出过低概率的情况。
KL divergence 的计算示例:
1 | import torch |
shape 变化:
1 | x, y : [B, ..., C] |
需要注意:
- KL 对小概率位置较敏感
- 如果
P_i > 0但Q_i = 0,KL 会趋向无穷 - 实际计算时通常使用
log_softmax或加eps保持数值稳定
JS divergence
JS divergence,全称 Jensen-Shannon divergence,可以看作 KL divergence 的对称、平滑版本。
定义中先构造中间分布:
1 | M = 0.5 * (P + Q) |
然后:
1 | D_JS(P || Q) = 0.5 * D_KL(P || M) + 0.5 * D_KL(Q || M) |
它的特点是:
- 对称:
1 | D_JS(P || Q) = D_JS(Q || P) |
- 有界
- 比 KL 更稳定
- 可以衡量两个分布整体上的差异
如果使用自然对数 ln,值域为:
1 | [0, ln 2] |
即:
1 | [0, 0.693...] |
如果使用以 2 为底的对数,值域为:
1 | [0, 1] |
JS divergence 的计算示例:
1 | log_p = F.log_softmax(x, dim=-1) |
shape 变化:
1 | x, y : [B, ..., C] |
如果希望将 JS divergence 归一化到 [0, 1],可以除以 ln 2:
1 | js_normalized = js / torch.log(torch.tensor(2.0)) |
含义:
0表示两个分布完全相同- 越接近上界,表示两个分布差异越大
- 相比 KL,JS 更适合做两个模型输出分布的对称比较
Argmax agreement
Argmax agreement 比较两个 tensor 在每个位置上预测的最大类别是否一致。
它不关心完整概率分布,只关心:
1 | argmax(x) 是否等于 argmax(y) |
计算方式:
1 | idx_x = torch.argmax(x, dim=-1) |
shape 变化:
1 | x, y : [B, ..., C] |
值域:
1 | [0, 1] |
含义:
1表示所有位置的 top-1 预测完全一致0表示所有位置的 top-1 预测完全不一致0.9表示 90% 的位置 top-1 预测一致
Argmax agreement 的特点:
- 只看最终预测类别
- 不看置信度
- 不看非最大类别的分布
- 对 logits 和 softmax 后的概率结果相同,因为 softmax 不改变排序
例如:
1 | x = [10.0, 1.0, 0.0] |
二者 argmax 都是第 0 类,因此 argmax agreement 为 1。
但两个分布的置信度差异很大,KL/JS 可能不小。
Top-k agreement
Top-k agreement 比较两个 tensor 的前 k 个预测类别是否一致。
常见定义有几种,最常用的是 top-k overlap ratio:
1 | top-k agreement = |TopK(x) ∩ TopK(y)| / k |
即两个 top-k 集合的交集占比。
例如:
1 | TopK(x) = {1, 3, 5} |
则:
1 | overlap = {3, 5} |
计算示例:
1 | k = 5 |
shape 变化:
1 | x, y : [B, ..., C] |
值域:
1 | [0, 1] |
含义:
1表示两个 tensor 的 top-k 集合完全一致0表示两个 tensor 的 top-k 集合完全没有交集0.6表示平均有 60% 的 top-k 候选相同
Top-k agreement 比 argmax agreement 更宽松。
例如:
1 | Top1(x) != Top1(y) |
但如果两个模型的高分候选集合接近,那么:
1 | top-k agreement 仍然可能较高 |
这在大词表语言模型、检索系统、推荐系统中很常见。
还可以定义更严格的 top-k 指标。
第一种是 top-k exact set agreement:
1 | TopK(x) 集合是否完全等于 TopK(y) 集合 |
1 | topk_exact = (overlap == 1.0).float() |
第二种是 ordered top-k agreement:
1 | TopK(x) 的顺序是否完全等于 TopK(y) |
1 | ordered_topk_agree = (topk_x == topk_y).all(dim=-1).float() |
严格程度如下:
1 | ordered top-k agreement |
其中 ordered top-k agreement 最严格,top-k overlap ratio 最平滑。
四类指标的对比
假设:
1 | x, y shape = [B, ..., C] |
整体 shape 变化如下:
| 指标 | 输入 shape | 中间 shape | 输出 shape | 标量汇总 |
|---|---|---|---|---|
| KL divergence | [B, ..., C] |
[B, ..., C] |
[B, ...] |
mean/sum |
| JS divergence | [B, ..., C] |
[B, ..., C] |
[B, ...] |
mean/sum |
| argmax agreement | [B, ..., C] |
[B, ...] |
[B, ...] |
mean |
| top-k agreement | [B, ..., C] |
[B, ..., k] |
[B, ...] |
mean |
值域对比:
| 指标 | 值域 | 最优值 | 方向 |
|---|---|---|---|
| KL divergence | [0, +∞) |
0 |
越小越相似 |
| JS divergence | [0, ln 2] |
0 |
越小越相似 |
| JS normalized | [0, 1] |
0 |
越小越相似 |
| argmax agreement | [0, 1] |
1 |
越大越相似 |
| top-k agreement | [0, 1] |
1 |
越大越相似 |
该如何解读
KL divergence 适合回答:
1 | 两个完整概率分布是否接近? |
它关注概率质量的偏移,尤其关注参考分布中高概率位置是否被另一个分布正确覆盖。
适用于:
- 知识蒸馏
- teacher/student 分布对齐
- 语言模型 logits 分布比较
- 量化前后概率分布偏移分析
JS divergence 适合回答:
1 | 两个分布整体差异有多大? |
它比 KL 更稳定、更对称,适合做模型间输出分布差异的通用度量。
适用于:
- 两个模型输出分布比较
- 量化前后分布漂移
- 不希望区分参考方和被比较方的场景
Argmax agreement 适合回答:
1 | 最终 top-1 决策是否一致? |
它不关心置信度,只关心最终预测类别。
适用于:
- 分类结果一致性
- 量化模型和原模型 top-1 是否一致
- 推理优化前后预测类别是否改变
Top-k agreement 适合回答:
1 | 高概率候选集合是否一致? |
它比 argmax 更宽松,能够反映候选排序的稳定性。
适用于:
- 语言模型 top-k token 对齐
- 检索候选集一致性
- 推荐系统候选集稳定性
- 大类别分类中 top-k 预测对齐
参考实现
下面给出一个统一实现,假设类别维在最后一维:
1 | import torch |
总结
这四个指标不是互相替代关系,而是观察差异的角度不同。
如果关心完整分布差异,使用:
1 | KL divergence |
如果关心最终决策是否一致,使用:
1 | argmax agreement |
如果关心候选集合是否稳定,使用:
1 | top-k agreement |
通常建议组合使用:
1 | JS divergence + argmax agreement + top-k agreement |
原因是:
- JS divergence 反映整体分布漂移
- argmax agreement 反映最终 top-1 决策一致性
- top-k agreement 反映高分候选集合稳定性
例如在量化模型评估中:
1 | JS 很小,argmax agreement 很高 |
说明量化后模型输出基本保持一致。
如果:
1 | JS 较大,但 argmax agreement 很高 |
说明最终预测类别没变,但置信度或非 top-1 分布发生了明显变化。
如果:
1 | JS 很小,但 argmax agreement 较低 |
说明两个分布整体很接近,但 top-1 位置可能经常发生细微交换,常见于多个类别分数非常接近的情况。
比较分类效果
推荐:
1 | accuracy |
如果关注概率校准:
1 | Brier score |
比较回归效果
推荐:
1 | MAE / L1 |
比较语言模型
推荐:
1 | mean token NLL |
任务型评价可以补充:
1 | exact match |
常见误区
L1越小只说明数值更接近,不一定说明任务效果更好。entropy低只说明模型更自信,不一定说明模型更正确。log_prob适合概率模型,但比较时必须保证数据和归一化方式一致。logits不是概率,也不是最终精度指标。- 任何指标都要先明确计算维度和 reduction 方式。
- 标量指标通常来自对 batch、类别、序列或空间维度的归约。
- 比较语言模型时,不要直接比较不同长度文本的总 log_prob。
简要结论
L1 norm:看数值差异,适合数值误差和回归。entropy:看分布不确定性,不适合单独代表准确率。log_prob:看模型给目标的概率,是 NLL 和 cross entropy 的基础。logits:模型原始分数,需要经过 softmax 或 sigmoid 才能解释为概率。- 比较精度前,必须先明确 tensor 的语义、计算维度和归约方式。