文章

Softmax:把分数变成概率分布

从直觉、公式、数值例子、Sigmoid 对比和温度参数理解 Softmax:它如何把任意实数分数转换为概率分布。

Softmax:把分数变成概率分布

Softmax 是深度学习里最常见的归一化函数之一。它做的事情可以先用一句话概括:

把一组任意实数分数,转换成一组总和为 1 的概率分布。

这组输入分数通常叫 logits。logits 可以为正、为负、很大、很小,本身还不是概率。Softmax 通过指数运算和归一化,把它们变成可以比较、可以解释、也可以继续参与训练的概率。

这篇文章按下面的顺序展开:

阶段要解决的问题关键图示
直觉与公式Softmax 到底把什么变成什么?logits 到概率分布的流程
数值例子一个向量如何一步步算出概率?表格计算
指数放大为什么大值会被强调?指数函数曲线
名字来源为什么它叫 Softmax?和 argmax 对比
Sigmoid 对比Sigmoid 和 Softmax 到底差在哪?Sigmoid 曲线
温度参数为什么温度能让分布变平或变尖?不同温度下的概率柱状图
注意力机制Softmax 在 Transformer 里做什么?权重分布解释
  1. 为什么需要 Softmax
  2. 公式
  3. 一个完整例子
  4. 指数放大的作用
    1. 指数函数曲线
  5. 为什么叫 Softmax
  6. 和 Sigmoid 的区别
    1. Sigmoid 在做什么
    2. Sigmoid 适合二分类
    3. Sigmoid 也适合多标签分类
    4. Softmax 是互斥竞争
    5. 关键区别
  7. 温度参数
  8. 在注意力机制里的作用
  9. 小结

为什么需要 Softmax

假设一个三分类模型输出了三个分数:

\[z = [2.0,\ 1.0,\ 0.1]\]

这三个数只能说明模型更偏向第一个类别,但它们还不是概率:

  • 它们不在 \(0\) 到 \(1\) 之间。
  • 它们的和不是 \(1\)。
  • 分数之间的差异还没有被转换成“相对可能性”。

Softmax 解决的就是这个问题:保留“分数越大越重要”的排序,同时把所有类别放进同一个概率分布里竞争。

flowchart LR
  Logits["logits<br/>任意实数分数"] --> Exp["指数放大<br/>强调较大分数"]
  Exp --> Sum["归一化<br/>除以指数和"]
  Sum --> Prob["概率分布<br/>每项在 0 到 1 之间,整体和为 1"]

  style Logits fill:#e3f2fd
  style Exp fill:#fff3bf
  style Sum fill:#e8f5e9
  style Prob fill:#ffe3e3

公式

对于一个包含 \(K\) 个元素的向量:

\[\mathbf{z} = [z_1,\ z_2,\ \dots,\ z_K]\]

Softmax 的第 \(i\) 个输出定义为:

\[\mathrm{softmax}(\mathbf{z})_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}\]

其中:

  • \(z_i\) 是第 \(i\) 个类别的原始分数。
  • \(e^{z_i}\) 把分数转换成正数,并放大较大分数之间的差异。
  • \(\sum_{j=1}^{K} e^{z_j}\) 是所有指数分数的总和。
  • 除以总和之后,每个输出都变成整体中的占比。

因此 Softmax 的输出满足:

\[0 < \mathrm{softmax}(\mathbf{z})_i < 1\]

并且:

\[\sum_{i=1}^{K} \mathrm{softmax}(\mathbf{z})_i = 1\]

这就是它能被解释成概率分布的原因。

一个完整例子

继续看这个向量:

\[z = [2.0,\ 1.0,\ 0.1]\]

第一步,计算每个元素的指数:

\[e^{2.0} \approx 7.389\] \[e^{1.0} \approx 2.718\] \[e^{0.1} \approx 1.105\]

第二步,计算指数和:

\[7.389 + 2.718 + 1.105 \approx 11.212\]

第三步,分别除以指数和:

