【端到端可微2】链式法则,论文:Introduction to Gradient Descent and Backpropagation Algorithm

论文:Introduction to Gradient Descent and Backpropagation Algorithm

文章目录

  • 0 前言
  • 1 链式法则
    • 定义
    • 作用
  • 2 单神经元的正向传播forward propagation
    • 定义
    • z 激活函数
  • 3 损失函数
    • 定义
  • 4 损失函数对权重张量的偏导数
    • 定义
      • z对w求偏导
      • l对z求偏导
  • 5 多个神经元的正向传播和 损失函数对权重张量的偏导数
      • z对w求偏导
      • l对z求偏导
  • 6 反向传播 backward propagation
    • 定义
  • 示例:单输出的梯度
  • 示例:多输出的感知机以及梯度
  • 示例:
    • 1加法节点的反向传播
    • 2 乘法节点的反向传播
    • 小结
  • 示例:复杂的函数的正向传播和反向传播
    • 1 Sigmoid函数
    • 2 Softmax-with-Loss 层
  • 总结
  • 参考
  • 附录

0 前言

专用名词:

  • 梯度下降
  • 深度学习的大致步骤( 构建神经网络—> 数据拟合 --> 选出最佳模型)
  • 选出最佳模型的方式,其实就是利用梯度下降算法,选出损失函数最小的那个。
  • 在深度学习当中,由于存在输入层,隐藏层,输出层,因此计算也会更加繁杂。
  • 正向传播,可以知道神经元的输出。
  • 目标函数,也叫做损失函数。计算正向传播的结果和真值结构的差异的公式。
  • 利用反向传播,逐层求出目标函数对各神经元权值的偏导数,构成目标函数权值张量梯度梯度是为了对权值的优化提供依据。
  • 权值优化了之后,再转为正向传播,当输出的结果达到设定的标准时,算法结束。

1 链式法则

定义

链式法则公式:
在这里插入图片描述
我们需要了解的就是链式法则:

在这里插入图片描述

在这里插入图片描述

通过扰动的思路,更容易理解链式法则,从扰动的角度来思考它会更直观。 ds 扰动 s 也会扰动 z,仍然可以推导得到链式法则
在这里插入图片描述

作用

链式法则,通过使用链式法则就可以把最后一层的误差一层一层的输出到中间层的权值中去,从而得到中间层的梯度信息,然后就可以很好的更新权值,得到最优化的效果。

对于一个简单的线性层来说不需要链式法则,但是对于对于实际的神经网络来说,展开公式是非常复杂的,不能直接一次到位,因此使用链式法则可以使得我们的求导过程非常简单。

2 单神经元的正向传播forward propagation

定义

在这里插入图片描述

用逻辑回归的神经元为例, z = w 1 x 1 + w 2 x 2 + b z = w_1x_1+w_2x_2 + b z=w1x1+w2x2+b。线性方程z会被代入到Sigmoid函数当中
在这里插入图片描述

一步步从左向右计算,最后得出结果,这就是称为正向传播(forward propagation)。

z 激活函数

在这里插入图片描述
Sigmoid函数的导数
在这里插入图片描述

3 损失函数

定义

正向传播的结果与真值的差异,用损失函数记为l,进行计算,例如,最小二乘法的损失函数。

假设实际值是y,损失函数是各个输出层的损失函数的累加,所以,整个神经网络的最小二乘损失函数就是:
在这里插入图片描述

4 损失函数对权重张量的偏导数

为了更新权重w,因此损失函数要对各个w求偏导,于是:
在这里插入图片描述
那么,这当中,最关键的部分,其实就是求sigma’(z),对于分类问题

定义

深度学习模型的优化目的是:修正权值w。让损失函数 l 对 w 求偏导,根据链式准则:
在这里插入图片描述

其中,

z对w求偏导

∂ z ∂ w \frac{\partial z}{\partial w} wz计算如下,是z对w求偏导:
在这里插入图片描述
又知道
z = w 1 x 1 + w 2 x 2 + b z = w_1x_1+w_2x_2 + b z=w1x1+w2x2+b

