torch.nn
库:这个库提供了许多预定义的层,如全连接层(Linear)、卷积层(Conv2d)等,以及一些损失函数(如MSELoss、CrossEntropyLoss等)。这些层都是类,它们都继承自nn.Module
,因此可以很方便地集成到自定义的模型中。torch.nn
库中的层都有自己的权重和偏置,这些参数可以通过优化器进行更新。
当你需要的操作包含可学习的参数(例如权重和偏置)时,通常使用torch.nn
库更为方便。例如,对于卷积层(Conv2d)、全连接层(Linear)等,由于它们包含可学习的参数,因此通常使用torch.nn
库中的类。这些类会自动管理参数的创建和更新。
例如:
import torch.nn as nn
conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)
fc = nn.Linear(in_features=1024, out_features=10)
torch.nn.functional库:这个库提供了一些函数,如激活函数(如relu、sigmoid等)、池化函数(如max_pool2d、avg_pool2d等)以及一些损失函数(如cross_entropy、mse_loss等)。这些函数更加灵活,但使用它们需要手动管理权重和偏置。
对于没有可学习参数的操作,例如ReLU激活函数、池化操作、dropout等,你可以选择使用torch.nn.functional库,因为这些操作不需要额外的参数。
import torch.nn.functional as F
x = F.relu(x)
x = F.max_pool2d(x, kernel_size=2)
x = F.dropout(x, p=0.5, training=self.training)
对于损失函数,torch.nn库和torch.nn.functional库都提供了实现,你可以根据需要选择。如果你需要的损失函数有可学习的参数(例如nn.BCEWithLogitsLoss中的pos_weight),那么应该使用torch.nn库。如果你的损失函数没有可学习的参数,那么你可以选择使用torch.nn.functional库,这样可以避免创建不必要的对象。
例如:
import torch.nn as nn
import torch.nn.functional as F
# 使用nn库
loss_fn = nn.CrossEntropyLoss()
loss = loss_fn(prediction, target)
# 使用functional库
loss = F.cross_entropy(prediction, target)
以下是一些常见的损失函数在torch.nn和torch.nn.functional中的对应关系:
nn.MSELoss()
输入:预测值和目标值,它们的形状应该是相同的。例如,如果你有一个批量大小为batch_size的数据,每个数据有n个特征,那么预测值和目标值的形状都应该是(batch_size, n)。
输出:一个标量,表示计算得到的均方误差损失。
例如:
import torch
import torch.nn as nn
# 假设我们有一个批量大小为3的数据,每个数据有2个特征
prediction = torch.randn(3, 2)
target = torch.randn(3, 2)
loss_fn = nn.MSELoss()
loss = loss_fn(prediction, target)
print(loss) # 输出一个标量,表示计算得到的均方误差损失
F.cross_entropy()
输入:预测值和目标值。预测值的形状应该是(batch_size, num_classes),表示对每个类别的预测概率;目标值的形状应该是(batch_size,),表示每个数据的真实类别标签。
输出:一个标量,表示计算得到的交叉熵损失。
例如:
import torch
import torch.nn.functional as F
# 假设我们有一个批量大小为3的数据,有4个类别
prediction = torch.randn(3, 4)
target = torch.tensor([1, 0, 3]) # 真实的类别标签
loss = F.cross_entropy(prediction, target)
print(loss) # 输出一个标量,表示计算得到的交叉熵损失
CrossEntropyLoss() = softmax + log + NLLLoss() = log_softmax + NLLLoss()
BCELoss()和BCEWithLogitsLoss()都是PyTorch中常用的损失函数,主要用于二分类问题。但是它们的输入和处理方式有所不同。
总的来说,BCELoss()和BCEWithLogitsLoss()的主要区别在于它们的输入:BCELoss()期望的输入是模型的概率输出,而BCEWithLogitsLoss()期望的输入是模型的原始输出。在实际使用中,你可以根据自己的需求和模型的输出来选择使用哪一个损失函数。
另外,BCEWithLogitsLoss()在内部进行sigmoid和loss计算可以提高数值稳定性,因此在实际使用中,如果模型的输出是原始分数,推荐使用BCEWithLogitsLoss()。
它的完整定义是torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')。
下面是这些参数的解释:
nn.MSELoss()函数的输入是两个张量,分别代表预测值和目标值。它们必须有相同的形状。函数的输出是一个标量值,表示损失。
因此,nn.SmoothL1Loss的一个主要优点是它可以在处理异常值和进行精细优化之间找到一个平衡,这在某些任务中可能是非常有用的。
nn.SmoothL1Loss是通过一个特定的数学公式来实现这个优点的。这个公式如下:
SmoothL1Loss(x, y) = 0.5 * (x - y)^2, if abs(x - y) < 1
= abs(x - y) - 0.5, otherwise
这个公式的含义是,当预测值和真实值的差距小于1时,使用平方误差损失(即L2损失);当差距大于或等于1时,使用绝对值误差损失(即L1损失)。
可以看到,当差距较小的时候,SmoothL1Loss的行为类似于nn.MSELoss,它会对这些小的误差进行精细优化。而当差距较大的时候,SmoothL1Loss的行为类似于L1损失,它不会对这些大的误差进行过度惩罚,从而提高了对异常值的鲁棒性。
这就是nn.SmoothL1Loss如何在处理异常值和进行精细优化之间找到平衡的。
nn.HuberLoss也被称为Huber损失,是一种结合了均方误差损失(Mean Squared Error,MSE)和平均绝对误差损失(Mean Absolute Error,MAE)的损失函数。它在处理回归问题时,尤其是存在异常值(outliers)的情况下,表现出较好的性能。
Huber损失的计算公式如下:
HuberLoss(x, y) = 0.5 * (x - y)^2, if abs(x - y) < delta
= delta * abs(x - y) - 0.5 * delta^2, otherwise
这个公式的含义是,当预测值和真实值的差距小于一个阈值delta时,使用平方误差损失(即MSE);当差距大于或等于delta时,使用线性误差损失(即MAE)。
与nn.SmoothL1Loss类似,nn.HuberLoss在处理异常值和进行精细优化之间找到了一个平衡。当预测误差较小的时候,它的行为类似于MSE,可以对这些小的误差进行精细优化;而当预测误差较大的时候,它的行为类似于MAE,不会对这些大的误差进行过度惩罚,从而提高了对异常值的鲁棒性。
另外,nn.HuberLoss的一个优点是它的梯度在整个定义域内都是有界的,这使得模型在训练过程中更稳定。
pytorch教程 (四)- 损失函数_pytorch对比损失-CSDN博客