目录
损失函数与反向传播
所需的Loss计算函数都在torch.nn的LossFunctions中,官方网址是:torch.nn --- PyTorch 2.0 documentation。举例了L1Loss、MSELoss、CrossEntropyLoss。
在这些Loss函数的使用中,有以下注意的点:
(1) 参数reduction='mean',默认是'mean'表示对差值的和求均值,还可以是'sum'则不会求均值。
(2) 一定要注意Input和target的shape。
L1Loss
创建一个标准,用于测量中每个元素之间的Input: x xx 和 target: y yy。
创建一个标准,用来测量Input: x xx 和 target: y yy 中的每个元素之间的平均绝对误差(MAE)(L 1 L_1L 1范数)。
Shape:
Input: (∗ *∗), where ∗ *∗ means any number of dimensions. 会对所有维度的loss求均值
Target: (∗ *∗), same shape as the input. 与Input的shape相同
Output: scalar.返回值是标量。
假设 a aa 是标量,则有:
type(a) = torch.Tensor
a.shape = torch.Size([])
a.dim = 0
MSELOSS
创建一个标准,用来测量Input: x xx 和 target: y yy 中的每个元素之间的均方误差(平方L2范数)。
Shape:
Input: (∗ *∗), where ∗ *∗ means any number of dimensions. 会对所有维度求loss
Target: (∗ *∗), same shape as the input. 与Input的shape相同
Output: scalar.返回值是标量。
CrossEntropyLoss
该标准计算 input 和 target 之间的交叉熵损失。
非常适用于当训练 C CC 类的分类问题(即多分类问题,若是二分类问题,可采用BCELoss)。如果要提供可选参数 w e i g h t weightweight ,那 w e i g h t weightweight 应设置为1维tensor去为每个类分配权重。这在训练集不平衡时特别有用。
期望的 input应包含每个类的原始的、未标准化的分数。input必须是大小为C CC(input未分批)、(m i n i b a t c h , C minibatch,Cminibatch,C) or (m i n i b a t c h , C , d 1 , d 2 , . . . d kminibatch,C,d_1,d_2,...d_kminibatch,C,d 1,d 2,...d k )的Tensor。最后一种方法适用于高维输入,例如计算2D图像的每像素交叉熵损失。
期望的 target应包含以下内容之一:
(1) (target包含了)在[ 0 , C ) [0,C)[0,C)区间的类别索引,C CC是类别总数量。如果指定了 ignore_index,则此损失也接受此类索引(此索引不一定在类别范围内)。reduction='none'情况下的loss为
注意:l o g loglog默认是以10为底的。
x是input,y yy是target,w ww是权重weight,C CC是类别数量,N NN涵盖minibatch维度且d 1 , d 2 . . . , d k d_1,d_2...,d_kd 1,d 2...,d k分别表示第k个维度。(N太难翻译了,总感觉没翻译对)如果reduction='mean'或'sum',
python
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
dataset = torchvision.datasets.CIFAR10('./dataset', train=False, transform=transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.model = Sequential(
Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),
MaxPool2d(kernel_size=2, stride=2),
Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),
MaxPool2d(kernel_size=2, stride=2),
Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),
MaxPool2d(kernel_size=2, stride=2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x): # 模型前向传播
return self.model(x)
model = Model() # 定义模型
loss_cross = nn.CrossEntropyLoss() # 定义损失函数
for data in dataloader:
imgs, targets = data
outputs = model(imgs)
# print(outputs) # 先打印查看一下结果。outputs.shape=(2, 10) 即(N,C)
# print(targets) # target.shape=(2) 即(N)
# 观察outputs和target的shape,然后选择使用哪个损失函数
res_loss = loss_cross(outputs, targets)
res_loss.backward() # 损失反向传播
print(res_loss)
#
# inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
# targets = torch.tensor([1, 2, 5], dtype=torch.float32)
#
# inputs = torch.reshape(inputs, (1, 1, 1, 3))
# targets = torch.reshape(targets, (1, 1, 1, 3))
#
# # -------------L1Loss--------------- #
# loss = nn.L1Loss()
# res = loss(inputs, targets) # 返回的是一个标量,ndim=0
# print(res) # tensor(1.6667)
#
# # -------------MSELoss--------------- #
# loss_mse = nn.MSELoss()
# res_mse = loss_mse(inputs, targets)
# print(res_mse)
#
# # -------------CrossEntropyLoss--------------- #
# x = torch.tensor([0.1, 0.2, 0.3]) # (N,C)
# x = torch.reshape(x, (1, 3))
# y = torch.tensor([1]) # (N)
# loss_cross = nn.CrossEntropyLoss()
# res_cross = loss_cross(x, y)
# print(res_cross)