4_损失函数和优化器

 教学视频:损失函数与反向传播_哔哩哔哩_bilibili

损失函数(Loss Function)

损失函数是衡量模型预测输出与实际目标之间差距的函数。在监督学习任务中,我们通常希望模型的预测尽可能接近真实的目标值。损失函数就是用来量化模型预测的误差大小的一种方法。

作用:

  1. 衡量模型性能: 损失函数的值越小,表示模型在训练集上的预测结果与实际标签越接近,即模型的性能越好。
  2. 指导模型优化(反向传播): 通过最小化损失函数来调整模型的参数,使得模型能够更准确地预测目标值。优化过程就是通过调整模型参数来减小损失函数的过程。可通过这个过程得到梯度。

常见的损失函数

常见的损失函数包括均方误差(Mean Squared Error, MSE)、交叉熵损失(Cross Entropy Loss)、对数损失(Log Loss)等,具体选择哪种损失函数取决于问题的类型和输出的形式。

pytorch官方网址:torch.nn — PyTorch 2.4 documentation

 

 接下来看几个损失函数:

L1Loss 

torch.nn.L1Loss(size_average=Nonereduce=Nonereduction='mean')

 如图所示,是这个函数所使用的的公式。看起来很复杂,其实就是对所有的损失求平均或求和。

另外我们需要注意输入和输出格式:

 使用案例:

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))

#没有指定参数reduction,则默认按均值方式计算,除此之外,还可以使用reduction='sum',使其求和
loss=nn.L1Loss()
#计算公式:(|1-1|+|2-2|+|5-3|)/3≈0.667
result=loss(inputs,targets)
print(result)

 MSELoss

平方差损失函数。

torch.nn.MSELoss(size_average=Nonereduce=Nonereduction='mean')

与上面的使用方法基本相同。

loss=nn.MSELoss()
result=loss(inputs,targets)
print(result)
#输出结果:tensor(1.3333)

 CrossEntropyLoss

交叉熵损失函数,特别适用于多分类任务和输出为概率分布的情况。这个我首次接触是在机器学习中的逻辑回归那部分。如果想要了解更多可以看我另一篇文章:0_(机器学习)逻辑回归介绍-CSDN博客

torch.nn.CrossEntropyLoss(weight=Nonesize_average=Noneignore_index=-100

reduce=Nonereduction='mean'label_smoothing=0.0)

注意此函数的输入和输出与前面两种略有不同:

x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
loss_cross=nn.CrossEntropyLoss()
result_cross=loss_cross(x,y)
print(result_cross)

 输出结果为:

tensor(1.1019)

反向传播(Backpropagation)

反向传播是一种有效的训练神经网络的方法,它利用链式法则计算损失函数对每个模型参数的梯度,并根据梯度更新参数。它是损失函数优化过程中的关键步骤。

作用:

  1. 计算梯度: 反向传播算法通过将损失函数的梯度从网络的输出层向输入层传播,计算每个参数对损失函数的影响程度。
  2. 参数更新: 计算得到的梯度可以用来更新模型的参数,使得损失函数值减小,从而提高模型的预测性能。

反向传播利用了链式法则来计算复杂的导数,高效地更新神经网络中的参数。这种算法使得深度学习模型可以在大量数据上进行训练,并从数据中学习到复杂的模式和关系。

测试代码:

from torch import nn
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset=torchvision.datasets.CIFAR10("../dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)

class MyNn(nn.Module):
    def __init__(self) :
        super().__init__()
        self.conv1=nn.Conv2d(3,32,5,padding=2)
        self.maxpool1=nn.MaxPool2d(2)
        self.conv2=nn.Conv2d(32,32,5,padding=2)
        self.maxpool2=nn.MaxPool2d(2)
        self.conv3=nn.Conv2d(32,64,5,padding=2)
        self.maxpool3=nn.MaxPool2d(2)
        self.flatten=nn.Flatten()
        self.linear1=nn.Linear(1024,64)
        self.linear2=nn.Linear(64,10)
        '''使用Sequential可以简化代码'''
        # self.model1=nn.Sequential(
        #     nn.Conv2d(3,32,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Conv2d(32,32,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Conv2d(32,64,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Flatten(),
        #     nn.Linear(1024,64),
        #     nn.Linear(64,10)
        # )


    def forward(self,x):
        x=self.conv1(x)
        x=self.maxpool1(x)
        x=self.conv2(x)
        x=self.maxpool2(x)
        x=self.conv3(x)
        x=self.maxpool3(x)
        x=self.flatten(x)
        x=self.linear1(x)
        x=self.linear2(x)
        # x=self.model1(x)
        return x

mynn=MyNn()
loss=nn.CrossEntropyLoss()
for data in dataloader:
    imgs,targets=data
    outputs=mynn(imgs)
    result_loss=loss(outputs,targets)
    result_loss.backward()
    print(result_loss)

在其中打上断点,如图:

然后debug运行查看参数,就可以看到在没有运行backward()函数之前,图中所指参数为空:

 那么现在往下运行一行试试:

 以上就是我们得到的梯度(梯度下降法中的梯度)。接下来选择合适的优化器,我们就可以对模型进行优化了。

优化器

官方文档:torch.optim — PyTorch 2.4 documentation

 用于优化神经网络模型的库,它的主要作用是实现各种优化算法,帮助模型在训练过程中更新参数以最小化损失函数。

有许许多多不同的优化器,入门阶段就不一一介绍。有需要可以自己查用法。

from torch import nn
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset=torchvision.datasets.CIFAR10("../dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)

class MyNn(nn.Module):
    def __init__(self) :
        super().__init__()
        self.conv1=nn.Conv2d(3,32,5,padding=2)
        self.maxpool1=nn.MaxPool2d(2)
        self.conv2=nn.Conv2d(32,32,5,padding=2)
        self.maxpool2=nn.MaxPool2d(2)
        self.conv3=nn.Conv2d(32,64,5,padding=2)
        self.maxpool3=nn.MaxPool2d(2)
        self.flatten=nn.Flatten()
        self.linear1=nn.Linear(1024,64)
        self.linear2=nn.Linear(64,10)
        '''使用Sequential可以简化代码'''
        # self.model1=nn.Sequential(
        #     nn.Conv2d(3,32,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Conv2d(32,32,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Conv2d(32,64,5,padding=2),
        #     nn.MaxPool2d(2),
        #     nn.Flatten(),
        #     nn.Linear(1024,64),
        #     nn.Linear(64,10)
        # )


    def forward(self,x):
        x=self.conv1(x)
        x=self.maxpool1(x)
        x=self.conv2(x)
        x=self.maxpool2(x)
        x=self.conv3(x)
        x=self.maxpool3(x)
        x=self.flatten(x)
        x=self.linear1(x)
        x=self.linear2(x)
        # x=self.model1(x)
        return x

mynn=MyNn()
loss=nn.CrossEntropyLoss()
optim=torch.optim.SGD(mynn.parameters(),lr=0.01)
for data in dataloader:
    imgs,targets=data
    outputs=mynn(imgs)
    result_loss=loss(outputs,targets)
    optim.zero_grad()
    result_loss.backward()
    optim.step()

优化输出结果,可以看到cost在逐渐变小:

tensor(358.2124, grad_fn=<AddBackward0>)
tensor(351.9559, grad_fn=<AddBackward0>)
tensor(328.9600, grad_fn=<AddBackward0>)
tensor(314.0949, grad_fn=<AddBackward0>)
tensor(306.4304, grad_fn=<AddBackward0>)
tensor(297.4454, grad_fn=<AddBackward0>)
tensor(288.6151, grad_fn=<AddBackward0>)
tensor(280.8827, grad_fn=<AddBackward0>)
tensor(273.8977, grad_fn=<AddBackward0>)
tensor(267.9252, grad_fn=<AddBackward0>)
tensor(262.4760, grad_fn=<AddBackward0>)
tensor(257.2650, grad_fn=<AddBackward0>)
tensor(252.2356, grad_fn=<AddBackward0>)
tensor(247.5495, grad_fn=<AddBackward0>)
tensor(243.2856, grad_fn=<AddBackward0>)
tensor(239.3630, grad_fn=<AddBackward0>)
tensor(235.6944, grad_fn=<AddBackward0>)
tensor(232.2151, grad_fn=<AddBackward0>)
tensor(228.8934, grad_fn=<AddBackward0>)
tensor(225.7084, grad_fn=<AddBackward0>)

截图:

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值