概述

log_softmax 就是稳定版的:

log⁡(softmax(x)) \log(\text{softmax}(x)) log(softmax(x))

它把模型输出的原始分数变成对数概率,常用于多分类任务。


1. softmax:把分数变成概率

神经网络最后一层通常输出 logits,比如:

[2.0,1.0,0.0] [2.0, 1.0, 0.0] [2.0,1.0,0.0]

这些数不是概率,可能为负、可能大于 1、和也不为 1。

softmax 负责把它们变成概率:

softmax(x)i=exp⁡(xi)∑jexp⁡(xj) \text{softmax}(x)_i = \frac{\exp(x_i)}{\sum_j \exp(x_j)} softmax(x)i​=∑j​exp(xj​)exp(xi​)​

例如:

[2.0,1.0,0.0]→[0.665,0.245,0.090] [2.0, 1.0, 0.0] \rightarrow [0.665, 0.245, 0.090] [2.0,1.0,0.0]→[0.665,0.245,0.090]

特点:

  • 每个值都大于 0;
  • 所有值加起来等于 1;
  • 可以表示每个类别的预测概率。

所以,softmax 的作用是:分数变概率。


2. log:把概率变成损失

多分类训练常用交叉熵损失。假设真实类别是第 yyy 类,模型预测它的概率是 pyp_ypy​。

我们希望 pyp_ypy​ 越大越好,等价于让下面这个值越小越好:

−log⁡py -\log p_y −logpy​

这就是负对数似然损失。

例如:

  • py=0.9p_y = 0.9py​=0.9,损失 −log⁡0.9≈0.105-\log 0.9 \approx 0.105−log0.9≈0.105,很小;
  • py=0.01p_y = 0.01py​=0.01,损失 −log⁡0.01≈4.605-\log 0.01 \approx 4.605−log0.01≈4.605,很大。

所以,log 的作用是:衡量模型对真实类别的预测有多差。


3. log_softmax:把两步合在一起

既然交叉熵需要:

log⁡(softmax(x)) \log(\text{softmax}(x)) log(softmax(x))

那就可以直接定义一个函数:

log_softmax(x)i=log⁡(softmax(x)i) \text{log\_softmax}(x)_i = \log(\text{softmax}(x)_i) log_softmax(x)i​=log(softmax(x)i​)

展开后:

log_softmax(x)i=xi−log⁡∑jexp⁡(xj) \text{log\_softmax}(x)_i = x_i - \log \sum_j \exp(x_j) log_softmax(x)i​=xi​−logj∑​exp(xj​)

实际实现会减去最大值,防止数值溢出:

log_softmax(x)i=xi−m−log⁡∑jexp⁡(xj−m) \text{log\_softmax}(x)_i = x_i - m - \log \sum_j \exp(x_j - m) log_softmax(x)i​=xi​−m−logj∑​exp(xj​−m)

其中 m=max⁡jxjm = \max_j x_jm=maxj​xj​。

它的输出是对数概率,对它取 exp 就得到 softmax:

softmax(x)=exp⁡(log_softmax(x)) \text{softmax}(x) = \exp(\text{log\_softmax}(x)) softmax(x)=exp(log_softmax(x))


4. 稳定性

softmax 的输出可能非常小,比如 10−3010^{-30}10−30。再取 log,可能直接变成 −∞-\infty−∞,浮点精度损失严重。

而 log_softmax 把两步合并计算,数值更稳定,也更高效。

所以:

log_softmax = 数值稳定版的 log(softmax(x))


5. PyTorch 用法

import torch
import torch.nn.functional as F

x = torch.tensor([[2.0, 1.0, 0.0]])  # logits
y = torch.tensor([0])                # 真实类别

log_probs = F.log_softmax(x, dim=1)
loss = F.nll_loss(log_probs, y)

# 更常用:CrossEntropyLoss 内部 = log_softmax + NLLLoss
loss2 = F.cross_entropy(x, y)

注意:

  • CrossEntropyLoss 接收的是 logits;
  • 不要再手动加 softmax;
  • NLLLoss 接收的是 log_softmax 的结果。

6. 总结

函数作用
softmax把 logits 变成概率
log把概率变成对数概率,用于计算损失
log_softmax稳定地计算 log(softmax(x))
CrossEntropyLoss内部执行 log_softmax + NLLLoss

更多推荐