因此x1,x2其实就是最开始的输入值,因此可以当做是已知的。

l对z求偏导

而l对z求导,这个部分其实很复杂,用链式法则求解。

那么这个部分该怎么求呢?如下所示:

∂ l ∂ z = ∂ l ∂ a ∂ a ∂ z = ∂ l ∂ a σ ′ ( z ) (公式 1 ) \frac{\partial l}{\partial z} =\frac{\partial l}{\partial a} \frac{\partial a}{\partial z}=\frac{\partial l}{\partial a} \sigma '(z)(公式1) zl=alza=alσ(z)(公式1
上游传来的导数乘上局部导数,得出传给下游的导数

5 多个神经元的正向传播和 损失函数对权重张量的偏导数

如果存在多个神经元的传播,如下图:
在这里插入图片描述

损失函数对权重张量的偏导数,
在这里插入图片描述

z对w求偏导

∂ z ∂ w \frac{\partial z}{\partial w} wz计算如下,是z对w求偏导:
在这里插入图片描述

l对z求偏导

∂ l ∂ z \frac{\partial l}{\partial z} zl计算如下,

∂ l ∂ z = [ w 3 ∂ l ∂ z ′ + w 4 ∂ l ∂ z ′ ′ ] σ ′ ( z ) (公式 2 ) \frac{\partial l}{\partial z} = [w_{3}\frac{\partial l}{\partial z'} + w_{4}\frac{\partial l}{\partial z''}]\sigma '(z)(公式2) zl=[w3zl+w4z′′l]σ(z)(公式2

即:先求l对 z ′ z' z的导,以及l对 z ′ ′ z'' z′′的导,然后分别乘以w3和w4,在结合sigma’(z)。由于在正向传播的时候,z是已知,sigomid函数已知,因此sigma’(z)我们也是已知的。

同学们注意: z ′ z' z z ′ ′ z'' z′′是经过线性方程的结果,不是导数。本文中的导数都是用的 ∂ z {\partial z} z

不过,又产生新的问题了。dl/dz的求解,明显依赖于dl/dz’,以及dl/dz’’。那么这两项又是如何求的呢?答案是:根据输出值去求。任何一组数据,在经过神经网络运算之后,都会产生一个输出值,我们记为y。如下所示:
在这里插入图片描述这个时候,我们就要分情况讨论了。

第一种情况:y1与y2在都在输出层
这个时候,比较简单,根据下面这个公式,直接套用即可:

∂ l ∂ z ′ = ∂ l ∂ y 1 ∂ y 1 ∂ z ′ \frac{\partial l}{\partial z'} = \frac{\partial l}{\partial y_{1}}\frac{\partial y_{1}}{\partial z'} zl=y1lzy1
∂ l ∂ z ′ ′ = ∂ l ∂ y 2 ∂ y 2 ∂ z ′ ′ \frac{\partial l}{\partial z''} =\frac{\partial l}{\partial y_{2}} \frac{\partial y_{2}}{\partial z''} z′′l=y2lz′′y2

第二种情况:y1,y2存在不在输出层的情况
这个时候,那就一直算到输出层,然后再从输出层往回传播即可。

6 反向传播 backward propagation

定义

计算图的反向传播(backward propagation)也就是BP算法,计算的方式:沿着与正方向相反的方向,上游传来的导数乘上局部导数,得出传给下游的导数。

这样通过链式法则,就能够完成反向传播了。

例如公式2 ∂ l ∂ z = [ w 3 ∂ l ∂ z ′ + w 4 ∂ l ∂ z ′ ′ ] σ ′ ( z ) \frac{\partial l}{\partial z} = [w_{3}\frac{\partial l}{\partial z'} + w_{4}\frac{\partial l}{\partial z''}]\sigma '(z) zl=[w3zl+w4z′′l]σ(z),根据其计算流程,画出来了下面这个图,上游传来的导数乘上局部导数,得出传给下游的导数
在这里插入图片描述

示例:单输出的梯度

所谓的单输出,就是指,只输出一个值,如下图所示。我们假设这个单输出的网络如下所示:其中符号sum就是我们一直说的z,它经过sigma函数后,输出的结果是O,真实值是t,则他们之间的损失值就是E。
在这里插入图片描述

则,最小二乘法的损失函数E对某一个权值w求导的结果就是:

在这里插入图片描述因此,这个求导的结果,是可以直接根据神经网络的输出结果算出来的。

总结:
在这里插入图片描述

方法实现

输入10个特征的x

x = torch.randn(1,10)
# tensor([[ 0.5817, -1.1089, -0.9756, -0.4556, -0.2144, -1.1662,  1.9232,  0.2331,
#         -1.2987, -0.4950]])
w = torch.randn(1,10,requires_grad = True)
# tensor([[-1.0490, -1.7553,  0.1665, -0.0458, -0.8664, -0.3328, -0.1398,  1.2416,
#          1.3097, -0.4996]], requires_grad=True)
o = torch.sigmoid(x@w.t())
# tensor([[0.5831]], grad_fn=<SigmoidBackward>)
loss = F.mse_loss(torch.ones(1,1),o)
# tensor(0.1738, grad_fn=<MseLossBackward>)
loss.backward()
w.grad
# tensor([[-0.1179,  0.2248,  0.1977,  0.0923,  0.0435,  0.2364, -0.3898, -0.0472,
#          0.2632,  0.1003]])

这样就得到了每一个 w w w的梯度,随后可以根据 w ′ = w − 0.001 ∗ ∇ w 来更新参数了。

示例:多输出的感知机以及梯度

其实多输出的感知机已经不能叫做感知机了,因为感知机的定义就是一个单一输出的。而多输出的感知机相当于标准全连接层的输出层。

在这里插入图片描述

最小二乘法的损失函数E对某一个权值w求导的结果就是

在这里插入图片描述

from torch.nn import functional as F

x = torch.randn(1,10)
w = torch.randn(2,10,requires_grad = True)
o = torch.sigmoid(x@w.t())
o.shape # torch.Size([1, 2])
loss = F.mse_loss(torch.ones(1,2),o) # tensor(0.1849, grad_fn=<MseLossBackward>)
loss.backward()
w.grad
# tensor([[ 0.1048,  0.0295,  0.0433,  0.0624,  0.0105, -0.0463,  0.0789, -0.0975,
#         -0.0250, -0.0553],
#        [ 0.1950,  0.0549,  0.0805,  0.1162,  0.0196, -0.0862,  0.1467, -0.1815,
#         -0.0464, -0.1029]])

示例:

下面介绍一些节点的反向传播的方法

1加法节点的反向传播

在这里插入图片描述
首先来考虑加法节点的反向传播。这里以z = x + y为对象,观察它的反向传播。z = x + y的导数可由下式(解析性地)计算出来。
在这里插入图片描述
那么其反向传播就如下:

在这里插入图片描述
加法节点的反向传播将上游(反向传播右边为上游)的值原封不动地输出到下游

例子:
在这里插入图片描述

2 乘法节点的反向传播

在这里插入图片描述
接下来,我们看一下乘法节点的反向传播。这里我们考虑z = xy。这个
式子的导数用式(5.6)表示。
在这里插入图片描述
乘法的反向传播会将上游的值乘以正向传播时的输入信号的“翻转值”后传递给下游。翻转值表示一种翻转关系,如下图,正向传播时信号是x的话,反向传播时则是y;正向传播时信号是y的话,反向传播时则是x。
在这里插入图片描述
例子:
在这里插入图片描述
注意:
因为乘法的反向传播会乘以输入信号的翻转值,所以各自可按1.3 × 5 = 6.5、1.3 × 10 = 13计算。另外,加法的反向传播只是将上游的值传给下游,并不需要正向传播的输入信号。但是,乘法的反向传播需要正向传播时的输入信号值。因此,实现乘法节点的反向传播时,要保存正向传播的输入信号。

小结

其实还会有很多复杂的节点例如log节点,exp节点,/节点等等,其实会计算各种归根到底就是学会如何求这些函数的导数罢了。因此列举加法节点和乘法节点就是为了抛砖引玉,使得我们更形象的理解反向传播。

示例:复杂的函数的正向传播和反向传播

接下来让我看一些比较复杂的函数的正向传播和反向传播的过程。

1 Sigmoid函数

在这里插入图片描述

Sigmoid函数计算图的正向传播过程:
在这里插入图片描述
接下来进行反向传播:
为了方便表示,我们令
在这里插入图片描述

步骤1
“/”节点表示 ,它的导数可以解析性地表示为下式:
在这里插入图片描述

在这里插入图片描述

步骤2
“+”节点将上游的值原封不动地传给下游。计算图如下所示。
在这里插入图片描述
步骤3
“exp”节点表示y = exp(x),它的导数由下式表示。
在这里插入图片描述
在这里插入图片描述

步骤4
“×”节点将正向传播时的值翻转后做乘法运算。因此,这里要乘以−1。
在这里插入图片描述
至此,反向传播已经完成。

可以整理一下:
在这里插入图片描述

那么我们可以定义一个Sigmoid节点,其反向传播表示如下:
在这里插入图片描述

2 Softmax-with-Loss 层

下面来实现Softmax层。考虑到这里也包含作为损失函数的交叉熵误差(cross entropy error),所以称为“Softmax-with-Loss层”(Softmax函数和交叉熵误差)。

其正向传播如下:
在这里插入图片描述
为了方便表示,我们进行一下变量替换如下:
在这里插入图片描述
值得注意的是:
在这里插入图片描述
因为计算图是局部计算,图中的求导是将前面两个输入节点的看成不同变量的。虽然二者可能相关,但是还是要看成不同的变量,因此需要使用图的乘法规则来进行反向传播的计算。

接下来让我们一步步看看反向传播如何进行。

首先,交叉熵误差的反向传播:
在这里插入图片描述
在这里插入图片描述
“x”节点上游传过来的导数为1
“+”节点上游传过来的导数为-1
那列“x”节点上游传过来的导数都为-1
那列log节点上有传过来的导数分别为-t1、-t2、-t3

在这里插入图片描述

在这里插入图片描述

这里遇到“x”节点。
“×”节点将正向传播的值翻转后相乘。这个过程中会进行下面的计算。
在这里插入图片描述
即传给“/”的导数如下:

在这里插入图片描述

在这里插入图片描述
“+”节点原封不动地传递上游的值。
“×”节点将值翻转后相乘。

因为上面令
在这里插入图片描述
所以
在这里插入图片描述

在这里插入图片描述
最后exp节点的反向传播如下:
在这里插入图片描述
因为exp(x)的导数就是exp(x),求导还是他本身
所以第一个exp节点最后反向传播的结果如下(正向分流,反向合流):
在这里插入图片描述
因为开始令
在这里插入图片描述
所以最后就是
在这里插入图片描述
然后剩下的计算都是一样的了。

最终反向传播结果如下:

在这里插入图片描述
至此,Softmax-with-Loss 层反向传播的推导完成。

虽然一眼看上去感觉这个计算图十分复杂,但是一步步走过去每一步都是蛮简单的,这就是计算图的局部计算的优势了。

然后现在指定一个学习率lr(0.001等),假设我们第一个输入是a1经过反向传播得到的误差为y1-t1,那么更新a1的公式如下:

a1 *= a1 - lr * (y1-t1)

这就是BP算法思想的核心,即先正向传播,计算出误差(损失值,通常会用一个损失函数来衡量预测值与真实值的差距,例如交叉熵函数、均方误差函数等等),然后将误差反向传播,得出每个参数应当做多少的修改以更接近真实值,让误差变小,从而使模型进行训练。

深度学习模型的训练就是依靠误差反向传播调整参数进行的。

总结

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

参考

https://blog.csdn.net/johnny_love_1968/article/details/117598649
https://blog.csdn.net/johnny_love_1968/article/details/117849939
https://atcold.github.io/pytorch-Deep-Learning/en/week02/02-1/
https://blog.csdn.net/vincent_duan/article/details/113974739
https://blog.csdn.net/qq_52785473/article/details/127133611

附录

softmax 函数求导
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/202879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业软件的分类|app小程序网站定制开发

企业软件的分类|app小程序网站定制开发 企业软件是指为满足企业管理和运营需求而设计和开发的一类软件&#xff0c;它通常用于支持企业的各项业务活动和流程。根据其功能和应用领域的不同&#xff0c;可以将企业软件分为以下几类。 1. 企业资源计划&#xff08;ERP&#xff09…

Android性能优化 - 从SharedPreferences到DataStore

前言 对于android开发者们来说&#xff0c;SharedPreferences已经是一个老生常谈的话题了&#xff0c;之所以还在性能优化这个专栏中再次提到&#xff0c;是因为在实际项目中还是会有很多使用到的地方&#xff0c;同时它也有足够的“坑”&#xff0c;比如常见的主进程阻塞&…

k8s中批量处理Pod应用的Job和CronJob控制器介绍

目录 一.Job控制器 1.简介 2.Jobs较完整解释 3.示例演示 4.注意&#xff1a;如上例的话&#xff0c;执行“kubectl delete -f myJob.yaml”就可以将job删掉 二.CronJob&#xff08;简写为cj&#xff09; 1.简介 2.CronJob较完整解释 3.案例演示 4.如上例的话&#xf…

Tomcat的安装及其使用

一.下载安装 本文下载的是8.5版本的&#xff0c;下载链接&#xff1a;Apache Tomcat - Welcome! 切记解压缩的目录不要有中文存在。 二.启动Tomcat 在解压缩之后&#xff0c;会有很多文件存在&#xff0c;但是我们只需要在意两个文件&#xff01; webapps 目录 . web applica…

亚马逊产品如何在 TikTok 上推广?

对亚马逊卖家而言&#xff0c;TikTok是提升品牌社交媒体影响力的理想平台。该平台在过去一年中实现了飞速增长&#xff0c;使得营销变得既快捷又有趣&#xff0c;且高效。本文将详细阐述如何在TikTok推广亚马逊产品&#xff0c;并如何策划更强大的品牌营销活动。 各大品牌纷纷…

Anemone库的爬虫程序代码示例

以下是代码&#xff1a; ruby require anemone # 设置代理服务器 Anemone.proxies { http > "", https > "" } # 定义爬取的URL url # 使用Anemone进行爬取 Anemone.crawl(url) do |page| # 使用正则表达式找出所有的视频链接 video_…

Chrome显示分享按钮

分享按钮不见了&#xff01; Chrome://flags Chrome Refresh 2023 Disabled 左上角的标签搜索会到右上角。

Git - cherry-pick

文章目录 前言git资源 前言 本地 Git 仓库有两个分支&#xff0c;分别为 main 和 dev&#xff0c;dev 是 main 在 hash 为 a2 的时候创建的开发分支&#xff1a; 现在需要将 dev 分支中 hash 为 b1 的 commit 单独合并到分支 main 去&#xff1a; 这种将 dev 中部分特定 commi…

Windows系统如何远程控制Realme手机?

realme使用的是realme UI系统。realme UI是realme研发的操作系统&#xff1b;realme UI 1.0基于安卓10系统&#xff0c;realme UI 2.0基于安卓11系统&#xff0c;realme UI 3.0基于安卓12系统。 对于安卓4.0及以上系统的手机&#xff0c;都可以通过软件AirDroid实现远程控制。 …

JavaScript黑科技:简洁有用的一行代码,让你的开发效率飙升!

说在前面 在这篇技术博客中&#xff0c;我们将向你介绍一些令人惊叹的JavaScript黑科技&#xff0c;这些只需一行代码就能实现的简洁而有用的功能&#xff0c;将极大地提升你的开发效率。无论是优化代码、增加交互性&#xff0c;还是实现复杂的逻辑&#xff0c;这些代码片段将成…

echarts图表显示不全

图表显示是显示了&#xff0c;但是没有展示全部&#xff0c;一看控制台div的高度只有1px了&#xff0c;手动修改高度也只是拉伸图表&#xff0c;并没有按规定的尺寸展示 随之开始思考为什么呢 ? ? ? 因为 Echarts 的依赖是惰性的&#xff0c;需要手动设置resize&#xff0…

Android textView 显示: STRING_TOO_LARGE

默认情况下&#xff0c;TextView只能显示大约32K的字符。如果你的字符串超过这个限制&#xff0c;你将收到一个错误&#xff1a;“String too large”。 <string content" ...."/>问题点是&#xff1a;getResource().getString(R.string.content) 得到的是&am…

TableAgent:首个国产可私有部署的企业级Code Interpreter

TableAgent公测地址&#xff1a;https://tableagent.DataCanvas.com 数字化时代&#xff0c;数据分析的重要性犹如空气般无处不在。商业数据分析是数字化管理、智能决策的基础&#xff0c;同时数据分析又是一个专业性极强的工作&#xff0c;描述性分析、诊断性分析、预测性分…

【Azure 架构师学习笔记】- Azure Databricks (1) - 环境搭建

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 前言 Databricks 已经成为了数据科学的必备工具&#xff0c;今时今日你已经很难抛开它来谈大数据&#xff0c;它常用于做复杂的ETL中的T&#xff0c; 数据分析&#xff0c;数据挖掘等&#xff0c;…

论文学习-Attention Is All You Need

Attention Is All You Need 目前暂时不会用到&#xff0c;大概了解一下即可。 Recurrent model 序列化的计算方式&#xff0c;难以并行&#xff0c;随着序列的增长&#xff0c;以前的记忆会逐渐丢失。而Attention机制可以观察到句子中所有的信息&#xff0c;不受距离影响&…

MySQL中的JOIN与IN:性能对比与最佳实践

文章目录 JOIN与IN的基本介绍JOININ JOIN与IN性能对比使用JOIN的查询使用IN的查询 何时使用JOIN何时使用IN性能优化的其他考虑因素总结 &#x1f389;MySQL中的JOIN与IN&#xff1a;性能对比与最佳实践 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈…

基于单片机设计的激光测距仪(采用XKC-Kl200模块)

一、前言 随着科技的不断进步和应用需求的增加&#xff0c;测距仪成为了许多领域必备的工具之一。传统的测距仪价格昂贵、体积庞大&#xff0c;使用起来不够方便。本项目采用STC89C52单片机作为主控芯片&#xff0c;结合XKC-KL200激光测距模块和LCD1602显示器&#xff0c;实现…

C++输出100以内的素数

以下是一个简单的C程序&#xff0c;用于输出100以内的所有素数&#xff1a; #include <iostream>using namespace std;int main() { int num, i, flag 0; for(num 2; num < 100; num) { flag 0; for(i 2; i < num/2; i) { if(…

市场调研:2023年SLG游戏行业需求及发展前景预测

SLG游戏(SLG游戏)一般指策略游戏&#xff0c;策略游戏是一种以取得各种形式胜利为主题的游戏。这类游戏提供给玩家一个可以动脑筋思考问题来处理较复杂事情的环境&#xff0c;允许玩家自由控制、管理和使用游戏中的人、或事物&#xff0c;通过这种自由的手段以及玩家们开动脑筋…

第72讲:MySQL数据库锁机制剖析:行级锁、间隙锁与临键锁详解及应用指南

文章目录 1.行级锁的概念2.行锁的概念以及基本使用2.1.行锁的概念2.2.常见的SQL语句所对应的行锁类别2.3.行锁的基本使用 3.间隙锁和临键锁的概念以及基本使用3.1.间隙锁和临键锁的概念3.2.间隙锁和临键锁的基本使用 1.行级锁的概念 行级锁指的是&#xff0c;每次操作锁住的是…