情感模型吐出 4.2 和 -1.7 这样的分数,它们不是概率。softmax 把它们变成一个加起来等于一的分布。为什么先减掉最大值再取指数?
分类器经常输出一组原始分数,称为 logits。Softmax 把分数变成总和为一的正数,使其可以作为概率分布使用。关键技巧是在取指数前减去最大分数,避免大数值溢出。 你还会用对数损失衡量自信的错误,并把概率变成审核阈值。
取指数并归一化
Softmax 对每个 logit 取 exp,再除以总和。exp 让所有值变为正数并保持顺序,除法让结果总和为一。logit 越大,概率越大,但输出并不代表模型一定正确。
import math
def softmax(logits):
exps = [math.exp(x) for x in logits]
total = sum(exps)
return [x / total for x in exps]
print([round(p, 3) for p in softmax([2, 0])])正数,且总和为一
减去最大值保持稳定
exp(1000) 对浮点数来说太大,即使最终比例很普通。给每个 logit 减去最大值,可以在不改变比例的情况下平移所有数值。这是标准的稳定实现,不是近似。
import math
def softmax(logits):
largest = max(logits)
exps = [math.exp(x - largest) for x in logits]
total = sum(exps)
return [x / total for x in exps]
print([round(p, 3) for p in softmax([1000, 1000])])先平移,再取指数
用温度改变尖锐程度
在 softmax 前把每个 logit 除以一个正温度。温度小于一会让最大分数更占优势;温度大于一会让分布更平缓。温度改变的是输出中的不确定性,不是底层证据。
import math
def softmax(logits, temperature=1.0):
scaled = [x / temperature for x in logits]
largest = max(scaled)
exps = [math.exp(x - largest) for x in scaled]
total = sum(exps)
return [x / total for x in exps]
print([round(p, 3) for p in softmax([2, 0], 0.5)])
print([round(p, 3) for p in softmax([2, 0], 2.0)])温度越低越尖锐
看整个分布,而不只看赢家
最大概率对应 argmax,但其他数值同样携带信息。[0.34, 0.33, 0.33] 与 [0.98, 0.01, 0.01] 的赢家相同,含义却完全不同。检查数值是否有限,并确认总和约等于一。
probs = [0.7, 0.2, 0.1]
winner = max(range(len(probs)), key=probs.__getitem__)
print(winner)
print(round(sum(probs), 3))argmax 加上基本检查
对数损失惩罚自信的错误
对单条样本,对数损失是正确类别概率的负对数。以 0.9 的概率答对贡献很小;自信地答错贡献很大。对各样本损失取平均,并在取对数前截断精确的零。
import math
for probability in [0.9, 0.5, 0.01]:
loss = -math.log(probability)
print(probability, round(loss, 3))置信度改变惩罚
把概率变成审核阈值
概率只有选定阈值后才会变成动作。如果自动答错的代价很高,就把不确定的样本送去审核。应在验证集上,根据审核与错误的相对成本选择阈值,而不是在测试集上选。
def action(probability, threshold=0.8):
return "accept" if probability >= threshold else "review"
for probability in [0.95, 0.72, 0.40]:
print(probability, action(probability))置信度闸门,而不是猜测
本课要点
- Softmax 把任意 logits 变成总和为一的正数。
- 取 exp 前减去最大 logit,避免溢出。
- 温度小于一会让分布更尖锐,大于一会更平缓。
- 最大概率是 argmax,但整个分布都有信息。
- 概率分布不等于正确性保证。
- 对数损失惩罚自信的错误;阈值把概率变成考虑成本的动作。
常见错误
- 直接对巨大 logits 取 exp,没有先减去最大值。
- 归一化之后才应用温度,而不是在 softmax 前。
- 把最高概率当成答案一定为真的证明。
- 把 softmax 的最大值当成确定性,却不检查校准或错误成本。
编写接受温度的稳定 softmax,对 logits [3, 1, 0] 分别用温度 0.5 和 2.0 打印保留三位小数的分布。
动手试试
改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。