PyTorch 深度学习笔记(十一):Softmax 与 Sigmoid 在多分类与二分类任务中的对比
·
PyTorch 深度学习笔记(十一):Softmax 与 Sigmoid 在多分类与二分类任务中的对比
在深度学习中,Softmax 和 Sigmoid 是两种常用的激活函数,广泛应用于分类任务。它们在多分类(类别数 $K > 2$)和二分类($K = 2$)任务中各有优势。本笔记将逐步对比它们的数学原理、适用场景、PyTorch 实现方式及注意事项,帮助您选择合适的函数。
1. 数学定义与原理
-
Sigmoid 函数:
- 适用于二分类任务,输出一个概率值(0 到 1),表示样本属于正类的概率。
- 数学公式:
$$ \sigma(x) = \frac{1}{1 + e^{-x}} $$ - 特点:输出值在 $[0, 1]$ 区间,常用于二分类的输出层。
-
Softmax 函数:
- 适用于多分类任务,输出一个概率分布,所有类别的概率和为 1。
- 数学公式:
$$ \sigma(\mathbf{z})i = \frac{e^{z_i}}{\sum{j=1}^{K} e^{z_j}} \quad \text{for} \quad i=1, \dotsc, K $$ - 特点:将原始分数(logits)转换为概率,$K$ 是类别数。
关键对比:
- Sigmoid 输出单个概率值,Softmax 输出概率向量。
- 在二分类任务中,Sigmoid 更直接;Softmax 也可用于二分类,但输出两个概率值(如 $[P(\text{class0}), P(\text{class1})]$),其中 $P(\text{class1}) = 1 - P(\text{class0})$,等价于 Sigmoid。
2. 适用任务对比
| 特征 | Sigmoid | Softmax |
|---|---|---|
| 任务类型 | 二分类($K=2$) | 多分类($K>2$) |
| 输出形式 | 单个概率值($P(\text{正类})$) | 概率分布(和为 1) |
| 损失函数 | 二元交叉熵(BCE) | 交叉熵(Cross-Entropy) |
| 优点 | 计算简单,适合二分类 | 直接处理多类别,输出可解释性强 |
| 缺点 | 在多分类中不适用 | 在二分类中可能冗余(输出两个值) |
| 适用场景 | 图像二分类(如猫 vs 狗)、文本情感分析(正/负) | 图像多分类(如 MNIST 数字识别)、自然语言处理(如词性标注) |
解释:
- 在二分类任务中,Sigmoid 是首选,因为它直接输出一个概率值(例如,$P(\text{猫}) = 0.8$ 表示 80% 概率为猫)。
- 在多分类任务中,Softmax 是标准选择,因为它确保所有类别的概率和为 1(例如,在 10 类分类中,输出 $[0.1, 0.7, 0.2, \dotsc]$)。
- 注意:在二分类中,Softmax 也可用,但通常不推荐,因为它增加计算开销(输出两个值)。Sigmoid 更高效。
3. PyTorch 实现示例
在 PyTorch 中,选择正确的激活函数和损失函数至关重要。以下示例展示如何实现。
二分类任务(使用 Sigmoid)
- 输出层:一个神经元 + Sigmoid。
- 损失函数:二元交叉熵(BCEWithLogitsLoss 更稳定,内部包含 Sigmoid)。
- 代码:
import torch import torch.nn as nn import torch.optim as optim # 定义模型(简单全连接网络) class BinaryClassifier(nn.Module): def __init__(self, input_size, hidden_size): super().__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, 1) # 输出一个值(logits) # 使用 BCEWithLogitsLoss,无需显式添加 Sigmoid def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) # 输出 logits return x # 参数设置 input_size = 10 # 输入特征维度 hidden_size = 64 model = BinaryClassifier(input_size, hidden_size) loss_fn = nn.BCEWithLogitsLoss() # 包含 Sigmoid 的损失函数 optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练示例(假设 data 和 labels 已定义) # labels 应为浮点型(0 或 1),如 torch.tensor([1.0, 0.0, ...]) outputs = model(data) loss = loss_fn(outputs.squeeze(), labels) # squeeze 去除多余维度 optimizer.zero_grad() loss.backward() optimizer.step()
多分类任务(使用 Softmax)
- 输出层:$K$ 个神经元,通常不显式添加 Softmax(因为 CrossEntropyLoss 内部包含)。
- 损失函数:交叉熵(CrossEntropyLoss)。
- 代码:
import torch import torch.nn as nn import torch.optim as optim # 定义模型 class MultiClassClassifier(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super().__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, num_classes) # 输出 K 个值(logits) # 使用 CrossEntropyLoss,无需显式添加 Softmax def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) # 输出 logits return x # 参数设置 input_size = 10 hidden_size = 64 num_classes = 5 # 类别数 K>2 model = MultiClassClassifier(input_size, hidden_size, num_classes) loss_fn = nn.CrossEntropyLoss() # 包含 Softmax 的损失函数 optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练示例(labels 应为整数型,如 torch.tensor([0, 2, 1, ...])) outputs = model(data) loss = loss_fn(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step()
关键点:
- 输出层:在 PyTorch 中,通常不在模型输出层显式添加
nn.Softmax或nn.Sigmoid,因为损失函数(如CrossEntropyLoss或BCEWithLogitsLoss)已内部处理。这能提高数值稳定性。 - 损失函数选择:
- Sigmoid + 二分类:使用
BCEWithLogitsLoss(推荐)或BCELoss(需手动添加 Sigmoid)。 - Softmax + 多分类:使用
CrossEntropyLoss。
- Sigmoid + 二分类:使用
- 二分类使用 Softmax 的替代方案:如果必须用 Softmax,可设置输出层为两个神经元:
但 Sigmoid 更简洁。self.fc2 = nn.Linear(hidden_size, 2) # K=2 loss_fn = nn.CrossEntropyLoss()
4. 注意事项与常见问题
- 梯度问题:
- Sigmoid 在极端值(如 $x \to \pm\infty$)时梯度接近 0,可能导致梯度消失。使用
BCEWithLogitsLoss可缓解。 - Softmax 在计算时涉及指数运算,需注意数值溢出(PyTorch 的
CrossEntropyLoss已优化)。
- Sigmoid 在极端值(如 $x \to \pm\infty$)时梯度接近 0,可能导致梯度消失。使用
- 概率解释:
- Sigmoid 输出 $P(\text{正类})$,可直接用于阈值判断(如 >0.5 为正类)。
- Softmax 输出概率分布,可用
torch.argmax获取预测类别。
- 性能影响:
- 在二分类中,Sigmoid 比 Softmax 计算量小(输出一个值 vs 两个值)。
- 在多分类中,Softmax 是标准,避免使用多个 Sigmoid(可能导致概率和不等于 1)。
- 实际建议:
- 二分类:优先使用 Sigmoid +
BCEWithLogitsLoss。 - 多分类:使用 Softmax(通过
CrossEntropyLoss)。 - 混合任务:如多标签分类(每个标签独立二分类),可使用多个 Sigmoid。
- 二分类:优先使用 Sigmoid +
5. 总结
- Sigmoid:理想选择用于二分类任务,输出简单概率值,PyTorch 实现高效。
- Softmax:标准用于多分类任务,输出概率分布,确保类别间竞争关系。
- 在 PyTorch 中,正确选择损失函数(如
BCEWithLogitsLoss或CrossEntropyLoss)是关键,避免显式添加激活函数以提高稳定性和性能。通过本对比,您可根据任务需求灵活应用。
更多推荐
所有评论(0)