• 深度学习:手写反向传播算法(BackPropagation)与代码实现


    前置知识回顾

    损失函数:交叉熵
    优化方法:SGD与GD
    网络结构:多层感知机是如何运作的
    链式法则:
    请添加图片描述

    前向传播

    首先定义一个简单的三层全连接神经网络,其中为了方便运算,我们省略了激活函数与偏置系数b,网络结构如图所示:
    请添加图片描述

    下面我们开始前向计算: 请添加图片描述
    请添加图片描述

    1.在这里我们发现,其中计算的结果也就是隐藏层神经元的数值z1与z2,那么不难看出,我们把这次计算的输出当作下次计算的输入,就可以计算出z3与z4,这样逐层传播,就是上述网络的前想传播过程。
    2.当我们得到网络的结果矩阵z3与z4,下面我们要通过代价函数计算损失
    为了方便运算,我们采用均方误差(MSE)来计算损失计算过程如下:
    在这里插入图片描述

    其中y假设为真实值。
    上述过程就是前向计算的过程。

    反向传播

    计算完代价函数,我们就需要更新我们的参数,之前我们学习的梯度梯度下降法只能更新一层神经网络的参数,而在多层网络中,我们需要用到链式法则的知识来得到其他层参数的偏导数,就可以逐层更新参数。具体过程如下:
    我们从后往前更新参数:
    首先计算损失函数对第二层网络参数的偏导数
    ∣ ∂ l 1 ∂ w 5 ∂ l 1 ∂ w 7 ∂ l 2 ∂ w 6 ∂ l 2 ∂ w 8 ∣ = ∣ ∂ l 1 ∂ z 3 ∂ z 3 , ∂ w 5 ∂ l 4 ∂ z 3 ∂ z 3 ∂ w 7 ∂ l 2 ∂ z 4 ∂ z 4 ∂ W 6 ∂ l 2 ∂ z 4 ∂ z 4 ∂ W 8 ∣

    |l1w5l1w7l2w6l2w8|" role="presentation" style="position: relative;">|l1w5l1w7l2w6l2w8|
    =
    |l1z3z3,w5l4z3z3w7l2z4z4W6l2z4z4W8|" role="presentation" style="position: relative;">|l1z3z3,w5l4z3z3w7l2z4z4W6l2z4z4W8|
    w5l1w6l2w7l1w8l2 = z3l1w5z3,z4l2W6z4z3l4w7z3z4l2W8z4
    计算偏导数后,我们可以通过梯度下降法更新参数(这里假设a为学习率):
    ∣ w 5 − a ∂ l 1 ∂ w 5 w 7 − a ∂ l 1 ∂ w 1 , w 6 − a ∂ l 2 ∂ w 6 w 8 − a ∂ l 2 ∂ w 8 ∣ = ∣ w 5 ∗ w 7 ∗ w 6 ∗ w 8 ∗ ∣
    |w5al1w5w7al1w1,w6al2w6w8al2w8|" role="presentation" style="position: relative;">|w5al1w5w7al1w1,w6al2w6w8al2w8|
    =
    |w5w7w6w8|" role="presentation" style="position: relative;">|w5w7w6w8|
    w5aw5l1w6aw6l2w7aw1l1,w8aw8l2 = w5w6w7w8

    接着,我们就继续向前跟新,这里损失函数对参数的偏导数为:
    ∂ l 1 ∂ w 1 = ∂ l 1 ∂ z 1 ∂ z 1 ∂ w 1 = ∂ l 1 ∂ z 3 ∂ z 3 ∂ z 1 ∂ z 1 ∂ w 1 \dfrac{\partial l_{1}}{\partial w_{1}}=\dfrac{\partial l_{1}}{\partial z_{1}}\dfrac{\partial z_{1}}{\partial w_1}=\dfrac{\partial l_{1}}{\partial z_{3}}\dfrac{\partial z_3}{\partial z_{1}}\dfrac{\partial z_{1}}{\partial w_{1}} w1l1=z1l1w1z1=z3l1z1z3w1z1
    有了偏导数,我们就可以重复上述操作,直至更新完所有参数。

    代码实现

    import torch.nn as nn
    import torch.nn.functional as F
    
    x = torch.tensor([2.0,2.0],requires_grad=True)
    class model(nn.Module):
        def __init__(self,x):
            super(model, self).__init__()
            self.x = x
            self.fc1 = nn.Linear(2, 2)
            self.fc2 = nn.Linear(2, 2)
        def forward(self):
            x = self.fc1(self.x)
            x = self.fc2(x)
            return x
        
        
    x = model(x).forward() 
    x = x.sum().backward()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    哈工大李治军老师操作系统笔记【9】:内核级线程(Learning OS Concepts By Coding Them !)
    主机jvisualvm连接到tomcat服务器查看jvm状态
    应届女生美团 Java 岗 4 面,一次性斩 offfer,我受到了万点暴击
    想要糖尿病逆转,健康饮食必不可少
    基于Micropython的桌面信息小摆件
    SpringBoot整合Jpa实现增删改查功能(提供Gitee源码)
    LNK2001 无法解析的外部符号 cuGetErrorName解决
    抖音热搜查询易语言代码
    实时频谱 TFN 手持式频谱分析仪 RMT716A 9KHz-6.3GHz 高性能全功能
    JVM第十七讲:调试排错 - Java 问题排查之Linux命令
  • 原文地址:https://blog.csdn.net/qq_18555105/article/details/126677588