扩展 - LogSoftmax() 函数讲解
1 课程概览
本课讲解 LogSoftmax() 函数的用法,它是多分类交叉熵(CrossEntropyLoss)的前身。LogSoftmax 对 softmax 的结果取对数,dim=0 表示按列操作。本课为后续人名分类案例做铺垫。
2 核心概念与定义
- LogSoftmax:对 softmax 的结果取对数,用于多分类任务。
- Softmax:将预测分数转换为概率分布,所有概率之和为 1。
- CrossEntropyLoss(交叉熵损失):多分类任务的损失函数,内部使用了 LogSoftmax。
- Logits:模型输出的原始预测分数。
- dim:指定操作的维度,
dim=0表示按列操作。
3 模型与算法详解
Softmax 与 LogSoftmax 的关系
| 函数 | 作用 | 公式 |
|---|---|---|
| Softmax | 将分数转换为概率 | $\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}$ |
| LogSoftmax | 对 softmax 取对数 | $\text{logsoftmax}(x_i) = \log(\text{softmax}(x_i))$ |
多分类流程
- 模型输出:原始预测分数(logits)
- Softmax:转换为概率分布(和为 1)
- LogSoftmax:对概率取对数
- CrossEntropyLoss:计算损失
LogSoftmax 与 CrossEntropyLoss 的关系
LogSoftmax 是多分类交叉熵(CrossEntropyLoss)的前身。
CrossEntropyLoss=LogSoftmax+NLLLoss- 使用
CrossEntropyLoss时,不需要手动加LogSoftmax
dim 参数
| dim 值 | 操作方向 | 说明 |
|---|---|---|
| dim=0 | 按列操作 | 每列的所有元素进行 softmax |
| dim=1 | 按行操作 | 每行的所有元素进行 softmax |
4 数学原理与推导
Softmax 公式
$$\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{n} e^{x_j}}$$
LogSoftmax 公式
$$\text{logsoftmax}(x_i) = \log\left(\frac{e^{x_i}}{\sum_{j=1}^{n} e^{x_j}}\right) = x_i - \log\left(\sum_{j=1}^{n} e^{x_j}\right)$$
数值稳定性
LogSoftmax 相比先 Softmax 再取对数,数值更稳定,避免下溢出。
5 代码示例
import torch
import torch.nn as nn
# 1. 创建数据,模拟模型输出的原始分数(logits)
# 表示三个分类的预测值
output = torch.tensor([3.2, 5.1, -1.7])
print("原始分数:", output)
# 2. 思路一:使用 log_softmax 函数(小写)
# 创建 log_softmax 对象,dim=0 表示按列操作
log_softmax = nn.LogSoftmax(dim=0)
# 计算结果
result = log_softmax(output)
print("LogSoftmax 结果:", result)
# 3. 对比 softmax 结果
softmax = nn.Softmax(dim=0)
softmax_result = softmax(output)
print("Softmax 结果:", softmax_result)
print("Softmax 和:", softmax_result.sum()) # 和为 1
# 4. 验证 LogSoftmax = log(Softmax)
import torch
log_softmax_manual = torch.log(softmax_result)
print("手动计算 log(softmax):", log_softmax_manual)
# 与 nn.LogSoftmax 结果相同
# 5. 多分类示例(二维数据)
# 3 个样本,每个样本 3 个分类的预测分数
output_2d = torch.tensor([
[3.2, 5.1, -1.7],
[1.0, 2.0, 3.0],
[0.5, 0.5, 0.5]
])
# dim=1 表示按行操作(每个样本的概率和为 1)
log_softmax_2d = nn.LogSoftmax(dim=1)
result_2d = log_softmax_2d(output_2d)
print("二维 LogSoftmax 结果:", result_2d)
# 6. 与 CrossEntropyLoss 的关系
# CrossEntropyLoss 内部已包含 LogSoftmax,不需要手动加
criterion = nn.CrossEntropyLoss()
# 使用 CrossEntropyLoss 时,模型不需要加 LogSoftmax
输出示例
原始分数: tensor([ 3.2000, 5.1000, -1.7000])
LogSoftmax 结果: tensor([-2.3003, -0.4003, -7.2003])
Softmax 结果: tensor([0.1000, 0.6700, 0.0007])
Softmax 和: tensor(1.0000)
6 重难点与易错提醒
- ❗重点:
LogSoftmax是多分类交叉熵(CrossEntropyLoss)的前身。 - ❗重点:
dim=0按列操作,dim=1按行操作。 - ⚠️易错:使用
CrossEntropyLoss时,模型不需要手动加LogSoftmax。 - 💡深入理解:
LogSoftmax相比先Softmax再取对数,数值更稳定。 - 💡深入理解:
nn.LogSoftmax(大写)是模块,nn.functional.log_softmax(小写)是函数。
7 课堂问答精选
Q1:LogSoftmax 和 Softmax 有什么区别?
A:Softmax 将预测分数转换为概率分布(和为 1)。LogSoftmax 对 softmax 的结果取对数,数值更稳定。
Q2:LogSoftmax 和 CrossEntropyLoss 有什么关系?
A:LogSoftmax 是 CrossEntropyLoss 的前身。CrossEntropyLoss = LogSoftmax + NLLLoss。使用 CrossEntropyLoss 时,不需要手动加 LogSoftmax。
Q3:dim 参数的作用是什么?
A:dim=0 表示按列操作(每列的元素进行 softmax),dim=1 表示按行操作(每行的元素进行 softmax)。
Q4:为什么使用 LogSoftmax 而不是先 Softmax 再取对数?
A:LogSoftmax 数值更稳定,避免下溢出问题。
8 本课小结
LogSoftmax:对 softmax 结果取对数。CrossEntropyLoss=LogSoftmax+NLLLoss。dim=0按列操作,dim=1按行操作。- 使用
CrossEntropyLoss时不需要手动加LogSoftmax。 LogSoftmax数值更稳定。
9 延伸思考
- 为什么 LogSoftmax 数值更稳定?
- CrossEntropyLoss 内部是如何实现的?