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

从零深度学习:(3)梯度下降

(1)反向传播

还是拿上节的例子:

当我们这时想要知道x的梯度是多少时,我们是无法得知的,此时输出为空。这是因为我们得需要进行一次反向传播,我们需要知道每个变量之间的函数关系式等信息,进而得到叶节点的导数值。

当我从最后的z节点进行反向传播之后,得到xyz三个变量之间的关系之后,就可以输出x的梯度值,这里也可以从高数的求导法则来检验一下:z = y^2 = 4x^2,求导得到8x,x=1带入得到8。

需要注意的是,执行反向传播之后只能查看叶节点也就是这里的最开始的x的导数,并且反向传播只能执行一次,如果再次执行就会报错如下:

如果出现这种情况只能重新再写一遍,当然我们也可以从y这里出发反向传播如下:

从哪个变量开始反向传播,就相当于那个变量对叶节点求导,所以可能会出现不同的结果,如下:

所以总结一下,反向传播就是通过已经自动保存的张量计算图来反向得到叶节点的梯度计算结果。

另外,由于只能计算叶节点的梯度,所以默认并不会保留中间节点的计算结果,会出现报错:

当然如果想要保留中间结果,可以使用retain_grad,如下:

(2)梯度下降基本思想

在之前的小节中,我们尝试使用最小二乘法来得到线性回归的全局最优解,但是最小二乘法有一个缺陷,就是使用条件比较苛刻,在实际情况中很多时候都不能满足使用条件。

所以相比较最小二乘法直接求导得到的解析解,梯度下降的思想也很朴素:从一个随机点出发,通过数学运算进行多次迭代,不断逼近最优解。

值得一提的是,我们通常指的梯度下降算法,并不是某一个算法,而是某一类依照梯度下降基本理论基础展开的算法簇,包括梯度下降算法、随机梯度下降算法、小批量梯度下降算法等等。接下来,我们就从最简单的梯度下降入手,讲解梯度下降的核心思想和一般使用方法。

在此之前我们画出过线性回归的目标函数的图像如下:

而梯度下降的方法示意图如下:

尽管如此,这个方法理解起来简单,但是实现起来并不容易。当我们要实现这个方法的时候,首先随机挑选一个点不难,困难的是如何找到下一步朝哪里走以及走多远的问题,也就是步长和方向这两个问题。

首先我们来讨论方向的问题,梯度下降的解法是用局部最优推导全局最优,有点类似贪心的想法。当我们站在山顶,我们想知道从哪个方向到山底最快,自然的想法是从最陡峭的地方下降最快。于是问题就变成了如何找到目标函数变化最快的方向,这个方向在数学上叫做梯度向量的方向。

首先第一步假设我们随机挑选的点就在(0,0)这个点,我们通过计算可以得到函数的值:

下一步通过反向传播计算a和b的梯度值:

接着,我们确定好方向之后就要确定步长,我们这里并不是一步直接移动到(-28,-12)这个点,因为一旦我们走了一小步,该方向就不再是梯度方向了,梯度方向会随着每次移动而变化,所以我们的步长不能太大,这里我们先以0.01为例子。

所以这里我们进行下一轮迭代,得到新的函数值,继续进行反向传播求梯度。

可以看到当我们进行新一轮迭代之后,梯度向量的方向已经发生变化了,而这里的0.01并不是一定的,没有统一的规定,又被叫做学习率。再进行若干次迭代之后就能到达(1,1)的全局最优解了

(3)梯度下降的矩阵表示

前面我们通过代数的方法进行了举例,并尝试迭代了两轮,但是代数的表示方便理解但并不适合代码编写,所以我们需要将代数表达转化为矩阵的表达。下面我们还是以一个多元线性回归来举例:

f(x) = w_{1}x_{1} + w_{2}x_{2} + ...+w_{d}x_{d} +b

我们将所有x前的系数和最后的截距提取出来

\hat{w} = (w_{1},w_{2},...,w_{d},b)

\hat{x} = (x_{1},x_{2},...,x_{d},1)

所以方程就可以转化为f(x) = \hat{w} * \hat{x}^{T}

另外我们将所以x的具体取值放到一个大的矩阵当中,为了拿到截距同样加上一列1,如下:

同理将y的取值也拿出来:

第一步:计算梯度表达式

第二步:得到迭代移动距离

第三步:跟新参数w

(4)手动实现梯度下降

这里我们还是用上一节的线性回归的例子:

1*a +b = 2

3*a +b = 4

用代码实现如下:

一轮迭代之后结果:

使用函数编程:

#用函数编写进行迭代
def GradDescent(x,y,steps = torch.tensor(0.01,requires_grad = True),num = 1000):
    m,n = x.shape
    weights = torch.zeros(n,1,requires_grad = True)
    for k in range(num):
        grad = torch.mm(x.t(),(torch.mm(x,weights)-y))/2
        weights = weights -steps*grad
    return weights

从结果可以看到和上节用最小二乘法得到的(1,1)一致。


http://www.kler.cn/a/513673.html

相关文章:

  • 使用tritonserver完成clip-vit-large-patch14图像特征提取模型的工程化。
  • Matlab自学笔记四十五:日期时间型和字符、字符串以及double型的相互转换方法
  • JS宏进阶:正则表达式的使用
  • 【C++】filesystem 详解
  • 在Windows/Linux/MacOS C++程序中打印崩溃调用栈和局部变量信息
  • TongESB7.1.0.0如何使用dockercompose运行镜像(by lqw)
  • Unity编辑拓展显示自定义类型
  • JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南
  • Java设计模式 十二 享元模式 (Flyweight Pattern)
  • 【GitHub】登录时的2FA验证
  • 简识JVM栈中的程序计数器
  • CPU狂飙900%如何分析?怎么定位?怎么溯源处理
  • C语言 结构体
  • 2024年度总结-CSDN
  • 图片专栏——修改分辨率
  • SSTI注入
  • 【vim】vim编辑器如何设置行号
  • 【2024年终总结】我与CSDN的一年
  • 5、原来可以这样理解C语言_数组(5)sizeof 计算数组元素个数
  • 数字图像处理:实验五
  • Golang的文件处理优化策略
  • WPF 实现动态属性绑定与动态绑定详解
  • springboot 配置多数据源以及动态切换数据源
  • Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)
  • 利用大型语言模型在量化投资中实现自动化策略
  • 洛谷P2853 [USACO06DEC] Cow Picnic S