torch.nn - PyTorch中文文档 (pytorch-cn.readthedocs.io)
torch.nn — PyTorch 2.3 documentation
Loss Function的作用
-
每次训练神经网络的时候都会有一个目标,也会有一个输出。目标和输出之间的误差,就是用Loss Function来衡量的。所以,误差Loss是越小越好的。
-
此外,我们可以根据误差Loss,指导输出output接近目标target。即我们可以以target为依据,不断训练神经网络,优化神经网络中各个模块,从而优化output
Loss Function的作用
- 计算实际输出和目标之间的差距
- 为我们更新输出提供一定的依据,这个提供依据的过程也叫反向传播。
nn.L1Loss
创建一个衡量输入x
(模型预测输出
)和目标y
之间差的绝对值的平均值的标准。
class torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
参数说明:
-
reduction:默认为 ‘mean’ ,可选mean和sum。
- 当
reduction='mean'
时,计算误差采用公式:
- 当
reduction='sum'
时,计算误差采用公式:
需要注意的是,计算的数据必须为浮点数。
程序代码:
import torch
from torch.nn import L1Loss
input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5],dtype=torch.float32)
input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))
loss1=L1Loss() #reduction='mean'
loss2=L1Loss(reduction='sum')
result1=loss1(input,target)
result2=loss2(input,target)
print(result1,result2)
输出:
nn.MSELoss
创建一个衡量输入x
(模型预测输出
)和目标y
之间均方误差标准。
-
x
和y
可以是任意形状,每个包含n
个元素。 -
对
n
个元素对应的差值的绝对值求和,得出来的结果除以n
。 -
如果在创建
MSELoss
实例的时候在构造函数中传入size_average=False
,那么求出来的平方和将不会除以n
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
参数说明:
reduction:默认为 ‘mean’ ,可选mean和sum。
- 当
reduction='mean'
时,计算误差采用公式:
- 当
reduction='sum'
时,计算误差采用公式:
程序代码:
import torch
from torch.nn import L1Loss,MSELoss
input = torch.tensor([1,2,3],dtype=torch.float32)
target = torch.tensor([1,2,5],dtype=torch.float32)
input = torch.reshape(input,(1,1,1,3))
target = torch.reshape(target,(1,1,1,3))
loss_mse1 = MSELoss() #reduction='mean'
loss_mse2 = MSELoss(reduction='sum')
result_mse1 = loss_mse1(input, target)
result_mse2 = loss_mse2(input, target)
print(result_mse1, result_mse2)
输出:
nn.CrossEntropyLoss(交叉熵)
当训练一个分类问题的时候,假设这个分类问题有C个类别,那么有:
当weight
参数被指定的时候,loss
的计算公式变为:
计算出的loss
对mini-batch
的大小取了平均。
形状(shape
):
-
Input: (N,C) 其中N代表batch_size,
C
是类别的数量即数据要分成几类(或有几个标签)。 -
Target: (N)
N
是mini-batch
的大小,0 <= targets[i] <= C-1
举个例子:
-
我们对包含了人、狗、猫的图片进行分类,其标签的索引分别为0、1、2。这时候将一张狗的图片输入神经网络,即目标(target)为1(对应狗的标签索引)。输出结果为[0.1,0.2,0.3],该列表中的数字分别代表分类标签对应的概率。
-
根据上述分类结果,图片为人的概率更大,即0.3。对于该分类的Loss Function,我们可以通过交叉熵去计算,即:
那么如何验证这个公式的合理性呢?根据上面的例子,分类结果越准确,Loss应该越小。这条公式由两个部分组成:
- 1、log(∑jexp(x[j])
log(∑jexp(x[j])主要作用是控制或限制预测结果的概率分布。比如说,预测出来的人、狗、猫的概率均为0.9,每个结果概率都很高,这显然是不合理的。此时 log(∑jexp(x[j]) 的值会变大,误差loss(x,class)也会随之变大。同时该指标也可以作为分类器性能评判标准。
-
2、−x[class]:在已知图片类别的情况下,预测出来对应该类别的概率x[class]越高,其预测结果误差越小。
程序代码:
import torch
from torch import nn
from torch.nn import L1Loss
inputs = torch.tensor([1, 2, 3], dtype=torch.float)
targets = torch.tensor([1, 2, 5], dtype=torch.float)
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))
x = torch.tensor([0.1, 0.2, 0.3], dtype=torch.float)
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss_cross_1 = nn.CrossEntropyLoss(reduction='mean')
result_cross_1 = loss_cross_1(x, y)
loss_cross_2 = nn.CrossEntropyLoss(reduction='sum')
result_cross_2 = loss_cross_2(x, y)
print(result_cross_1, result_cross_2)
输出:
反向传播
如何根据Loss Function为更新神经网络数据提供依据?
-
对于每个卷积核当中的参数,设置一个grad(梯度)。
-
当我们进行反向传播的时候,对每一个节点的参数都会求出一个对应的梯度。之后我们根据梯度对每一个参数进行优化,最终达到降低Loss的一个目的。比较典型的一个方法——梯度下降法。
代码举例:
result_loss = loss(outputs, targets)
result_loss.backward()
- 上面就是反向传播的使用方法,它的主要作用是计算一个grad。使用debug功能并删掉上面这行代码,会发现单纯由
result_loss=loss(output,targets)
计算出来的结果,是没有grad这个参数的。