当前位置: 首页 > backend >正文

3 反向传播

3 反向传播

B站视频学习链接:3 反向传播

文章目录

  • 3 反向传播
    • 0 复习回顾
    • 1 反向传播原理
      • 1.1 引入原理
      • 1.3 求导法则
      • 1.4 求导计算图
    • 2 代码使用
      • 2.1 分块编写
      • 2.2 代码综合
    • 3 课后作业
      • 3.1 换一组变量进行推导并绘制其计算图
      • 3.2 增加模型复杂度继续进行`pytorch`求解
      • 3.3 尝试使用**二次函数模型**进行**反向传播**的求解


0 复习回顾

在上一节课程中,主要使用的是numpy库函数配合梯度下降算法来进行咱们权重的一个选取操作。

主要的模型是一个最简单的线性模型*(是线性模型里面最简单的一个哈)*,y^=x∗ω\hat{y}=x*\omegay^=xω,用这个模型进行的一个算法的模拟。就像是下面这个图片展示的这个样子。

**第一步、**咱们输入了变量xxx和相对应的权重www,并将这两个变量按照函数要求进行数值相乘,得到咱们的计算值y^\hat{y}y^

第二步、将得到的计算值y^\hat{y}y^作为输入重新进入下一层内求出损失函数losslossloss

image-20250828141240269

**第三步、**求解该损失函数在该条件下的梯度,∂lossn∂ω=2⋅xn⋅(xn⋅ω−yn)\frac{\partial loss_n}{\partial\omega}=2\cdot x_n\cdot(x_n\cdot\omega-y_n)ωlossn=2xn(xnωyn)

**第四步、**重新更新咱们的权重,ω=ω−α∂loss∂ω\omega=\omega-\alpha\frac{\partial loss}{\partial\omega}ω=ωαωloss,知道稳定收敛为止。

image-20250828141347184

咱们上一次的例子是一个线性的模型,同时还是线性模型里面最简单的一个模型,因此在计算解析式的时候难度不大,但是一般而言,咱们的深度学习网络是有很多层的,并且输入的变量个数也不仅仅只有一个,像是下面这图片所示。

试问这种类型的深度学习网络模型该如何求解他的解析式呢?

这个模型左侧有555xxx的输入,第一个隐层有666个节点,因此第一层就有303030个权重,那么后面慢慢累积起来,这个运算量大的恐怖,基本上是无法求解他的解析式的!

image-20250828141440063

那么我们应该如何求解他的梯度呢,这个时候咱们想到了链式法则


1 反向传播原理

1.1 引入原理

首先让我们上一点难度,看看双层的线性模型是个什么样子的,下面是一个双层的神经网络模型y^=W2(W1⋅X+b1)+b2\hat{y}=W_{2}(W_{1}\cdot X+b_{1})+b_{2}y^=W2(W1X+b1)+b2

image-20250828141859910

这个是一个双层的神经网络,首先咱们看看他的第一层,也就是权重w1w_1w1所在的那一层

image-20250829221621340

在这里面我们令H(1)H^{(1)}H(1)作为我们的隐层则有H(1)=W1TXH^{(1)} = W_1^{T}XH(1)=W1TX。这几个数据的形状为

image-20250829222722186

因此第一层是这个玩意儿,我们需要确定矩阵的形状大小,一定要求这W1W_1W1的大小是m×nm \times nm×n的其中mmmmmm表示的是matrixmultiplicationmatrix multiplicationmatrixmultiplication 每一个隐层都有一个偏置量即bias−bbias-bbiasbb1b_1b1mmm维度的

image-20250829161729428

然后我们将第一层的输出结果进行再一次的矩阵乘法,便得到了第二层的神经网络。

image-20250829161806892

而对于矩阵求导的话可以找一本书叫做mairixcookbookmairix\ cookbookmairix cookbook这本书

本地位置: [martix cookbook.pdf](…\martix cookbook.pdf)
网络连接:martix-cookbook-pdf

j如果咱们现在将上面讲的双层线性模型进行展开可以得到下面这个东西,不难看出多层线性变换可以获得同一个形式的解,因此这么多层就没有意义了,故需要添加非线性的层才有意义。
y^=W2(W1⋅X+b1)+b2=W2⋅W1⋅X+(W2b1+b2)=W⋅X+b\begin{aligned}&\hat{y}=W_{2}(W_{1}\cdot X+b_{1})+b_{2}\\&=W_{2}\cdot W_{1}\cdot X+(W_{2}b_{1}+b_{2})\\&=W\cdot X+b\end{aligned} y^=W2(W1X+b1)+b2=W2W1X+(W2b1+b2)=WX+b
就像下面一样我们可以适当的引入一些非线性层会更加的有意义。