类别logit指数值Softmax 概率
类别 1\(2.0\)\(7.389\)\(7.389 / 11.212 \approx 0.659\)
类别 2\(1.0\)\(2.718\)\(2.718 / 11.212 \approx 0.242\)
类别 3\(0.1\)\(1.105\)\(1.105 / 11.212 \approx 0.099\)

最终输出是:

\[\mathrm{softmax}(z) \approx [0.659,\ 0.242,\ 0.099]\]

也就是说,模型认为三个类别的相对概率大约是:

  • 类别 1:\(65.9\%\)
  • 类别 2:\(24.2\%\)
  • 类别 3:\(9.9\%\)

注意这里的概率是相对这三个候选类别而言的。Softmax 不会凭空保证模型一定正确,它只是把模型给出的分数转换成一个归一化分布。

指数放大的作用

Softmax 里最关键的一步是指数运算。指数函数会把较大的输入放大得更明显。

例如:

输入指数
\(0.1\)\(1.105\)
\(1.0\)\(2.718\)
\(2.0\)\(7.389\)

输入从 \(1.0\) 到 \(2.0\) 只差 \(1\),但指数值从 \(2.718\) 变成 \(7.389\)。这会让较大分数在归一化后占据更大的比例。

所以 Softmax 同时做了两件事:

  • 用指数函数强化较大 logit 的优势。
  • 用归一化把所有候选项压到同一个概率分布里。

只看表格还不够直观。下面用指数函数曲线看这件事。

指数函数曲线

Softmax 里用到的是指数函数 \(e^x\)。它的特点是:输入越大,增长越快。

x y 0 0 1 e⁰=1 指数函数:高分会被快速放大
指数函数不会把输出限制在 1 以内,它会快速放大正数输入。

这解释了 Softmax 为什么会强调较大的 logit。比如 \(2.0\) 只比 \(1.0\) 大 \(1\),但:

\[e^{2.0} \approx 7.389,\quad e^{1.0} \approx 2.718\]

指数之后,较大分数的优势被明显放大。

为什么叫 Softmax

有了“指数会放大高分”的直觉后,再看 Softmax 这个名字就更自然了。理解 Softmax,最好把它和 argmax 放在一起看。

argmax 是“硬”的最大值选择:只保留最大分数对应的位置,其它位置全部丢掉。对于:

\[[2.0,\ 1.0,\ 0.1]\]

argmax 对应的 one-hot 结果可以理解为:

\[[1,\ 0,\ 0]\]

它只告诉我们“第一个最大”,不再保留第二个和第三个选项的相对差距。

Softmax 则是“软”的最大值选择:

\[[0.659,\ 0.242,\ 0.099]\]

最大值仍然得到最高概率,但其它选项不会被直接清零。它们仍然保留了相对可能性。

方法输出特点
argmaxone-hot 选择只保留最大项,信息最硬
softmax概率分布强调最大项,同时保留其它项的相对可能性

这也是“softmax”这个名字的含义:它像 max 一样偏向最大值,但方式更柔和。

和 Sigmoid 的区别

Sigmoid 和 Softmax 很容易混在一起,因为它们都会输出 \(0\) 到 \(1\) 之间的数。但这只是表面相似。真正的区别在于:

Sigmoid 把“一个分数”变成“一个判断的概率”;Softmax 把“一组分数”变成“一组互斥选项的概率分布”。

先看 Sigmoid。

Sigmoid 在做什么

Sigmoid 处理的是单个实数:

\[\sigma(x) = \frac{1}{1 + e^{-x}}\]

这个公式的作用是:不管输入 \(x\) 是多大、多小、正数还是负数,都把它压到 \(0\) 和 \(1\) 之间。

输入 \(x\)Sigmoid 输出直觉
很大的正数接近 \(1\)这个判断很可能成立
\(0\)\(0.5\)正反两边差不多
很大的负数接近 \(0\)这个判断很可能不成立

例如:

\[\sigma(2.0) = \frac{1}{1 + e^{-2.0}} \approx 0.881\] \[\sigma(0) = \frac{1}{1 + e^{0}} = 0.5\] \[\sigma(-2.0) = \frac{1}{1 + e^{2.0}} \approx 0.119\]

