PyTorch 中的 LogSoftmax 和 Softmax 用于交叉熵损失函数的比较

PyTorch 中的 LogSoftmax 和 Softmax 用于交叉熵损失函数的比较

在本文中,我们将介绍 PyTorch 中的两个重要函数,即 LogSoftmax 和 Softmax,它们在交叉熵损失函数中的应用。让我们先了解一下交叉熵损失函数的背景。

阅读更多:Pytorch 教程

交叉熵损失函数

交叉熵损失函数是深度学习任务中常用的损失函数之一,特别适用于分类问题。在训练模型的过程中,我们希望模型的输出概率分布与真实标签的概率分布尽可能接近。交叉熵损失函数就是衡量这两个概率分布之间的差异。PyTorch 提供了一个方便的函数 nn.CrossEntropyLoss 来计算交叉熵损失。

然而,为了计算交叉熵损失,我们需要模型的最终输出经过一个激活函数,并且该函数应用于模型的输出层。在 PyTorch 中,常用的激活函数有 Softmax 和 LogSoftmax。

Softmax 函数

Softmax 函数是一个常用的激活函数,它将模型的原始输出转化为一个概率分布。具体来说,Softmax 函数可以将一个 K 维向量 x 转化为一个 K 维向量 y,且满足以下公式:

y_i = exp(x_i) / sum(exp(x_j)), for j = 1,...,K
Python

其中,y_i 表示向量 y 的第 i 个元素,x_i 表示向量 x 的第 i 个元素,exp(x_i) 表示 x_i 的指数值。

Softmax 函数的输出是一个概率分布,其中每个元素的取值范围在 0 到 1 之间,并且所有元素的和等于 1。在分类问题中,Softmax 函数通常应用于模型的输出层,用于将原始输出转化为对应的类别概率。

在 PyTorch 中,我们可以使用 nn.Softmax 函数来实现 Softmax 操作。下面是一个示例:

import torch
import torch.nn as nn

# 定义模型输出层的维度为10,表示有10个类别
output_dim = 10
# 假设模型的原始输出为一个10维向量
raw_output = torch.randn(output_dim)

softmax = nn.Softmax(dim=0)
output = softmax(raw_output)

print(output)
Python

上述代码中,softmax 是一个 nn.Softmax 对象,通过指定 dim=0 参数将 Softmax 函数应用于 raw_output 向量的每个维度。最后打印的 output 是一个满足概率分布条件的概率向量。

需要注意的是,Softmax 函数的输出值较小的维度可能会接近于 0,而值较大的维度可能会接近于 1。如果计算交叉熵损失时直接使用 Softmax 函数的输出,可能会出现数值稳定性的问题。

LogSoftmax 函数

为了解决 Softmax 函数在计算交叉熵损失时的数值稳定性问题,PyTorch 还提供了 LogSoftmax 函数。

LogSoftmax 函数它先计算 Softmax 函数的输出,然后再对每个维度的值应用自然对数函数。具体来说,对于一个 K 维向量 x,LogSoftmax 函数的计算如下:

logsoftmax_i = log(exp(x_i) / sum(exp(x_j))), for j = 1,...,K
Python

LogSoftmax 函数的输出是一个 K 维向量,其中每个元素的取值范围在负无穷到 0 之间。由于 LogSoftmax 函数在计算交叉熵损失时,会将原始输出先进行对数转换,因此可以避免 Softmax 函数在较小和较大值时出现数值上溢和下溢的情况。

在 PyTorch 中,我们可以使用 nn.LogSoftmax 函数来实现 LogSoftmax 操作。下面是一个示例:

import torch
import torch.nn as nn

# 定义模型输出层的维度为10,表示有10个类别
output_dim = 10
# 假设模型的原始输出为一个10维向量
raw_output = torch.randn(output_dim)

logsoftmax = nn.LogSoftmax(dim=0)
output = logsoftmax(raw_output)

print(output)
Python

上述代码中,logsoftmax 是一个 nn.LogSoftmax 对象,通过指定 dim=0 参数将 LogSoftmax 函数应用于 raw_output 向量的每个维度。最后打印的 output 是一个满足对数概率分布条件的对数概率向量。

需要注意的是,LogSoftmax 函数的输出是对数概率值,可以用作交叉熵损失函数的输入。

LogSoftmax vs Softmax for CrossEntropyLoss

在常见的深度学习任务中,交叉熵损失函数通常与 Softmax 函数一起使用,可以直接计算模型输出与真实标签之间的差异。然而,在使用 Softmax 函数时,由于其将原始输出指数化后再归一化,可能会导致数值稳定性问题。

LogSoftmax 函数通过对 Softmax 函数的输出进行对数转换,解决了 Softmax 函数计算交叉熵损失时的数值稳定性问题。在实际应用中,我们通常使用 LogSoftmax 函数作为分类任务中模型输出的激活函数,并将其与交叉熵损失函数相结合。

下面是一个示例,演示了如何使用 LogSoftmax 函数和交叉熵损失函数来训练一个简单的分类模型:

import torch
import torch.nn as nn
import torch.optim as optim

# 构建一个简单的分类模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(10, 2)

    def forward(self, x):
        x = self.fc(x)
        x = nn.LogSoftmax(dim=1)(x)
        return x

# 创建模型实例、损失函数和优化器
model = SimpleModel()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 准备输入数据和标签
inputs = torch.randn(32, 10) # 32个10维向量作为输入数据
labels = torch.tensor([0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1,
                       0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1])  # 32个二分类标签

# 模型训练
for epoch in range(100):
    optimizer.zero_grad()
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    if (epoch+1) % 10 == 0:
        print(f'Epoch: {epoch+1}, Loss: {loss.item():.4f}')
Python

上述代码中,我们定义了一个简单的分类模型 SimpleModel,它包含一个线性层和 LogSoftmax 函数。我们使用交叉熵损失函数 nn.CrossEntropyLoss 来计算模型输出和真实标签之间的差异,并使用随机梯度下降优化器 optim.SGD 来更新模型的参数。

在训练过程中,我们生成了一个随机的输入数据 inputs 和对应的二分类标签 labels。然后,我们通过初始化模型、计算输出、计算损失、反向传播和参数更新等步骤来训练模型。每经过 10 个周期,我们打印一次训练损失。

总结

在本文中,我们介绍了 PyTorch 中的 LogSoftmax 和 Softmax 函数,并比较了它们在交叉熵损失函数中的应用。Softmax 函数将原始输出转化为概率分布,用于多分类任务,而 LogSoftmax 函数通过对 Softmax 函数的输出进行对数转换,解决了数值稳定性问题。在实际应用中,我们通常使用 LogSoftmax 函数作为模型输出的激活函数,并将其与交叉熵损失函数相结合,以实现分类任务的训练。

通过本文的学习,我们对 PyTorch 中 LogSoftmax 和 Softmax 函数在交叉熵损失函数中的使用有了更深入的理解。希望本文能对你在深度学习中的实践有所帮助!

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册