深度学习之——反向传播

反向传播算法(BP):

前向传播通过训练数据和权重参数计算输出结果;反向传播通过导数链式法则计算损失函数对各参数的梯度,并根据梯度进行参数的更新。

1.前向传播

在前面的:全连接神经网络——前向传播中我们已经实现了神经网络的前向计算

这里就不过多介绍了,我们直接上代码:

import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.layer=nn.Sequential(
            nn.Linear(3*28*28,256),
            nn.ReLU(),
            nn.Linear(256,64),
            nn.ReLU(),
            nn.Linear(64, 10),
            nn.Softmax(dim=1)
        )
    #前向传播
    def forward(self,x):
        return self.layer(x)#这里是返回前向计算的输出
if __name__ == '__main__':
    net=Net()
    x=torch.randn(2,3*28*28)
    y=net.forward(x)
    print(y.shape)#torch.Size([2, 10])

2.损失计算

在:深度学习——损失函数这篇文章中我们也得到了两种不同的损失函数,接下来,我们就将利用前向计算所得到损失函数进行反向传播,去修正我们的权值。前面前向计算得到两个10分类的概率分布,这时我们将前向传播的结果和标签(真实值做对比)求损失。

这里就不过多介绍了,我们直接上代码(这里用到的是MSE损失):

    net=Net()
    x=torch.randn(2,3*28*28)
    y=net.forward(x)
    print(y.shape)#torch.Size([2, 10])
    loss_fun=nn.MSELoss()#构造损失函数
    target = torch.zeros(2,10)
    target[0:2,random.randrange(10)] = 1  # 定义标签,torch.Size([2, 10])
    loss=loss_fun(y,target)
    print(loss)

3.反向传播

如果,在输出层输出的数据和我们设定的目标以及标准相差比较大(损失函数较大),这个时候,就需要反向传播。利用反向传播,逐层求出目标函数对各神经元权值的偏导数(利用链式法则)。

构成目标函数对权值向量的梯度,之所以算这个,是为了对权值的优化提供依据(梯度下降的思想),等权值优化了之后,再转为正向传播……当输出的结果达到设定的标准时(损失函数足够低),算法结束。

反向传播的原理:(1)链式求导法则  (2)梯度下降

链式求导法则:

我们以逻辑回归的神经元为例子:

显然,在这神经元当中:

\large z=x_{1}w_{1}+x_{2}w_{2}+b

最后,这个线性方程z会被代入到Sigmoid函数当中,也就是说:

                                                        \large a=sigmoid(z)

计算之后都会产生一定的损失值,我们把这个损失函数记为loss(a:输出,A:标签):

\large loss=MSE(a,A)

反向传播的最终目的是修正权值w,那么我们让loss对w求偏导,根据链式准则:

\large \frac{\partial loss}{\partial w}=\frac{\partial z}{\partial w}\frac{\partial loss}{\partial z}(公式0)

\large \frac{\partial z}{\partial w_{1}}=x_{1}           \large \frac{\partial z}{\partial w_{2}}=x_{2}

\large \frac{\partial loss}{\partial z}=\frac{\partial a}{\partial z}\frac{\partial loss}{\partial a}

正向传播与反向传播其实是同时使用的。首先,你需要正向传播,来计算z对w的偏导,进而求出sigmoid(z)是多少。然后,根据输出层输出的数据进行反向传播,计算出loss对z的偏导是多少,最后,代入到(公式0)当中,即可求出loss对w的偏导是多少。注意,这个偏导,其实反应的就是梯度。然后我们利用梯度下降法,对这个w不断进行迭代(也就是权值优化的过程),使得损失函数越来越小,整体模型也越来越接近于真实值。

代码示例:

opt = optim.Adam(net.parameters())
opt.zero_grad()#梯度清空
loss.backward()#反向传播
opt.step()

猜你喜欢

转载自blog.csdn.net/GWENGJING/article/details/126796200