本博文是PyTorch的学习笔记,第11次内容记录,主要介绍损失函数和反向传播的使用。
损失函数(loss function)或代价函数(cost function)是将随机事件或其有关随机变量的取值映射为非负实数以表示该随机事件的“风险”或“损失”的函数。在应用中,损失函数通常作为学习准则与优化问题相联系,即通过最小化损失函数
求解和评估模型。
一般情况下,损失函数是用来表示实际输出和目标输出之间的差距,例如下例子中,实际得分分别为:10、10、10,目标分数为:30、20、50,实际得分与目标分数之间的差距计算方法如下:(30-10)+(20-10)+(50-10)=70,也就是说损失函数值为70。
损失函数的作用主要体现在下面两个方面:
在PyTorch的官网中介绍了一系列的损失函数及其使用方法,现以L1Loss的使用为例,在PyTorc官网中关于L1Loss函数的详细介绍:L1Loss函数。其中L1Loss函数的参数reduction在默认情况下等于mean,也就是求解实际输出和目标输出之间的差距的绝对值的均值,而当reduction="sum"时,取的是实际输出和目标输出之间差距的和。
通过实际代码实践一下用L1Loss函数计算损失,代码如下:
# coding :UTF-8
# 文件功能: 代码实现损失函数loss function功能
# 开发人员: dpp
# 开发时间: 2021/8/18 12:12 下午
# 文件名称: nn_loss.py
# 开发工具: PyCharm
import torch
from torch.nn import L1Loss
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))
loss = L1Loss(reduction="sum")
result = loss(inputs, targets)
print(result)
上述代码计算了实际输出[1, 2, 3]和目标输出[1, 2, 5]之间的L1Loss,代码输出结果为:
tensor(2.)
MSELoss是一个均方损失函数,其计算公式如下所示,与L1Loss类似,可以设置reduction参数来决定具体的计算方法。
通过实际代码实践一下用MSELoss函数计算损失,代码如下:
# coding :UTF-8
# 文件功能: 代码实现损失函数loss function功能
# 开发人员: dpp
# 开发时间: 2021/8/18 12:12 下午
# 文件名称: nn_loss.py
# 开发工具: PyCharm
import torch
from torch.nn import L1Loss, MSELoss
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))
loss = L1Loss(reduction="sum")
result = loss(inputs, targets)
print(result)
loss_mse = MSELoss(reduction="sum")
result_mse = loss_mse(inputs,targets)
print(result_mse)
上述代码计算了实际输出[1, 2, 3]和目标输出[1, 2, 5]之间的MSELoss,代码输出结果为:
tensor(2.)
tensor(4.) #均方误差损失函数计算结果
CrossEntropyLoss是表示交叉熵损失函数,PyTorch官网中关于交叉熵损失函数的计算方法如下:
此外,关于交叉熵损失函数计算方法的细节可以参照这个博文:交叉熵损失函数。
通过实际代码实践一下用CrossEntropyLoss函数计算损失,代码如下:
# coding :UTF-8
# 文件功能: 代码实现损失函数loss function功能
# 开发人员: dpp
# 开发时间: 2021/8/18 12:12 下午
# 文件名称: nn_loss.py
# 开发工具: PyCharm
import torch
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss
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))
loss = L1Loss(reduction="sum")
result = loss(inputs, targets)
print(result)
loss_mse = MSELoss(reduction="sum")
result_mse = loss_mse(inputs,targets)
print(result_mse)
x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3)) # 是一个3分类问题,所以reshape里面有3
loss_cross = CrossEntropyLoss()
result_cross = loss_cross(x, y)
print(result_cross)
上述代码计算了实际输出[0.1, 0.2, 0.3]和目标输出[1]之间的CrossEntropyLoss,代码输出结果为:
tensor(2.)
tensor(4.)
tensor(1.1019) #交叉熵损失函数计算结果
现在以CIFAR10数据集为例,在上一篇文章中最后搭建的神经网络中使用CrossEntropyLoss函数作为损失函数,讲解在神经网络中如何使用损失函数。具体代码如下:
# coding :UTF-8
# 文件功能: 代码实现在神经网络中使用损失函数的功能
# 开发人员: dpp
# 开发时间: 2021/8/18 3:52 下午
# 文件名称: nn_loss_network.py
# 开发工具: PyCharm
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10("CIFAR10", train=False,
transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Test(nn.Module):
def __init__(self):
super(Test, self).__init__()
self.model1 = Sequential(
Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
x = self.model1(x)
return x
test = Test()
loss = nn.CrossEntropyLoss()
for data in dataloader:
imgs, targets = data
outputs = test(imgs)
result_loss = loss(outputs, targets)
print(result_loss)
上述代码得到的输出结果如下:
tensor(2.4465, grad_fn=)
tensor(2.2060, grad_fn=)
tensor(2.2159, grad_fn=)
tensor(2.2214, grad_fn=)
tensor(2.2359, grad_fn=)
tensor(2.2378, grad_fn=)
...
上述结果中的数值较好的展示了神经网络中损失函数的计算结果情况。这个例子就很好的展示了损失函数的功能:计算实际输出值与目标输出值之间的差距。但是上述例子的损失函数的计算结果从一开始到最终并没有减小的趋势,均在2.2附近波动,但是真实的情况是要根据损失函数的值不断调整参数的值,并使损失函数值朝着梯度下降
的方向发展,这时就要用到优化器
,在下一篇文章中进行总结。
在本文中以主要总结了几种常用的损失函数,并通过实例介绍了每一种损失函数的具体用法,并将交叉熵损失函数在具体神经网络中的应用进行了举例,但是我们期望损失函数值不断下降,也就是真是输出值与目标输出值之间的差距不断缩小,因此在下一篇博文中将重点介绍优化器,使损失函数值朝着梯度下降的方向发展。