Softmax
一组任意大小的分数,怎么变成一组加起来等于 1 的概率?
分类器的最后一层输出什么?
回到那台猜水果的机器。它最后一层给每种水果配了一个神经元——这一课先用苹果、香蕉、西瓜三种举例。 经过若干层 Wx + b 和 ReLU 之后,假设三个神经元的输出是:
这三个数叫 logits(原始分数)。它们的大小可以比较——2.1 > 1.8 > −0.5, 说明网络认为「苹果」的可能性最高。但有两个问题:
- 「苹果」的概率是多少?2.1 这个数字本身没有概率意义。
- 三个数加起来等于 3.4,不等于 1。概率必须加起来等于 1。
交叉熵损失需要的输入是概率。所以需要一个转换:把三个任意实数变成三个加起来等于 1 的非负数。
修补负数:先变成正数再归一化
负数的问题在于:直接除以总和后,原来是负数的项仍然是负数。 要让所有项变成正数,再归一化。 最直觉的修补:把所有数都加上最小值的绝对值,平移到非负区间。
−0.5 + 0.5 = 0
1.8 + 0.5 = 2.3
总和 = 4.9
概率 = [2.6/4.9, 0/4.9, 2.3/4.9] ≈ [0.53, 0, 0.47]
「加上 0.5」是因为最小值是 −0.5,我们选择了把它平移到 0。 但为什么必须是 0?如果把最小值平移到 1,结果就完全不同了: [3.1/6.9, 1/6.9, 2.8/6.9] ≈ [0.45, 0.14, 0.41]。概率的分布随着任意选择的平移量而改变——这不合理。 我们需要一种不依赖「平移量」的转换方法。
问题的核心是:需要一个函数,能把任意实数(包括负数)变成正数, 而且不依赖其他数的绝对大小,只保留相对排序信息。
指数函数:天然无负数
有一个函数对所有实数输出都是正数,而且不需要知道其他项是多少——就是指数函数 。 先看它长什么样:
把三个 logit(苹果 2.1、香蕉 −0.5、西瓜 1.8)分别代进去,负数也变成了正数:
全部除以总和:
这就是 Softmax:对每个 logit 取 e 的指数,再整体归一化。 (第 6 课埋过一个伏笔——「把任意一组实数变成概率分布,正是 Softmax 的工作」。这一课就是来兑现承诺的。)
这正是第 7 课见过的那台机器的输出层——当时只说「softmax 把分数挤成概率」,现在你知道它在里面具体做了什么了。 下面把那台四种水果的机器再搬出来:转旋钮改变四个神经元的分数,看 softmax 如何把它们实时换算成一组加起来 = 100% 的概率:
一个意外的发现:温度参数
指数函数有一个有趣的副效应:它放大了 logits 之间的差距。 2.1 比 1.8 大 17%,但 ——差距被扩大了 35%。 差距越大,最大值的概率越接近 1,其他值越接近 0。
这个「放大程度」是可以调节的——引入一个温度参数 ,把 logits 先除以 ,再做 Softmax:
这就是你使用 ChatGPT 时看到的「temperature」旋钮: 低温(如 0.2)让输出更确定、更保守——适合写代码、做数学; 高温(如 0.8~1.0)让输出更多样、更有创意——适合写故事、头脑风暴。
当某个 logit 是 1000 时, 超出浮点数上限(上溢出)。 解法:先把所有 logit 减去最大值再取指数——数学上等价(分子分母同乘 抵消),但数值上稳定。 这叫 log-sum-exp 技巧,PyTorch 的 F.cross_entropy 已经内置,直接传 logits 即可。
总结
Softmax 解决了「分数→概率」的两个问题(负数 + 不加和为 1): 对每个 logit 取 eˣ(天然非负),再整体归一化。 指数放大差距,温度参数可以反向调节这个放大—— 这就是ChatGPT temperature 的数学来源。
这一课你亲手推导了
- Logits:分类网络最后一层的原始分数,有正有负,不是概率。
- 直接归一化的问题:有负数时会出现负概率;平移量任意导致结果不稳定。
- Softmax:eᶻⁱ / Σeᶻʲ,先取指数消除负数,再归一化;差距被放大。
- 温度参数 T:Softmax(z/T);T 越小越果断,T 越大越随机。
学习小测验
做完这一课,来检测一下核心知识点。选出你的答案后点击「提交」,即可看到正确选项与讲解。
梯度下降与优化器
有了损失和梯度——但步子迈多大?全量数据算梯度为什么行不通?