Samar-blog

导航

P22_损失函数与反向传播

22.1损失函数的作用

  1. 计算实际输出和目标之间的差距
  2. 为我们更新输出提供一定的依据(反向传播)

22.2几种官方文档中的损失函数

打开torch.nn—Loss Functions:

【注意:损失函数只能处理float类型的张量,可在张量设置时加入dtype=torch.float或者张量中出现小数点】

1.L1Loss:

(1)其参数如下:

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

其中reduction默认是mean,也可以设置为sum

(2)举个例子

输入X:1,2,3

对应的目标Y:1,2,5

mean:L1loss = (0+0+2)/3 = 0.6667

sum:LL1loss = 0+0+2 = 2

(3)将上例写入代码
点击查看代码
import torch
from torch.nn import L1Loss

#损失函数只能处理float类型的张量
inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)

#将inputs和targets变成1batch_size、1channel,1行3列
inputs = torch.reshape(inputs,(1,1,1,3))
targets = torch.reshape(targets,(1,1,1,3))

loss = L1Loss()
result = loss(inputs,targets)

print(result)
(4)输出:

tensor(0.6667)

(5)设置reduction为sum

loss = L1Loss(reduction='sum')

输出为:
tensor(2.)

2.MSELoss(平方差):

(1)举个例子

输入X:1,2,3

对应的目标Y:1,2,5

则MSE=(0+0+2^2)/3 = 4/3 = 1.333

(2)写入代码:
点击查看代码
import torch
from torch.nn import L1Loss, MSELoss
from torch import nn

#损失函数只能处理float类型的张量
inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)

#将inputs和targets变成1batch_size、1channel,1行3列
inputs = torch.reshape(inputs,(1,1,1,3))
targets = torch.reshape(targets,(1,1,1,3))


loss_mse = MSELoss()
result_mse = loss_mse(inputs,targets)

print(result_mse)

(3)输出:

tensor(1.3333)

3.CrossEntropyLoss(交叉熵):

(1)交叉熵计算公式

想要loss小,就要使x[class]大(其前有负号)以及log的部分小;

假设要分成三类:person、dog、cat,现在给他们分别赋上标签:0,1,2

设person假如经过神经网络的输出output为[0.1,0.2,0.3],target是1(狗的标签是1);

此时,代入到计算公式里面,output就是x,target就是class:

P22_第三个loss的使用

则计算结果为:loss(x,class) = -0.2 + log(exp(0.1)+exp(0.2)+exp(0.3)),计算机里面log默认是以e为底,即loss(x,class) = -0.2 + ln(exp(0.1)+exp(0.2)+exp(0.3)),得到1.1019
P22_CrossEntropyLoss的计算结果

(2)CrossEntropyLoss的shape要求

Input:(N,C),C是类别数,N是batch_size

Target:N

Output:scalar

(3)写入代码:
点击查看代码
x = torch.tensor([0.1,0.2,0.3])
y = torch.tensor([1])

#按照Input的shape要求,把Input:(N,C),C是类别数,N是batch_size
#即分成三类:person,cat,dog;batch_size为一个
x = torch.reshape(x,(1,3))
#新建交叉熵
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x,y)

print(result_cross)
结果如下: `tensor(1.1019)` 与上面我们计算的结果一致;

22.3在神经网络中使用Loss Function:

1.将CIFAR10的数据集放到神经网络

点击查看代码
import torchvision.transforms
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 DYL_seq(nn.Module):
    def __init__(self):
        super(DYL_seq, self).__init__()
        self.model1 = Sequential(
            Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self,x):
        x = self.model1(x)
        return x

#创建网络
dyl_seq = DYL_seq()

#从dataloader去取数据
for data in dataloader:
    imgs,targets = data
    outputs = dyl_seq(imgs)
    print(outputs)
    print(targets)

2.输出:

点击查看代码
Files already downloaded and verified
tensor([[ 0.1075, -0.0205, -0.0137, -0.1302,  0.0355, -0.0131,  0.0246, -0.0382,
          0.1338,  0.0322]], grad_fn=<AddmmBackward0>)
tensor([3])
tensor([[ 0.0851,  0.0023,  0.0055, -0.1246,  0.0670, -0.0242,  0.0132, -0.0222,
          0.1512,  0.0251]], grad_fn=<AddmmBackward0>)
tensor([8])
......
结果中:

输入的图片放在神经网络中得到一个输出:一共有10个输出,每个值代表预测是这个类别的概率

[ 0.1075, -0.0205, -0.0137, -0.1302, 0.0355, -0.0131, 0.0246, -0.0382,0.1338, 0.0322]

其对应的tensor([3])代表其真实类别是3;

3.使用Loss Function

(1)添加代码:
点击查看代码
loss = nn.CrossEntropyLoss()

#创建网络
dyl_seq = DYL_seq()

#从dataloader去取数据
for data in dataloader:
    imgs,targets = data
    outputs = dyl_seq(imgs)
    result_loss = loss(outputs,targets)
    #CrossEntropyLoss的计算公式中,x就是神经网络的输出outputs,class就是targets
    print(result_loss)
(2)输出结果如下:
点击查看代码
Files already downloaded and verified
tensor(2.3312, grad_fn=<NllLossBackward0>)
tensor(2.1667, grad_fn=<NllLossBackward0>)
.......

我们得到的这些数:就是神经网络的输出和真实输出的误差

4.lossfunction的第二个作用:为我们更新输出提供一定的依据(反向传播)

(1)即grad

给每一个卷积核中的参数设置了一个grad梯度,当我们采用反向传播时,每一个要更新的参数就会求出对应多个梯度,在优化过程中,就会对其中参数进行一个优化

(2)代码如下
点击查看代码
x for data in dataloader:    imgs,targets = data    outputs = dyl_seq(imgs)    result_loss = loss(outputs,targets)    #CrossEntropyLoss的计算公式中,x就是神经网络的输出outputs,class就是targets    result_loss.backward()    #print(result_loss)    print("ok")
(3)把断点打在: result_loss.backward(),然后debug

可见:dyl_seq的modules下边的‘model1’中的modules的第一层‘0’里面的weight下边的gard为None

P22_weight下边的gard为None

(4)然后调试进入到下一步:

其gard梯度就计算出来了:
P22_调试到下一步后weight下边的gard为None

但是如果删掉了result_loss.backward,就会发现gard始终为none

所以:

要用backward去做反向传播,他就可以计算出每一个节点的参数,就得到各个节点的参数的梯度,接下里就可以选用合适的优化器,对其参数极限那优化,对loss达到降低的目的。

posted on 2025-11-22 18:08  风居住的街道DYL  阅读(0)  评论(0)    收藏  举报