Pytorch的四种函数讲解


前言

在PyTorch中,Softmax和LogSoftmax函数是用于将多维张量的值转换为概率分布的函数。它们通常用于多分类问题中,将模型的输出转换为每个类别的概率。
在PyTorch中,NLLLoss(负对数似然损失)和CrossEntropyLoss(交叉熵损失)是两种常用的损失函数,它们通常用于多分类问题。


一、四种函数的概念

1.1 Softmax函数

Softmax函数通常用于多分类问题的输出层,它将一个K维的任意实数值向量转换为另一个K维的实数值向量,其中向量中的每个元素都在0到1之间,并且所有元素的和为1。这使得输出可以被解释为概率分布。

函数定义
Softmax函数定义为:
\text{Softmax}(x_i) = \frac{\exp(x_i)}{\sum_{j=1}^{K} \exp(x_j)}
其中,​ x_i是输入向量中的第 i个元素,\exp(x_i)是  x_i的指数值。

1.2 LogSoftmax函数

LogSoftmax函数是Softmax函数的对数形式,它首先计算Softmax函数的输出,然后对每个维度的值应用自然对数函数。这有助于数值稳定性,尤其是在处理非常大或非常小的数值时。

函数定义
LogSoftmax函数定义为:
\text{LogSoftmax}(x_i) = \log\left(\frac{\exp(x_i)}{\sum_{j=1}^{K} \exp(x_j)}\right)

1.3  NLLLoss(负对数似然损失)

NLLLoss(Negative Log Likelihood Loss)是用于多分类问题的损失函数,它计算的是负对数似然损失。在多分类问题中,模型的输出通常是一个对数概率分布,而NLLLoss用于计算这个分布与真实标签之间的损失。

函数定义
\text{NLLLoss}(x, y) = -\sum_{i} y_i \log(x_i)
其中,x 是模型输出的对数概率分布,y 是真实标签的独热编码。

1.4 CrossEntropyLoss(交叉熵损失)

CrossEntropyLoss是另一种用于多分类问题的损失函数,它结合了LogSoftmaxNLLLoss的功能。在计算交叉熵损失时,模型的输出首先通过LogSoftmax函数转换为对数概率分布,然后计算这个分布与真实标签之间的负对数似然损失。

函数定义
\text{CrossEntropyLoss}(x, y) = -\sum_{i} y_i \log(\text{softmax}(x_i))
其中,x  是模型输出的原始概率分布,y  是真实标签的独热编码。

二、使用步骤

1.1 Softmax和LogSoftmax函数示例

代码展示:

import torch
import math

# 参数设置dim=1表示行和为1
softmax = torch.nn.Softmax(dim=1)              # 定义Softmax函数

input = torch.Tensor([[1, 2, 3], [1, 2, 4]])
print("测试数据:", input)
output = softmax(input)                       # Softmax函数计算
print("输出softmax计算后结果:\n", output)

x00 = math.log(0.0900)
x01 = math.log(0.2447)
x02 = math.log(0.6652)
x10 = math.log(0.0420)
x11 = math.log(0.1142)
x12 = math.log(0.8438)
print("输出log计算结果:")
print(x00, x01, x02)
print(x10, x11, x12)

# 参数设置dim=1表示行和为1
lgsoftmax = torch.nn.LogSoftmax(dim=1)      # 定义LogSoftmax函数

output = lgsoftmax(input)                   # LogSoftmax函数计算
print("输出LogSoftmax计算后结果:\n", output)

代码讲解:

1.定义一个Softmax函数实例,其中dim=1表示在计算softmax时,将沿着每一行(dim=1)进行操作,使得每一行的元素和为1。

dim解释:在PyTorch中,dim参数用于指定在哪个维度上应用函数。对于SoftmaxLogSoftmax函数,dim参数决定了函数将沿着哪个维度进行归一化操作。

对于Softmax函数,dim参数指定了输入张量的哪个维度将被归一化。例如,如果dim=1,则函数将沿着输入张量的第二个维度(通常是类别维度)进行归一化,使得每个样本的输出概率和为1。如果dim=0,则函数将沿着第一个维度(通常是样本维度)进行归一化。

对于LogSoftmax函数,dim参数同样指定了归一化的维度。LogSoftmax函数首先计算Softmax函数的输出,然后对每个维度的值应用自然对数函数。因此,LogSoftmax函数的输出是Softmax函数输出的对数,这有助于数值稳定性,尤其是在处理非常大或非常小的数值时。