画出来就是一条 S 形曲线。输入很小的时候输出接近 \(0\),输入很大的时候输出接近 \(1\),输入为 \(0\) 时输出正好是 \(0.5\)。

x y 0 0 0.5 1 σ(0)=0.5 Sigmoid:把单个分数压到 0 到 1
Sigmoid 的输出有上下界:再大的正数也只会接近 1,再小的负数也只会接近 0。

这张图对应前面的直觉:

  • \(x\) 越大,\(\sigma(x)\) 越接近 \(1\)。
  • \(x\) 越小,\(\sigma(x)\) 越接近 \(0\)。
  • \(x = 0\) 时,正反两边势均力敌,所以输出 \(0.5\)。

所以 Sigmoid 的直觉不是“在多个类别里分配概率”,而是回答一个是非问题:

这个东西是不是某一类?这个标签是否成立?这个事件是否发生?

Sigmoid 适合二分类

比如做垃圾邮件识别,模型最后只输出一个 logit:

\[x = 2.0\]

经过 Sigmoid:

\[\sigma(2.0) \approx 0.881\]

可以解释为:模型认为这封邮件是垃圾邮件的概率约为 \(88.1\%\)。

这里其实只有一个判断:

  • 是垃圾邮件
  • 不是垃圾邮件

如果 “是垃圾邮件” 的概率是 \(0.881\),那 “不是垃圾邮件” 的概率可以理解为:

\[1 - 0.881 = 0.119\]

这就是二分类里 Sigmoid 很自然的地方:一个输出就够了,因为正类和负类互为补集。

flowchart LR
  Logit["一个 logit<br/>垃圾邮件分数"] --> Sigmoid["sigmoid"]
  Sigmoid --> Prob["一个概率<br/>是垃圾邮件的概率"]
  Prob --> Complement["1 - p<br/>不是垃圾邮件的概率"]

  style Logit fill:#e3f2fd
  style Sigmoid fill:#fff3bf
  style Prob fill:#e8f5e9
  style Complement fill:#ffe3e3

Sigmoid 也适合多标签分类

再看一个更容易和 Softmax 搞混的场景:图片标签识别。

一张图片可以同时包含多个标签:

  • 有人
  • 有车
  • 在夜晚
  • 在海边

这些标签不是互斥的。一张图完全可以既“有人”,又“有车”,还“在夜晚”。

这种情况下,模型可以给每个标签各输出一个 logit,然后分别做 Sigmoid:

标签logitSigmoid 概率含义
\(2.0\)\(0.881\)很可能有人
\(1.2\)\(0.768\)也可能有车
夜晚\(0.7\)\(0.668\)可能是夜晚
海边\(-1.5\)\(0.182\)不太像海边

这些概率不需要加起来等于 \(1\)。因为它们不是在争夺同一个名额,而是在分别回答四个独立问题:

  • 这张图有没有人?
  • 这张图有没有车?
  • 这张图是不是夜晚?
  • 这张图是不是海边?

这就是 Sigmoid 和 Softmax 的关键分界线。

Softmax 是互斥竞争

Softmax 处理的是一整个向量。它让多个候选项共享同一个总概率 \(1\),因此更适合互斥类别的多分类问题。

比如手写数字识别,输入图片只能是 \(0\) 到 \(9\) 中的一个数字。模型可以输出 10 个 logits:

\[[z_0,\ z_1,\ z_2,\ \dots,\ z_9]\]

经过 Softmax 后,得到 10 个概率:

\[[p_0,\ p_1,\ p_2,\ \dots,\ p_9]\]

并且:

\[\sum_{i=0}^{9} p_i = 1\]

这里的 10 个类别在竞争同一个总概率。某个数字的概率变高,通常意味着其它数字的概率要被压低。

关键区别

