Softmax 函数是深度学习、分类模型、神经网络和人工智能中非常常见的一个术语。它用来描述一种把多个原始分数转换成概率分布的方法。换句话说Softmax 函数是在回答模型已经给每个类别算出了一个分数怎样把这些分数变成“各类别可能性”的概率。如果说神经网络的最后一层会输出一组类别得分那么 Softmax 函数就是把这些得分转换成可比较、可解释的概率。因此Softmax 常用于多分类任务、神经网络输出层、交叉熵损失、文本分类、图像分类、语言模型和注意力机制是理解分类模型输出的重要基础概念。一、基本概念什么是 Softmax 函数Softmax 函数Softmax Function是一种把一组实数转换成概率分布的函数。假设模型对 K 个类别输出了一组原始分数Softmax 会把第 k 个类别的分数 zₖ 转换为概率 pₖ其中• zₖ 表示第 k 个类别的原始分数• pₖ 表示第 k 个类别经过 Softmax 后的概率• K 表示类别总数• e 表示自然常数• 分母表示所有类别指数值之和Softmax 输出满足两个条件并且也就是说Softmax 输出的每个值都在 0 到 1 之间并且所有类别概率加起来等于 1。从通俗角度看Softmax 可以理解为把多个类别的“竞争分数”转换成“概率份额”。例如模型对三类图片给出原始分数猫2.0狗1.0鸟0.1这些分数本身不是概率不能直接解释为“猫的概率是 2.0”。经过 Softmax 后它们会变成一组概率例如猫约 0.66狗约 0.24鸟约 0.10这时就可以理解为模型认为这张图片最可能是猫。二、为什么需要 Softmax 函数Softmax 之所以重要是因为多分类模型通常不会直接输出概率而是先输出一组原始分数。在神经网络中最后一层通常会产生一个向量这些 z 值通常称为• logits• 原始分数• 未归一化得分它们可以是任意实数[2.4, -0.7, 5.1, 0.3]这些数值本身有大小关系但不满足概率要求• 可能大于 1• 可能小于 0• 总和不一定等于 1因此如果希望模型输出“属于每个类别的概率”就需要一个转换函数。Softmax 的作用就是把任意实数分数转换成一个合法的概率分布。从通俗角度看• 神经网络最后一层给每个类别打分• Softmax 函数把这些分数变成概率这在多分类任务中非常重要。例如在手写数字识别中模型需要判断图片属于 0 到 9 中的哪一类。输出层会产生 10 个分数Softmax 会把这 10 个分数转换成 10 个概率数字 00.01数字 10.02数字 20.03……数字 70.88……最终模型通常选择概率最大的类别作为预测结果。三、Softmax 的核心公式Softmax 的核心公式为这个公式可以分成两步理解。1、指数变换首先对每个分数取指数指数函数有两个作用。第一它会把任意实数变成正数。例如z 2 → e² 0z 0 → e⁰ 1z -3 → e⁻³ 0这样可以保证 Softmax 的分子为正数。第二它会放大较大分数之间的差异。例如分数差 1在指数后会变得更明显分数差 3在指数后会变得非常明显。因此原始分数较高的类别会获得更大的概率。2、归一化然后把每个指数值除以所有指数值之和这一步使所有输出加起来等于 1。因此Softmax 的输出可以被看作概率分布。从通俗角度看Softmax 先把所有类别分数变成正数再按它们的相对大小分配概率。分数越高概率越大分数越低概率越小所有类别共同竞争一个总量为 1 的概率空间。四、如何直观理解 SoftmaxSoftmax 最核心的直觉是它不是单独看某个类别的分数而是看这个类别相对于其他类别有多强。例如有三组 logits情况 A[2, 1, 0]情况 B[10, 9, 8]情况 C[2, 2, 2]情况 A 中第一个类别最高所以它概率最大。情况 B 中虽然分数整体都比情况 A 大很多但三个分数之间的相对差距仍然是 1 和 2。Softmax 更关心相对差距而不是绝对大小。情况 C 中三个类别分数完全相同因此 Softmax 会输出均匀概率[1/3, 1/3, 1/3]从通俗角度看Softmax 像是在分蛋糕• 每个类别的指数分数决定它能分到多少• 分数高的类别分得多• 分数低的类别分得少• 所有类别加起来刚好分完整个蛋糕因此Softmax 输出的不是孤立概率而是各类别之间竞争后的结果。需要注意Softmax 不会改变分数的大小顺序。如果 z₁ 最大那么 Softmax 后的 p₁ 也最大。因此预测类别通常可以直接取 logits 最大值也可以取 Softmax 后概率最大值二者类别结果相同。不过Softmax 后的概率更适合用于解释和计算损失。五、Softmax 与 Sigmoid 的区别Softmax 经常和 Sigmoid 函数放在一起比较。1、Sigmoid 适合二分类或多标签任务Sigmoid 函数公式为它把一个实数压缩到 0 到 1 之间。在二分类任务中可以用 Sigmoid 输出正类概率例如• 是否为垃圾邮件是 / 否• 是否患病是 / 否• 是否点击广告是 / 否Sigmoid 也常用于多标签分类。多标签任务中一个样本可以同时属于多个类别。例如一张图片可以同时包含人、狗、汽车、街道这时每个标签都可以独立判断是否存在。2、Softmax 适合互斥多分类任务Softmax 适合多分类任务尤其是类别互斥的情况。例如• 手写数字只能是 0 到 9 中的一个• 一张动物图片只标为猫、狗、鸟中的一个• 新闻主题只归入一个主类别Softmax 会让所有类别共享一个概率总和这表示各类别之间是竞争关系。3、二者的直观区别可以简单理解为• Sigmoid每个类别单独判断“是不是”• Softmax多个类别一起竞争“是哪一个”例如• 多标签任务一张图片可以既有“人”又有“车” → 用 Sigmoid• 多分类任务一张图片只能属于“猫 / 狗 / 鸟”之一 → 用 Softmax从通俗角度看Sigmoid 像多个独立开关Softmax 像多个候选答案抢一个总概率。六、Softmax 与交叉熵损失Softmax 常常和交叉熵损失一起使用。在多分类任务中模型先输出 logits然后用 Softmax 得到预测概率如果真实类别是第 c 类那么交叉熵损失可以写为其中• L 表示损失• p_c 表示模型分配给真实类别的概率这个公式的含义是模型给真实类别的概率越高损失越小给真实类别的概率越低损失越大。例如真实类别是“猫”模型给“猫”的概率是 0.90 → 损失较小模型给“猫”的概率是 0.10 → 损失较大如果真实标签使用 one-hot 编码交叉熵可以写为其中• yₖ 表示第 k 类的真实标签• 如果第 k 类是真实类别则 yₖ 1• 否则 yₖ 0由于只有真实类别位置为 1所以这个式子本质上仍然等价于从通俗角度看Softmax 负责把分数变成概率交叉熵负责惩罚模型没有把足够高的概率给真实类别。这就是多分类神经网络训练中非常常见的组合。七、Softmax 在注意力机制中的作用Softmax 不只用于分类输出层也广泛用于注意力机制。在 Transformer 的缩放点积注意力中公式为其中• Q 表示查询矩阵• K 表示键矩阵• V 表示值矩阵• QKᵀ 表示 Query 与 Key 的相似度分数• dₖ 表示键向量维度• Softmax 把相似度分数转换成注意力权重在这里Softmax 的作用不是输出类别概率而是输出注意力权重。这些权重同样满足其中• αᵢ 表示第 i 个位置的注意力权重• 权重越大表示模型越关注该位置从通俗角度看在注意力机制中Softmax 把“相关性分数”转换成“关注比例”。例如当模型处理某个词时会计算它与其他词的相关性。Softmax 会把这些相关性分数转换为权重关注第 1 个词0.10关注第 2 个词0.65关注第 3 个词0.25然后模型根据这些权重加权汇总信息。因此Softmax 是注意力机制中“分配关注度”的关键步骤。八、Softmax 的数值稳定性问题Softmax 公式中包含指数函数如果 zₖ 很大指数值可能非常大导致计算机溢出。例如e¹⁰⁰⁰这个数非常巨大普通浮点计算可能无法表示。为了解决这个问题实际计算 Softmax 时通常会先减去最大值其中• z_max 表示所有 logits 中的最大值这种变换不会改变 Softmax 的结果。原因是对所有 z 同时减去同一个常数不会改变相对比例其中 c 可以取 z_max。从通俗角度看减去最大值只是为了让数字更安全不会改变各类别之间的相对竞争关系。因此在手写 Softmax 函数时推荐使用稳定版本z z - np.max(z)在深度学习框架中通常不需要手动处理因为框架内部已经做了数值稳定优化。另外在训练分类模型时很多框架会把 Softmax 和交叉熵合并实现例如 PyTorch 的 CrossEntropyLoss。这通常比先手动 Softmax 再计算交叉熵更加稳定。九、Softmax 的优势、局限与使用注意事项1、Softmax 的主要优势Softmax 最大的优势是可以把任意实数分数转换成概率分布。它让多分类模型的输出更容易解释• 每个类别一个概率• 所有概率加起来等于 1• 概率最大者通常作为预测类别其次Softmax 保留了类别之间的相对竞争关系。分数越高的类别得到的概率越大。再次Softmax 可以和交叉熵损失自然配合形成多分类神经网络的标准训练方式。从通俗角度看Softmax 的优势在于它把模型的多个类别打分转换成一组可比较的概率。2、Softmax 的主要局限Softmax 也有局限。首先Softmax 适合互斥多分类不适合多标签分类。如果一个样本可以同时属于多个类别Softmax 的“总和为 1”会强迫类别竞争可能不合理。其次Softmax 输出的概率不一定是真正可靠的置信度。神经网络有时会过度自信即使预测错误也可能给出很高概率。再次Softmax 对 logits 的相对差距很敏感。如果某个类别分数明显大于其他类别它可能获得非常接近 1 的概率。此外Softmax 本身不负责学习它只是一个转换函数。模型能否预测准确仍取决于特征表示、网络结构、训练数据和损失函数。3、使用 Softmax 时需要注意的问题使用 Softmax 时需要注意以下几点• 互斥多分类任务适合使用 Softmax• 多标签任务通常使用 Sigmoid• 训练时通常搭配交叉熵损失• 不要把 logits 直接当成概率• 手写 Softmax 时要注意数值稳定性• 在 PyTorch 中使用 CrossEntropyLoss 时不要先手动 Softmax• Softmax 概率高不一定等于模型绝对可靠从实践角度看Softmax 是多分类输出层中的基础工具但它输出的是模型归一化后的概率估计不应被无条件当作真实置信度。十、Python 示例下面给出几个简单示例用来帮助理解 Softmax 函数的计算和使用。示例 1手动实现 Softmaximport numpy as np def softmax(z): Softmax函数将分数向量转换为概率分布 exp_z np.exp(z) # 对每个分数取指数 return exp_z / np.sum(exp_z) # 归一化使总和为1 # 三个类别的原始分数scores np.array([2.0, 1.0, 0.1]) # 转换为概率分布probabilities softmax(scores) print(原始分数, scores)print(Softmax 概率, probabilities)print(概率总和, probabilities.sum()) # 验证和为1这个例子中Softmax 会把三个类别分数转换成概率分布。需要注意这个版本没有处理数值稳定性。如果分数很大可能出现溢出。示例 2数值稳定版本 Softmaximport numpy as np def stable_softmax(z): 数值稳定的Softmax函数通过减去最大值防止溢出 z z - np.max(z) # 减去最大值使最大值为0避免exp(z)过大 exp_z np.exp(z) # 计算指数 return exp_z / np.sum(exp_z) # 归一化为概率分布 # 大数值分数直接exp会导致溢出scores np.array([1000.0, 999.0, 998.0]) probabilities stable_softmax(scores) print(Softmax 概率, probabilities)print(概率总和, probabilities.sum())这个版本先减去最大值可以避免指数函数溢出。从数学上看减去同一个常数不会改变 Softmax 输出结果只是让计算更稳定。示例 3Softmax 与预测类别import numpy as np def stable_softmax(z): 数值稳定的Softmax函数减去最大值防止溢出 z z - np.max(z) # 平移输入使最大值为0 exp_z np.exp(z) # 指数运算 return exp_z / np.sum(exp_z) # 归一化得到概率 # 类别名称class_names [猫, 狗, 鸟] # 模型输出的原始分数logitsscores np.array([2.0, 1.0, 0.1]) # 转换为概率分布probabilities stable_softmax(scores) # 取概率最大的类别作为预测结果pred_index np.argmax(probabilities) # 最大概率的索引pred_class class_names[pred_index] # 索引对应的类别名 print(类别概率)for name, prob in zip(class_names, probabilities): print(name, :, prob) print(预测类别, pred_class)这个例子展示了多分类预测的基本过程logits → Softmax 概率 → 选择概率最大类别因为 Softmax 不改变分数大小顺序所以 np.argmax(scores) 和 np.argmax(probabilities) 会得到相同类别。示例 4PyTorch 中的 Softmax 与 CrossEntropyLossimport torchimport torch.nn as nn # 模型输出的原始分数logits1个样本3个类别logits torch.tensor([[2.0, 1.0, 0.1]]) # 真实类别索引0表示第一类如猫target torch.tensor([0]) # 通过Softmax将logits转换为概率分布dim1表示对类别维度probabilities torch.softmax(logits, dim1)print(Softmax 概率, probabilities) # 交叉熵损失结合了LogSoftmax NLLLoss直接输入logits和标签loss_fn nn.CrossEntropyLoss()loss loss_fn(logits, target) print(交叉熵损失, loss.item()) # 损失 -ln(softmax概率对应真实类的值)需要注意nn.CrossEntropyLoss() 接收的是 logits而不是已经经过 Softmax 的概率。也就是说PyTorch 内部会完成类似 LogSoftmax Negative Log Likelihood 的稳定计算。因此使用 CrossEntropyLoss 时通常不要在模型输出后手动加 Softmax。 小结Softmax 函数是一种把多个原始分数转换成概率分布的函数常用于互斥多分类任务的输出层。它通过指数变换放大分数差异再通过归一化使所有类别概率之和为 1。Softmax 常与交叉熵损失配合使用也常出现在注意力机制中用来把相关性分数转换成注意力权重。对初学者而言可以把 Softmax 理解为让多个类别根据模型打分共同竞争一个总概率分数越高分到的概率越大。“点赞有美意赞赏是鼓励”