image-20250829162319156

上面就是采用了一些非线性的函数进行了优化以防止展开成基本相同的线性函数。

1.3 求导法则

image-20250829162557375

上面是一个比较好的一个概念,其中g,fg , fg,f这两个分别是两种对应法则,fog(x)fog(x)fog(x)就是f(g(x))f(g(x))f(g(x))因此,如果相对x求导数,那么就需要使用矩阵的链式法则。

dfog(x)dx=dfog(x)dg(x)×dg(x)dx\frac{\mathrm{d}fog(x)}{\mathrm{d}x}=\frac{\mathrm{d}fog(x)}{\mathrm{d}g(x)}\times\frac{\mathrm{d}g(x)}{\mathrm{d}x}dxdfog(x)=dg(x)dfog(x)×dxdg(x)

最主要的就是这个链式法则在矩阵上面的应用。

1.4 求导计算图

现在咱们同样对一个最简单的模型y^=x×ω\hat{y}=x\times \omegay^=x×ω进行讲解。

**前馈;**输入参数x,wx,wx,w我们将这两个参数传入到模型f(x)f(x)f(x)中,便可以得到第一个函数z=f(x,w)z= f(x,w)z=f(x,w),这个时候的zzz实际上就是所谓的虚拟计算值,将这个数值和真实值一起边可求得损失函数loss()loss()loss(),有了损失函数便可以使用梯度下降算法进行权重的求解啦。

**反馈(反向传播);**反向和正向在说法上就刚好相反,首先我们得到了损失函数关于传入参数zzz的导数∂z∂ω\frac{\partial z}{\partial \omega}ωz这时候我们拟用链式求导法则,通过∂L∂x=∂L∂z⋅∂z∂x\frac{\partial L}{\partial x}=\frac{\partial L}{\partial z}\cdot\frac{\partial z}{\partial x}xL=zLxz求得zzzxxx的导数;通过∂L∂ω=∂L∂z⋅∂z∂ω\frac{\partial L}{\partial\omega}=\frac{\partial L}{\partial z}\cdot\frac{\partial z}{\partial\omega}ωL=zLωz求得zzzω\omegaω的导数。

image-20250829163257883

这就是一个最简单的求导计算图。黑色箭头就是最简单的从前面到后面的一个前馈,而红色箭头便是反向传播。

举一个例子吧。

image-20250829163327331

上面就是一个正向的前馈处理。

image-20250829163536505

这个是反向传播,首先在进行前面的传播过程我们可以得到lllzzz的导数是555然后反向及逆行。这个样子就可以求出相应的www了。注意哈l对zzz的偏导是给出的。

现在给出一个具体的模型来处理尝试

image-20250829164150723

先进行前向处理,后进行反向传播之后便可以得到解答。


2 代码使用

2.1 分块编写

咱们使用的是pytorch进行编写哈。其中的所有的数据均是在一个叫做Tensor的东西。然后我们又开了两个玩意儿一个是他的数据datadatadata也即是权重,另一个是gradgradgrad也就是所谓的梯度也即是损失函数对权重的导数。这两个就是最重要的两个参数。

image-20250829223830943

因此对于一个普通的最简单的线性模型y^=x×ω\hat{y}=x\times \omegay^=x×ω而言他的计算图绘制如下所示。

image-20250829225912780

在进行代码编写的时候最重要的就是整出这样子的计算图

现在让我们正式开始代码的编写。

首先引入库,同时定义训练数据,并初始化权重,同时开启自动保存梯度的开关。

import torch # 引入库x_data = [1.0, 2.0, 3.0] #给定训练数据
y_data = [2.0, 4.0, 6.0]w = torch.Tensor([1.0]) # 初始化权重
w.requires_grad = True # 开启自动保存梯度的开关

image-20250829164823859

注意:w.requires_grad = True这个表示的是需要进行梯度的计算,并开启自动保存。

然后咱么开始各个函数的配置。

首先就是前馈相乘函数forward()

其次就是计算损失的损失函数loss()

def forward(x): #前馈相乘函数return x * wdef loss(x, y): # 计算损失的损失函数y_pred = forward(x)return (y_pred - y) ** 2

image-20250829213540998

image-20250829213706377

注意:xxxwww是一个数乘,但是xxx并不是一个tensortensortensor需要将xxx转换成tensortensortensor即可。

现在就可以进行深度学习求解权重的处理了。

这里给一个以循环轮数为循环变量,同时循环的最大轮数为100轮;

其次读取咱们的训练数据;

开始进行计算图的前馈模拟;

前馈完毕后进行反向传播backward()

然后重新更新这个权重,

更新好之后将权重里面的梯度数据进行一个清理操作即可。

