4. 概率输出与分数:模型输出与阈值的关系
在可解释 AI 的阈值调整流程中,理解模型输出的原始数值形态是第一步。模型不会直接输出“是/否”的最终决策,而是输出一个连续分数或概率,再由阈值将其映射为离散类别。本节将详细拆解 logits、softmax 概率、sigmoid 分数这三种常见输出形式,以及它们与阈值之间的核心关系。
4.1 三种输出形态的定义与对比
不同模型架构和任务类型会输出不同形态的原始分数。下表从数值范围、含义和阈值适用性三个维度进行对比:
| 输出形态 | 数值范围 | 核心含义 | 阈值调整方式 |
|---|---|---|---|
| Logits | (-∞, +∞) | 模型最后一层线性变换的原始输出,未经过任何概率归一化 | 直接对 logits 设定截断值;或先转换为概率再调阈值 |
| Softmax 概率 | [0, 1],且所有类别概率之和 = 1 | 多分类任务中,将 logits 向量归一化为概率分布 | 对每个类别的概率设定独立阈值(通常默认 0.5) |
| Sigmoid 分数 | (0, 1) | 二分类或多标签任务中,将单个 logit 压缩到 (0,1) 区间 | 对每个输出节点设定独立阈值(通常默认 0.5) |
关键区分: Softmax 强制所有类别概率总和为 1,适合互斥分类(如手写数字识别);Sigmoid 对每个类别独立计算,适合多标签分类(如一张图片同时包含“猫”和“狗”)。
4.2 从 Logits 到概率的转换流程
下图展示了从模型原始 logits 到最终决策标签的完整数据流,以及阈值在其中的作用位置:
4.3 如何获取原始分数
在实际开发中,获取模型原始分数(而非仅最终标签)是进行阈值分析和可解释性分析的前提。以下是三种主流框架的获取方式:
4.3.1 Scikit-learn 模型
使用 predict_proba() 或 decision_function() 方法:
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train)
# 获取 softmax 概率(二分类返回两列:负类概率、正类概率)
probs = model.predict_proba(X_test) # shape: (n_samples, n_classes)
# 获取决策函数值(相当于 logits)
scores = model.decision_function(X_test) # shape: (n_samples,)
4.3.2 PyTorch 模型
在推理时关闭梯度计算,手动提取 logits 并应用 softmax:
import torch
import torch.nn.functional as F
model.eval()
with torch.no_grad():
logits = model(X_tensor) # 原始 logits,shape: (batch, n_classes)
probs = F.softmax(logits, dim=1) # 转换为概率
# 对于二分类,也可使用 torch.sigmoid(logits)
4.3.3 TensorFlow / Keras 模型
通过设置模型输出层为线性激活(或直接访问 logits 层):
import tensorflow as tf
# 方式一:构建时保留 logits 输出
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1, activation=None) # 输出 logits
])
# 方式二:从已有模型中提取 logits 层输出
logits_model = tf.keras.Model(inputs=model.input,
outputs=model.layers[-1].output)
logits = logits_model.predict(X_test)
# 手动应用 sigmoid 得到概率
probs = tf.sigmoid(logits).numpy()
实践建议: 在模型部署或可解释性分析时,始终保留输出原始 logits 或概率的接口,而不是只输出最终标签。这样可以在不重新训练模型的情况下,灵活调整阈值并观察不同阈值下的性能变化。
4.4 阈值与概率分数的映射关系
阈值本质上是一个截断点:当模型输出的概率(或分数)大于等于阈值时,预测为正类;否则为负类。下图展示了不同阈值对二分类决策边界的影响:
4.5 获取原始分数的注意事项
- 数值稳定性: 直接从 logits 计算 softmax 时,建议先减去最大值(
logits - max(logits)),防止指数运算溢出。 - 多分类 vs 多标签: 多分类使用 softmax,阈值通常对所有类别统一调整;多标签使用 sigmoid,每个标签可独立设置阈值。
- 校准问题: 某些模型(如未校准的 SVM、提升树)输出的概率可能不是真实概率,需通过 Platt 缩放或 Isotonic 回归进行校准后再调阈值。
- 保存原始分数: 在模型评估和监控阶段,建议将原始概率/分数与预测标签一并保存到日志或数据库,便于后续回溯分析。
常见误区: 不要直接使用
model.predict() 返回的标签进行阈值分析,因为该标签已经使用了默认阈值(通常为 0.5)。必须使用 predict_proba() 或等效接口获取原始概率,才能进行灵活的阈值调整实验。