在上述代码中,dim=1表示SoftmaxLogSoftmax函数将沿着输入张量的每一行(即每个样本的类别维度)进行归一化和对数运算。这意味着对于每个样本,函数将确保其类别概率的总和为1,并且输出的是每个类别的对数概率。

softmax = torch.nn.Softmax(dim=1)

2.创建一个2x3的Tensor作为输入数据。

input = torch.Tensor([[1, 2, 3], [1, 2, 4]])

3.打印输入数据。

print("测试数据:", input)

4.使用定义好的Softmax函数计算输入数据的softmax值,并打印结果。

output = softmax(input)
print("输出softmax计算后结果:\n", output)

5.手动计算输入数据的log值,用于后续与LogSoftmax的结果进行比较。

x00 = math.log(0.0900)
x01 = math.log(0.2447)
x02 = math.log(0.6652)
x10 = math.log(0.0420)
x11 = math.log(0.1142)
x12 = math.log(0.8438)
print("输出log计算结果:")
print(x00, x01, x02)
print(x10, x11, x12)

6.定义一个LogSoftmax函数实例,同样地,dim=1表示在计算logsoftmax时,将沿着每一行进行操作。

lgsoftmax = torch.nn.LogSoftmax(dim=1)

7.使用定义好的LogSoftmax函数计算输入数据的logsoftmax值,并打印结果。

output = lgsoftmax(input)
print("输出LogSoftmax计算后结果:\n", output)

1.2 NLLLoss函数示例

代码展示:

import torch

# 参数设置dim=1表示行和为1
lgsoftmax = torch.nn.LogSoftmax(dim=1)         # 定义LogSoftmax函数
input = torch.Tensor([[1, 2, 3], [1, 2, 4]])   # 测试数据
output = lgsoftmax(input)                      # LogSoftmax函数自动计算
print("输出LogSoftmax计算后结果:\n", output)

criterion = torch.nn.NLLLoss()                # 定义NLLLoss函数
labels = torch.tensor([1, 2])                  # 每一项的范围是[0,C-1] 0 1 2
loss = criterion(output, labels)
print(loss)

print((1.4076+0.1698)/2)

 代码讲解:

lgsoftmax = torch.nn.LogSoftmax(dim=1)          # 定义LogSoftmax函数

这里创建了一个LogSoftmax函数的实例。LogSoftmax函数是Softmax函数的对数形式,它将输入的任意实数值映射到(0, 1)区间,并且输出的总和为1。dim=1参数指定了在哪个维度上进行softmax操作,这里是在行上进行操作。

input = torch.Tensor([[1, 2, 3], [1, 2, 4]])    # 测试数据

这行代码创建了一个2x3的Tensor,作为模型的输入数据。这个Tensor包含了两组数据,每组数据有三个特征。

output = lgsoftmax(input)                       # LogSoftmax函数自动计算

这行代码将LogSoftmax函数应用于输入数据input,计算出每个元素的LogSoftmax值。

print("输出LogSoftmax计算后结果:\n", output)

打印出LogSoftmax计算后的结果。

criterion = torch.nn.NLLLoss()                 # 定义NLLLoss函数

这里创建了一个负对数似然损失(NLLLoss)函数的实例。NLLLoss通常用于多分类问题,它计算的是负对数似然损失,即预测概率分布的负对数似然。

labels = torch.tensor([1, 2])                   # 每一项的范围是[0,C-1] 0 1 2

这行代码创建了一个Tensor,包含了两个标签,分别对应于输入数据中的两组数据。标签的值范围是从0到类别数减1。

loss = criterion(output, labels)

这行代码计算了使用NLLLoss函数的损失值。output是LogSoftmax函数的输出,labels是真实的标签。

1.3 CrossEntropyLoss函数示例

代码展示:

import torch

######### 使用 NLLLoss函数 ######################
# 参数设置dim=1表示行和为1
lgsoftmax = torch.nn.LogSoftmax(dim=1)         # 定义LogSoftmax函数
input = torch.Tensor([[1, 2, 3], [1, 2, 4]])   # 测试数据
output = lgsoftmax(input)                      # LogSoftmax函数自动计算
print("输出LogSoftmax计算后结果:\n", output)

criterion1 = torch.nn.NLLLoss()                # 定义NLLLoss函数
labels = torch.tensor([1, 2])                  # 每一项的范围是[0,C-1] 0 1 2
loss1 = criterion1(output, labels)
print(loss1)

