码头牛牛Blog点我刷新(小声)

深度学习(十三)——损失函数与反向传播

码头牛牛·2023-08-24 21:13·814 次阅读

深度学习(十三)——损失函数与反向传播

一、损失函数:Loss Function#

官网文档:torch.nn — PyTorch 2.0 documentation

1. Loss Function的作用#

  • 每次训练神经网络的时候都会有一个目标,也会有一个输出。目标和输出之间的误差,就是用Loss Function来衡量的。所以,误差Loss越小越好的。

  • 此外,我们可以根据误差Loss,指导输出output接近目标target。即我们可以以Loss为依据,不断训练神经网络,优化神经网络中各个模块,从而优化output

Loss Function的作用:

(1)计算实际输出和目标之间的差距

(2)为我们更新输出提供一定的依据,这个提供依据的过程也叫反向传播

2. Loss Function中的函数介绍#

(1)nn.L1Loss#

计算MAE (mean absolute error),即假设输入为xi,目标为yi,特征数量为n。在默认情况下,nn.L1Loss通过下面公式计算误差:

i=1n|xiyi|n

Copy
class torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')

参数说明:

  • reduction:默认为 ‘mean’ ,可选meansum

    • reduction='mean'时,计算误差采用公式:

      i=1n|xiyi|n

    • reduction='sum'时,计算误差采用公式:

      i=1n|xiyi|

  • 需要注意的是,计算的数据必须为浮点数

代码栗子:

Copy
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') #reduction='mean' result1=loss1(input,target) result2=loss2(input,target) print(result1,result2)

(2)nn.MSELoss#

计算MSE (mean squared error),即假设输入为xi,目标为yi,特征数量为n。在默认情况下,nn.MSELoss通过下面公式计算误差:

i=1n(xiyi)2n

Copy
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')

参数说明:

  • reduction:默认为 ‘mean’ ,可选meansum

    • reduction='mean'时,计算误差采用公式:

      i=1n(xiyi)2n

    • reduction='sum'时,计算误差采用公式:

      i=1n(xiyi)2

代码栗子:

Copy
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') #reduction='mean' result_mse1=loss_mse1(input,target) result_mse2=loss_mse2(input,target) print(result_mse1,result_mse2)

(3)nn.CrossEntropyLoss(交叉熵)#

当训练一个分类问题的时候,假设这个分类问题有C个类别,那么有:

loss(x,class)=log(exp(x[class])jexp(x[j]))=x[class]+log(jexp(x[j])

*注意:其中的log在数学中表示的是ln,即以10为底的对数函数

举个栗子:

  • 我们对包含了人、狗、猫的图片进行分类,其标签的索引分别为0、1、2。这时候将一张的图片输入神经网络,即目标target)为1(对应标签索引)。输出结果为[0.1,0.2,0.3],该列表中的数字分别代表分类标签对应的概率。

  • 根据上述分类结果,图片为的概率更大,即0.3。对于该分类的Loss Function,我们可以通过交叉熵去计算,即:

    x=[0.1,0.2,0.3]x[class]=x[1]=0.2

    loss(x,class)=0.2+log[exp(0.1)+exp(0.2)+exp(0.3)]

那么如何验证这个公式的合理性呢?根据上面的栗子,分类结果越准确,Loss应该越小。这条公式由两个部分组成:

  • log(jexp(x[j]):主要作用是控制或限制预测结果的概率分布。比如说,预测出来的人、狗、猫的概率均为0.9,每个结果概率都很高,这显然是不合理的。此时log(jexp(x[j])的值会变大,误差loss(x,class)也会随之变大。同时该指标也可以作为分类器性能评判标准。

  • x[class]:在已知图片类别的情况下,预测出来对应该类别的概率x[class]越高,其预测结果误差越小。

参数说明:

  • Input: (N,C),其中N代表batch_sizeC代表分类的数量(或者叫标签数量),即数据要分成几类(或有几个标签)。

  • Target: (N),对于每个数据:0target[i]C1

代码栗子:

  • 仍然以上面图片分类栗子的结果为例,编写程序
Copy
import torch from torch.nn import L1Loss,MSELoss,CrossEntropyLoss x=torch.tensor([0.1,0.2,0.3]) y=torch.tensor([1]) x=torch.reshape(x,(1,3)) loss_cross=CrossEntropyLoss() result_cross=loss_cross(x,y) print(result_cross)
  • 直接用CIFAR 10数据进行实战分类:
Copy
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("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor()) dataloder=DataLoader(dataset,batch_size=1) class Demo(nn.Module): def __init__(self): super(Demo,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=self.model1(x) return x demo=Demo() loss=nn.CrossEntropyLoss() for data in dataloder: imgs,targets=data output=demo(imgs) # print(output) #[Run] 一共输出10个数据,分别代表该图像为各个标签的概率.具体如下: # tensor([[-0.0151, -0.0990, 0.0908, 0.0354, 0.0731, -0.0313, -0.0329, 0.1006, # -0.0953, 0.0449]], grad_fn= < AddmmBackward0 >) # print(targets) #[Run] 输出该图像真实的标签,具体如下: # tensor([7]) result_loss=loss(output,targets) print(result_loss)

二、反向传播#

如何根据Loss Function为更新神经网络数据提供依据?

  • 对于每个卷积核当中的参数,设置一个grad(梯度)。

  • 当我们进行反向传播的时候,对每一个节点的参数都会求出一个对应的梯度。之后我们根据梯度对每一个参数进行优化,最终达到降低Loss的一个目的。比较典型的一个方法——梯度下降法

代码举例:

  • 在上面的代码for循环的最后,加上:
Copy
result_loss.backward()
  • 上面就是反向传播的使用方法,它的主要作用是计算一个grad。使用debug功能并删掉上面这行代码,会发现单纯由result_loss=loss(output,targets)计算出来的结果,是没有grad这个参数的。
posted @   码头牛牛  阅读(814)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示
目录