对比项SigmoidSoftmax
核心问题这个判断是否成立?这些互斥选项里哪个更可能?
输入方式单个 logit,或多个 logit 分别独立处理一组 logits 整体处理
输出含义每个输出是一个独立概率整体输出是一个概率分布
概率和多个输出不要求和为 1所有输出和为 1
类别关系可以不互斥通常互斥
典型场景二分类、多标签分类单标签多分类、注意力权重

一个简单判断标准是:

如果多个标签可以同时成立,通常用 Sigmoid;如果多个类别彼此竞争、只能选一个,通常用 Softmax。

也可以换成更口语化的判断:

  • Sigmoid 像是在做多道判断题,每一道都回答“是”或“不是”。
  • Softmax 像是在做单选题,所有选项一起竞争一个答案。

温度参数

Softmax 还经常和温度参数一起使用:

\[\mathrm{softmax}(\mathbf{z})_i = \frac{e^{z_i / \tau}}{\sum_{j=1}^{K} e^{z_j / \tau}}\]

其中 \(\tau\) 是 temperature。

温度效果直觉
\(\tau = 1\)标准 Softmax不额外调整分布
\(\tau > 1\)分布更平滑分数差距被压小,模型更不确定
\(\tau < 1\)分布更尖锐分数差距被放大,模型更自信

温度越高,输出越接近平均分布;温度越低,输出越接近 argmax。

Softmax 的输入是向量,所以它不像 Sigmoid 那样对应一条单变量曲线。看温度参数时,更直观的画法是:固定一组 logits,看不同温度下输出概率怎么变化。

仍然使用这组 logits:

\[[2.0,\ 1.0,\ 0.1]\]
Softmax:温度改变概率分布的尖锐程度 0 0.5 1 τ = 0.5 0.864 τ = 1 0.659 τ = 2 0.502 类1 类2 类3 类1 类2 类3 类1 类2 类3
同一组 logits 下,低温更接近 argmax,高温会给次优选项更多概率。

图里三组柱子对应同一组 logits 的三种 Softmax:

温度输出概率直觉
\(\tau = 0.5\)\([0.864,\ 0.117,\ 0.019]\)最大项非常突出
\(\tau = 1\)\([0.659,\ 0.242,\ 0.099]\)标准 Softmax
\(\tau = 2\)\([0.502,\ 0.304,\ 0.194]\)分布更平滑,次优项权重更高

这就是为什么温度参数常出现在知识蒸馏和生成模型采样里。知识蒸馏里,提高温度可以让学生模型看到教师模型对非最高类别的细腻判断;生成模型里,调整温度可以控制输出更保守还是更多样。

在注意力机制里的作用

Softmax 不只用于分类输出层,也用于 Transformer 的注意力机制。

在注意力里,模型会先计算 Query 和 Key 的相似度,得到一组原始注意力分数:

\[S = QK^T\]

这些分数同样不是概率。它们只是“这个 token 和那个 token 有多相关”的原始打分。经过 Softmax 后:

\[A = \mathrm{softmax}(S)\]

每一行就变成一个注意力分布,表示当前位置应该从其它位置分别拿多少信息。

再用这个权重矩阵去加权 Value:

\[O = AV\]

所以在注意力机制里,Softmax 的角色不是“预测类别”,而是“把相关性分数变成权重分布”。

场景Softmax 输入Softmax 输出
多分类输出层每个类别的 logits每个类别的概率
注意力机制token 之间的相似度分数每个 token 对其它 token 的注意力权重

小结

Softmax 的核心可以压缩成三点:

  • 它把任意实数向量转换成概率分布,输出每项在 \(0\) 到 \(1\) 之间,整体和为 \(1\)。
  • 它是 argmax 的“软”版本,强调最大值,但保留其它选项的相对可能性。
  • 它不仅用于多分类输出层,也用于 Transformer 里的注意力权重归一化。

如果只记住一个公式,就是:

\[\mathrm{softmax}(\mathbf{z})_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}\]

如果只记住一个直觉,就是:

Softmax 先用指数突出高分,再用归一化让所有候选项在同一个概率池里竞争。

本文由作者按照 CC BY 4.0 进行授权