gpt4 book ai didi

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

转载 作者:我是一只小鸟 更新时间:2023-08-24 22:33:25 41 4
gpt4 key购买 nike

1、损失函数: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 ),即假设输入为 \(x_i\) ,目标为 \(y_i\) ,特征数量为 \(n\) 。在默认情况下, \(nn.L1Loss\) 通过下面公式计算误差:

\[\frac{\sum^{n}_{i=1}{|x_i-y_i|}}{n} \]

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

                        
                      

参数说明:

  • reduction :默认为 ‘mean’ ,可选 mean 和 sum .

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

      \[\frac{\sum^{n}_{i=1}{|x_i-y_i|}}{n} \]

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

      \[\sum^{n}_{i=1}{|x_i-y_i|} \]

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

代码栗子:

                        
                          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 ),即假设输入为 \(x_i\) ,目标为 \(y_i\) ,特征数量为 \(n\) 。在默认情况下, \(nn.MSELoss\) 通过下面公式计算误差:

\[\frac{\sum^{n}_{i=1}{(x_i-y_i)^2}}{n} \]

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

                        
                      

参数说明:

  • reduction :默认为 ‘mean’ ,可选 mean 和 sum .

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

      \[\frac{\sum^{n}_{i=1}{(x_i-y_i)^2}}{n} \]

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

      \[\sum^{n}_{i=1}{(x_i-y_i)^2} \]

代码栗子:

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

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

参数说明:

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

  • Target : \((N)\) ,对于每个数据: \(0\leq{target[i]}\leq{C-1}\) 。

代码栗子:

  • 仍然以上面图片分类栗子的结果为例,编写程序
                        
                          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 数据进行实战分类:
                        
                          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)

                        
                      

2、反向传播

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

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

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

代码举例:

  • 在上面的代码for循环的最后,加上:
                        
                          result_loss.backward()

                        
                      
  • 上面就是反向传播的使用方法,它的主要作用是计算一个 \(grad\) 。使用debug功能并删掉上面这行代码,会发现单纯由 result_loss=loss(output,targets) 计算出来的结果,是没有 \(grad\) 这个参数的。

最后此篇关于深度学习(十三)——损失函数与反向传播的文章就讲到这里了,如果你想了解更多关于深度学习(十三)——损失函数与反向传播的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com