print("predict (before training)", 4, forward(4).item())for epoch in range(100): #以循环轮数为循环变量,同时循环的最大轮数为100轮for x, y in zip(x_data, y_data): #读取咱们的训练数据l = loss(x, y) #计算图的前馈模拟l.backward() #进行反向传播print('\tgrad:', x, y, w.grad.item())w.data = w.data - 0.01 * w.grad.data #重新更新这个权重w.grad.data.zero_() #将权重里面的梯度数据进行一个清理print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())

image-20250829213921513

image-20250829213952830

注意:backward())这个函数用来反向传播并且计算路上的每一个梯度,同时将这个求出来的梯度存储在w里面。

但是一旦进行backward之后loss便被释放了,这个计算图就没了。

image-20250829214132202

注意:获取梯度的数据方法,注意这个grad也是一个tensor,一定要用data进行计算,要不然的话会整出一个新的计算图了。
item是将梯度的数值直接拿出来变成一个标量。防止产生计算图。
权重的更新一定要使用data而非直接用张量计算。防止出现计算图。

image-20250829214540316

注意:将权重里面的梯度数据全部进行一个清零操作。否则在下一轮的时候上一轮的梯度数据会进行一个重合操纵,这样就出问题了。

这就是使用pytorch来进行反向传播的操作。

2.2 代码综合

import torch # 引入库x_data = [1.0, 2.0, 3.0] #给定训练数据
y_data = [2.0, 4.0, 6.0]w = torch.Tensor([1.0]) # 初始化权重
w.requires_grad = True # 开启自动保存梯度的开关def forward(x): #前馈相乘函数return x * wdef loss(x, y): # 计算损失的损失函数y_pred = forward(x)return (y_pred - y) ** 2print("predict (before training)", 4, forward(4).item())for epoch in range(100): #以循环轮数为循环变量,同时循环的最大轮数为100轮for x, y in zip(x_data, y_data): #读取咱们的训练数据l = loss(x, y) #计算图的前馈模拟l.backward() #进行反向传播print('\tgrad:', x, y, w.grad.item())w.data = w.data - 0.01 * w.grad.data #重新更新这个权重w.grad.data.zero_() #将权重里面的梯度数据进行一个清理print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())

3 课后作业

3.1 换一组变量进行推导并绘制其计算图

image-20250829164407921

现在给出这个题目的解答。

1. 正向传播(前馈)

image-20250830101423445

2. 反向传播

image-20250830101402430

3. 计算图的绘制

image-20250830101029515

3.2 增加模型复杂度继续进行pytorch求解

image-20250829164440947

现在给出这个题目的解答

  1. 正向传播

image-20250830102441337

  1. 反向传播

image-20250830102423484

  1. 计算图绘制

image-20250830103237282

3.3 尝试使用二次函数模型进行反向传播的求解

image-20250829214924771

现在给出这个题目的解答

http://www.xdnf.cn/news/19075.html

相关文章:

  • WebStorm-在WebStorm中使用Git管理项目
  • Set和Map
  • Manus AI:突破多语言手写识别的技术壁垒,重塑全球交流方式
  • 【69页PPT】智慧方案智慧校园解决方案(附下载方式)
  • oceanbase-参数及变量的记录
  • 零成本解锁 Cursor Pro:虚拟卡白嫖1个月+14天试用全攻略
  • 【MFC自动生成的文件详解:YoloClassMFC.cpp 的逐行解释、作用及是否能删除】
  • 30分钟入门实战速成Cursor IDE(2)
  • B树的概述以及插入逻辑
  • 亚马逊的宝藏促销活动~
  • Java全栈开发实战:从基础到微服务的深度探索
  • KNN算法详解:鸢尾花识别和手写数字识别
  • 在做题中学习(91):二叉树的锯齿形层序遍历
  • Vue3 中的 v-model 语法糖
  • 什么是token,什么叫词嵌入
  • linux系统学习(9.文件系统管理)
  • Linux Shell 编程
  • Less介绍Less变量
  • C/C++ 编程实战 -- CMake用法
  • 隧道搭建技术
  • C++/python解决OpenCV的窗口被渲染到了屏幕外,导致imshow方法无法弹出窗口问题
  • JDK12安装步骤及下载(附小白详细教程)
  • 钉钉补卡事件处理方案
  • 算法---字符串
  • FDTD_mie散射_仿真学习(2)
  • 【机器人概念设计软件操作手册】 建模技巧与最佳实践
  • 自适应RAG架构:智能检索增强生成的演进与实现
  • 前端如何使用canvas实现截图
  • Python OpenCV图像处理与深度学习:Python OpenCV入门-图像处理基础
  • Linux之Docker虚拟化技术(二)