损失函数与反向传播
损失函数
损失函数(Loss Function)是用来度量模型预测值与真实标签之间差异的函数。它接受模型的输出和真实标签作为输入,并输出一个数值,该数值表示模型预测的错误程度或差异程度。损失函数通常被设计成非负的,当模型预测值与真实标签完全一致时,损失函数达到最小值。
损失函数大致可以分成两类:回归(Regression)和分类(Classification)。
常见的损失函数:
交叉熵损失函数(Cross-Entropy Loss):
用于多分类任务,特别是在类别互斥的情况下;
均方误差损失函数(Mean Squared Error Loss):
用于回归任务;
计算模型输入与真实标签之间的平方差;
平均绝对误差损失函数(Mean Absolute Error Loss):
用于回归任务;
计算模型输出与真实标签之间的绝对差;
反向传播
反向传播(Backpropagation):反向传播是深度学习中的一种核心算法,用于计算损失函数对模型每一个参数的梯度。在优化模型参数(例如使用梯度下降算法)的过程中,我们需要知道模型每一项参数的梯度方向,以此来更新参数。
反向传播算法工作流程如下:
前向传播(Forward Pass):数据沿着从输入层至输出层的方向进行传播,经过每一层的操作,最终在输出层产生预测值。
损失计算:根据模型的预测值和真实值,使用损失函数计算损失。
反向传播(Backward Pass):根据链式法则(Chain Rule),从输出层开始,沿着网络的结构向反方向(输入层方向)回传,计算损失函数对每一层参数的梯度。
反向传播能够有效地计算损失函数关于每一个参数的梯度,结合优化算法(如SGD,Adam等),这使得我们可以通过梯度下降法更新模型的参数,进而训练我们的模型。(上面说的训练的目标就是找到一组参数可以最小化损失函数,这里更新参数就是为了这个目的)
总结
torch.nn 里的 loss function 衡量误差,在使用过程中根据需求使用,注意输入形状和输出形状即可
loss 衡量实际神经网络输出 output 与真实想要结果 target 的差距,越小越好
作用:
- 计算实际输出和目标之间的差距
- 为我们更新输出提供一定的依据(反向传播):给每一个卷积核中的参数提供了梯度 grad,采用反向传播时,每一个要更新的参数都会计算出对应的梯度,优化过程中根据梯度对参数进行优化,最终达到整个 loss 进行降低的目的
梯度下降法:
1. L1LOSS
input:(N,*) N是batch_size,即有多少个数据;*可以是任意维度
CLASS torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
小例子:
代码
import torch
from torch.nn import L1Loss
# 实际数据或网络默认情况下就是float类型,不写测试案例的话一般不需要加dtype
inputs = torch.tensor([1,2,3],dtype=torch.float32) # 计算时要求数据类型为浮点数,不能是整型的long
targets = torch.tensor([1,2,5],dtype=torch.float32)
inputs = torch.reshape(inputs,(1,1,1,3)) # 1 batch_size, 1 channel, 1行3列
targets = torch.reshape(targets,(1,1,1,3))
#L1Loss默认求均值的方式
loss = L1Loss()
#L1Loss改成求和的方式
#loss = L1Loss(reduction='sum')
result = loss(inputs,targets)
print(result)
运行结果:
tensor(0.6667)
L1Loss可以选择计算的方式,修改成求和的方式:
修改上述代码中的一句即可
loss = L1Loss(reduction='sum')
运行结果:
tensor(2.)
2.MSELOSS(均方误差)
input:(N,*) N是batch_size,即有多少个数据;*可以是任意维度
CLASS torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
添加如下几行代码:
from torch import nn
#MSELOSS(均方误差)
loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)
print(result_mse)
结果:
tensor(1.3333)
上述代码的例子:
3. CROSSENTROPYLOSS(交叉熵)
适用于训练分类问题,有C个类别
**例:**三分类问题,person,dog,cat
(公式中的 log 可以按 ln 算)
这里的output不是概率,是评估分数
添加如下代码:
#CROSSENTROPYLOSS(交叉熵)
x = torch.tensor([0.1,0.2,0.3])
y = torch.tensor([1])
x = torch.reshape(x,(1,3))#把x变成交叉熵要求的input格式(N,C)N为batch_size,C为类别数
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x,y)
print(result_cross)
结果:
tensor(1.1019)
4.如何在之前写的神经网络中用到 Loss Function(损失函数)
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x): # x为input
x = self.model1(x)
return x
loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in dataloader:
imgs, targets = data # imgs为输入,放入神经网络中
outputs = tudui(imgs) # outputs为输入通过神经网络得到的输出,targets为实际输出
result_loss = loss(outputs, targets)
print(result_loss) # 神经网络输出与真实输出的误差
结果:
5.backward 反向传播
计算出每一个节点参数的梯度
在上述代码result_loss = loss(outputs, targets)后加一行:
result_loss.backward() # backward反向传播,是对计算出来的result_loss,而不是对loss
在这一句代码前打上断点(运行到该行代码的前一行,该行不运行),debug 后:
tudui ——> model 1 ——> Protected Attributes ——> _modules ——> ‘0’ ——> bias / weight——> grad(是None)
点击Step into My Code,运行完该行后,可以发现刚刚的None有值了(损失函数一定要经过 .backward() 后才能反向传播,才能有每个需要调节的参数的grad的值)
下一节:选择合适的优化器,利用梯度对网络中的参数进行优化更新,以达到整个 loss最低的目的
one)
[外链图片转存中…(img-o6bLsm5T-1724861861970)]
点击Step into My Code,运行完该行后,可以发现刚刚的None有值了(损失函数一定要经过 .backward() 后才能反向传播,才能有每个需要调节的参数的grad的值)
[外链图片转存中…(img-KvOrYXrm-1724861861970)]
下一节:选择合适的优化器,利用梯度对网络中的参数进行优化更新,以达到整个 loss最低的目的