######### 使用 CrossEntropyLoss 交叉熵损失函数 ###################### CrossEntropyLoss = softmax + lg + NLLLoss
criterion2 = torch.nn.CrossEntropyLoss()
loss2 = criterion2(input, labels)
print(loss2)

代码讲解:

loss1 = criterion1(output, labels)

这行代码计算了使用NLLLoss函数的损失值。output是LogSoftmax函数的输出,labels是真实的标签。

criterion2 = torch.nn.CrossEntropyLoss()

这里创建了一个交叉熵损失(CrossEntropyLoss)函数的实例。CrossEntropyLoss是NLLLoss和LogSoftmax的组合,它直接计算了输入和目标之间的交叉熵损失。

loss2 = criterion2(input, labels)

这行代码计算了使用CrossEntropyLoss函数的损失值。input是原始的输入数据,labels是真实的标签。


总结

LogSoftmax:LogSoftmax函数是Softmax函数的对数形式,它将输入的任意实数值映射到(0, 1)区间,并且输出的总和为1。LogSoftmax通常与NLLLoss(负对数似然损失)一起使用,特别是在多分类问题中,它能够将模型的输出转换为概率分布,然后计算该分布的负对数似然损失。

NLLLoss (Negative Log Likelihood Loss):NLLLoss函数计算的是负对数似然损失,即预测概率分布的负对数似然。在多分类问题中,它通常与LogSoftmax一起使用,因为LogSoftmax的输出可以作为NLLLoss的输入。这种组合能够有效地衡量模型预测的准确性。

CrossEntropyLoss:CrossEntropyLoss是NLLLoss和LogSoftmax的组合,它直接计算了输入和目标之间的交叉熵损失。在多分类问题中,CrossEntropyLoss可以直接应用于模型的原始输出(通常是未经LogSoftmax处理的分数),而不需要先进行LogSoftmax转换。这种损失函数在处理多分类问题时非常常见,因为它能够直接衡量模型输出与真实标签之间的差异。

Softmax:Softmax函数将输入的任意实数值映射到(0, 1)区间,并且输出的总和为1。它通常用于多分类问题中,将模型的原始输出转换为概率分布。在某些情况下,Softmax可以与CrossEntropyLoss一起使用,尤其是在模型的输出已经是一个概率分布时。

PyTorch 中,LSTM 模型可以通过 `torch.nn.LSTM` 来实现。下面是一个简单的例子,讲解如何使用 PyTorch 实现 LSTM 模型。 首先,我们需要导入必要的包: ```python import torch import torch.nn as nn ``` 接着,我们定义一个 LSTM 模型类 `LSTMModel`。在这个类中,我们需要定义 LSTM 模型的输入维度、隐藏层维度、LSTM 层数、输出维度、以及 dropout 概率。这些参数将在类的初始化函数 `__init__` 中进行设置。 ```python class LSTMModel(nn.Module): def __init__(self, input_dim, hidden_dim, layer_dim, output_dim, dropout_prob): super(LSTMModel, self).__init__() # 定义 LSTM 模型的参数 self.hidden_dim = hidden_dim self.layer_dim = layer_dim # 定义 LSTM 层 self.lstm = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True) # 定义 dropout 层 self.dropout = nn.Dropout(p=dropout_prob) # 定义全连接层 self.fc = nn.Linear(hidden_dim, output_dim) ``` 在 `forward` 函数中,我们需要传入模型的输入数据 `x`,并将它传入 LSTM 层中。LSTM 层的输出包括两个部分:LSTM 的输出 `out` 和最后一个时间步的隐藏状态 `h_n` 和记忆单元状态 `c_n`。我们取 `out[:, -1, :]` 作为最后一个时间步的输出,并将它传入全连接层中得到模型的输出。在 `forward` 函数中,我们还需要添加 dropout 层以避免过拟合。 ```python def forward(self, x): # 初始化隐藏状态和记忆单元状态 h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_() c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_() # 将输入传入 LSTM 层中 out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach())) # 取最后一个时间步的输出,并传入全连接层中 out = self.dropout(out[:, -1, :]) out = self.fc(out) return out ``` 最后,我们实例化一个 LSTM 模型并定义损失函数和优化器: ```python # 实例化 LSTM 模型 input_dim = 28 hidden_dim = 100 layer_dim = 1 output_dim = 10 dropout_prob = 0.2 model = LSTMModel(input_dim, hidden_dim, layer_dim, output_dim, dropout_prob) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() learning_rate = 0.1 optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) ``` 这样,我们就可以使用 PyTorch 实现 LSTM 模型了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想敲代码的小趴菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值