深度学习数学基础(二)~随机梯度下降(Stochastic Gradient Descent, SGD)

本文详细解析了梯度、导数和梯度消失、爆炸现象,介绍了批量、随机和mini-batch梯度下降方法,并通过可视化和实例探讨了优化策略。关键点包括梯度的几何意义、SGD的原理及抑制梯度问题的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. 梯度

1.1 理解导数 

1.2 理解梯度 gradient

1.3 理解梯度消失和梯度爆炸

1.4 抑制梯度消失和梯度爆炸

2. 逆梯度下降公示推导

2. 梯度下降方法比较

2.1 批量梯度下降

2.2 随机梯度下降(优化器optimizer)

2.3 mini-batch梯度下降

收敛性分析

3. 随机梯度下降可视化


1. 梯度

1.1 理解导数 

导数表示函数在每一点的变化率 \approx 切线的斜率,从微积分的角度理解,如果将x轴切分成无数小段,则导数公式可以表示为: 

f'(x) = \frac{\Delta y}{\Delta x} =k \approx \frac{f(x+\Delta x) - f(x)}{\Delta x}在定积分\Delta x无限小的情况下,近似认为曲线段上两点等于直线段。

1.2 理解梯度 gradient

本质:梯度gradient = 误差error的导数,即在该点处具有最大值方向的损失函数的导数L'(\theta)  

误差e,即损失函数loss,即为常用的损失函数有:交叉熵,最小二乘,BECLoss,e.g.。

L(\theta) = f(\theta; x) - y = \Delta y ,损失函数是关于参数\theta的函数,误差损失值随\theta的变化而变化。

梯度:数学意义上的梯度是一个矢量,大小为函数在某点处的偏导数,方向为函数值增长最大的方向,这里更具象一点就是导数切线向上增长的方向!!!

结合下图区分导数和梯度含义

  • 参数\theta为正时,导数=梯度大小为正值,导数方向在[0, 90度],梯度方向在[0, 90度],参数\theta沿着梯度方向变化,L(\theta)增长最快;
  • 参数\theta为负时,导数=梯度大小为负值,导数方向在在[270, 360],梯度方向在[90, 180],自变量\theta沿着梯度方向变化,L(\theta)增长最快。
  • =》梯度表示损失函数L(\theta)在该点处的变化率和方向,变化率大小=导数,梯度 gradient的符号(正或负)取决于损失函数loss的形状和参数\theta当前的位置。

假设我们的目标是最小化损失函数L(\theta) = \theta^2 +1,那如何能达到我们的最小化目标呢? 用逆梯度下降法,简称梯度下降。简单的理解,梯度就是对\theta求导,得到L'(\theta),逆梯度就是-L'(\theta),如果梯度值是负值(在0的左边),那么\theta沿逆梯度方向变化(更加的靠近0),损失函数值变得更小!同理,当梯度值为正值时,也一样。 

example of SGD of L(\theta) = \theta^2 +1

假设目标函数为损失函数,SGD逆梯度方向更新,学习率\alpha=0.1

当初始参数值在右侧时,假设\theta_0=4L(\theta_0) = 17

        Iteration 1: L'(\theta_0) = 9,update:\theta_1 = 4-0.1*9=3.1L(\theta_1) = 10.61

        Iteration 2: L'(\theta_1) = 7.2, update: \theta_2 = 4-0.1*7.2=2.38L(\theta_2) = 6.67

        ......直到\theta接近于0. 就问损失函数值是不是减小了!

当初始参数值在左侧时,假设\theta_0=-4L(\theta_0) = 17

        Iteration 1: L'(\theta_0) = -7,update:\theta_1 = -4-0.1*(-7)=-3.3L(\theta_1) = 11.89

        Iteration 2: L'(\theta_1) = -5.6, update: \theta_2 = 4-0.1*(-5.6)=-2.74L(\theta_2) = 8.5

        ......直到\theta接近于0. 导数为负值时,要注意参数值也为负,不要把参数值默认为正的!

优化的基本原则 Rule:

  • 加比减好做、乘比除好做、缩小比放大好做!
  • 最大化经过加负号由最小化来实现。这就是逆梯度下降(随机梯度下降)中“逆”的由来!梯度是损失函数值增大的最快方向,相反加负号后的逆梯度就是减小的最快方向。

有时候就很佩服学问渊博的专家,ta们总能把复杂的概念翻译成很标准的中文!

梯度,从字面理解就是坡度,山坡越陡,梯度越大!同样是走一步路,坡度大的地方上升的高度就高,坡度小的地方上升的高度就小,对比现实生活中的盘山公路!注意梯度的方向是向上的,而BP优化方向是向下的,所以BP全名是逆梯度方向下降! 

这里x, y轴表示参数\theta_0, \theta_1,z轴表示损失函数值J(\theta)。 

直观上,我们可以这样理解,一开始的时候我们随机站在山上的一个点。每一步,我们都以下降最多的路线来下山,那么,在这个过程中我们到达山底(收敛)是最快的,而学习率\alpha,它决定了我们“向下山走”时每一步的大小---参数优化步长,过小的话收敛太慢----梯度消失,过大的话可能错过最小值----梯度爆炸。➡️【扩展知识:详解机器学习中的梯度消失、爆炸原因及其解决方法】)。这是一种很自然的算法,每一步总是寻找使损失函数J下降最“陡”的方向(就像找最快下山的路一样)。 

1.3 理解梯度消失和梯度爆炸

“梯度消失”和梯度爆炸 -》梯度消失和梯度爆炸的根本原因来自于loss的值。

因为链式法则\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx}:BP每经过一层神经网络,损失函数偏导就得乘以一次权重wi上误差分偏导。

  • 如果求得的loss value较小。假定是3层神经网络,loss gradient=0.2。在指数级偏导相乘的加持下,0.2 * 0.2 * 0.2 = 0.008,这就是梯度消失。因为这么小的loss,对每层神经网络上参数\theta的影响急剧减小,直到0.008可以忽略不计了!这里可以看出梯度消失的本质是initial loss value很小。而这个很小是由embedding value很小得到得。
  • 如果求得的loss value较大。同样假定3层神经网络,loss gradient=200,在指数级相乘加持下,200*200*200=8000000,这就是梯度爆炸!因为这么大的loss,对每层神经网络上参数\theta的影响急剧变大,直到80000就不能承受了!这里同样可以得出梯度爆炸的本质是initial loss value过大。实际上较大的loss值来源于较大的向量值embedding values

Then,我们知道了梯度消失、梯度爆炸的根本原因是initial loss value太小、太大。而loss value太小、太大的原因是因为x embedding value值太小、太大!那么我们该如何抑制梯度消失和梯度爆炸呢?

1.4 抑制梯度消失和梯度爆炸

由上述分析得出,抑制梯度消失和梯度爆炸的根本措施是让loss value变得正常!这有两个方向可以动:参数和向量值。

参数方向

  • 参数放缩 scaling

向量值方向

embedding values adjustment,包括:激活函数、归一化等。

  • 激活函数:sigmoid、ReLU、ELU。这里不同的激活函数有不同的特性!没有最好的激活函数,只有最合适的激活函数!比如,sigmoid就比ReLU更好的抑制梯度爆炸。因为ReLU和ELU因为公式定义,无法处理embedding values中的较大值!
  • 归一化函数。torch.BatchNorm1d,对梯度消失和梯度爆炸有奇效哟

2. 逆梯度下降公示推导

我们把要最小化或最大化函数称为目标函数。当我们对其进行最小化时,我们也把它称为损失函数 loss function J(\theta).

求误差梯度 gradient

下面,我们假设一个损失函数为最小二乘估计:J(\theta )=\frac{1}{2} \sum_{i=1}^{m}(h_{\theta }(x)-y)^{2} ,其中h_{\theta }(x)=\theta_{0} +\theta_{1}x_{1}+\theta_{2}x_{2}+......+\theta_{n}x_{n} 然后要使得最小化它。

我们知道曲面上方向导数的最大值的方向就代表了梯度的方向,➡️【扩展知识:如何直观形象的理解方向导数与梯度以及它们之间的关系?

因此我们在做梯度下降的时候,应该是沿着梯度的反方向进行权重的更新(因为梯度指的是函数值增长最快的方向,而逆梯度是减小最快的方向),可以有效地找到全局的最优解。这里\theta 的更新过程可以描述为

a表示的是步长或者说是学习率(learning rate)

从数学的角度想,我们要找到损失函数的最小值。

  • 先想在低维的时候,比如二维,我们具体到1元函数f(x)=wx+b中时,梯度方向首先是沿着曲线的切线的,然后取切线向上增长的方向为梯度方向
  • 在2元或者多元函数中,梯度向量为损失函数f对每个变量求偏导,该向量最大值方向就是梯度的方向,当然向量的大小也就是梯度的大小

2. 梯度下降方法比较

随机梯度下降,实际上是逆随机梯度下降 

这里比较对象是批量梯度(Batch Gradient Descent)和mini-batch梯度下降,先看下他们三者:

2.1 批量梯度下降
  • 批量梯度下降:在每次更新时用所有样本,要留意,在梯度下降中,对于\theta_{i} 的更新,所有的样本都有贡献,也就是参与调整\theta.其计算得到的是一个标准梯度,对于最优化问题,凸问题,也肯定可以达到一个全局最优。因而理论上来说一次更新的幅度是比较大的。如果样本不多的情况下,当然是这样收敛的速度会更快啦。但是很多时候,样本很多,更新一次要很久,这样的方法就不合适啦。下图是其更新公式

2.2 随机梯度下降(优化器optimizer)

 由上面知道,为啥用随机逆梯度下降法,减小误差/loss。

BP更新:back propogation,包括:误差求导L'(\theta) + 参数更新

误差求导L'(\theta)

参数更新\theta^{new} = \theta^{old} - \alpha \cdot L'(\theta; x; y; \hat{y}). 这里逆梯度的逆体现在减号-上;\alpha是学习率,即更新步长;L'(\theta)是损失函数求偏导,求导我们所在这一layer of DNN model的分导。

  • 随机梯度下降算法:在每次更新时用1个样本,可以看到多了随机两个字,随机也就是说我们用样本中的一个例子来近似我所有的样本,来调整θ,因而随机梯度下降是会带来一定的问题,因为计算得到的并不是准确的一个梯度,对于最优化问题,凸问题,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。但是相比于批量梯度,这样的方法更快,更快收敛,虽然不是全局最优,但很多时候是我们可以接受的,所以这个方法用的也比上面的多。下图是其更新公式:

2.3 mini-batch梯度下降
  • mini-batch梯度下降:在每次更新时用b个样本,其实批量的梯度下降就是一种折中的方法,他用了一些小样本来近似全部的,其本质就是我1个指不定不太准,那我用个30个50个样本那比随机的要准不少了吧,而且批量的话还是非常可以反映样本的一个分布情况的。在深度学习中,这种方法用的是最多的,因为这个方法收敛也不会很慢,收敛的局部最优也是更多的可以接受!

了解之后,总的来说,随机梯度下降一般来说效率高,收敛到的路线曲折,但一般得到的解是我们能够接受的,在深度学习中,用的比较多的是mini-batch梯度下降。

收敛性分析

能收敛吗?

对于收敛性的问题,知乎上就有这个问题:为什么随机梯度下降方法能够收敛?,我比较赞赏李文哲博士的回答(推荐一看),总的来说就是从expected loss用特卡洛(monte carlo)来表示计算,那batch GD, mini-batch GD, SGD都可以看成SGD的范畴。因为大家都是在一个真实的分布中得到的样本,对于分布的拟合都是近似的。那这个时候三种方式的梯度下降就都是可以看成用样本来近似分布的过程,都是可以收敛的!

能收敛到什么地方:

能到的地方:最小值,极小值,鞍点。这些都是能收敛到的地方,也就是梯度为0的点。

当然,几乎不存在找到鞍点的可能,除非很碰巧,因为梯度下降是对损失函数每个维度分别求极小值,即分别求 关于 极小值。

然后是最小值和极小值,如果是凸函数,梯度下降会收敛到最小值,因为只有一个极小值,它就是最小值。

至于什么是凸函数,详见我的专栏文章: 掌握机器学习数学基础之凸优化

理论支持:

Optimization Methods for Large-Scale Machine Learning:这论文之前的问答也看到了,贴下知友的翻译。为什么我们更宠爱“随机”梯度下降?

ROBUST STOCHASTIC APPROXIMATION APPROACH TO STOCHASTIC PROGRAMMING

An Introduction to optimization

以上三个关于优化的文章,一切问题,自然随之而解。值得一看!

3. 随机梯度下降可视化

作者:量子位
链接:https://www.zhihu.com/question/264189719/answer/649129090
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


下面的这张动图演示,乍看就像就像是在复杂地形中作战的沙盘推演,其实揭示的是随机梯度下降(SGD)算法的本质。

让小球滚下山坡,找到它们分别落在哪个山谷里,原来梯度下降算法还能变得像游戏视频一样酷炫。

谷歌大脑东京研究员hardmaru转发了视频对应的文章,评价它“像极了即时战略游戏”。

可别光顾着好玩,视频还得配合文章一起“服用”才有效果。上面的热门视频就是摘自fast.ai成员Javier Ideami写的一篇科普文。

如果代码和公式让你感到枯燥,那么不妨从这段酷炫的SGD视频入手,再读一读这篇文章,它会帮你更直观地理解深度学习。

到底什么是梯度?

深度学习的架构和最新发展,包括CNN、RNN、造出无数假脸的GAN,都离不开梯度下降算法。

梯度可以理解成山坡上某一点上升最快的方向,它的反方向就是下降最快的方向。想要以最快的方式下山,就沿着梯度的反方向走。

看起来像沙盘推演的东西,其实是我们撒出的小球,它们会沿着梯度下降的方向滚到谷底。

而梯度下降算法的最终目的,是找到整个“地形”中的最低点(全局最小值),也就是海拔最低的山谷。

但在这片地形中,山谷可能不止一处(局部最小值),所以我们需要撒很多球,让它们分别落入不同山谷,最后对比高度找到其中的海拔最低点。

以上就是随机梯度下降(SGD)算法的基本思想。

### 随机梯度下降 (SGD) 算法详解 #### 定义与基本概念 随机梯度下降Stochastic Gradient Descent, SGD)是一种用于最小化损失函数的方法,在机器学习领域广泛应用。相比于批量梯度下降(Batch Gradient Descent)SGD每次仅使用一个样本来更新模型参数,这使得其具有更高的计算效率和更好的扩展性[^1]。 #### 工作机制 在每一轮迭代过程中,SGD会从训练集中随机选取一个样本,并基于该样本计算当前权重下的预测误差及其对应的梯度方向;随后按照预设的学习率调整权值向量的位置。通过不断重复这一过程直至满足停止条件为止,最终达到全局最优解附近或局部极小值点处。 #### 实现方式 下面给出Python语言中的简单实现: ```python import numpy as np def sgd(X, y, learning_rate=0.01, epochs=100): m, n = X.shape weights = np.zeros(n) for epoch in range(epochs): indices = list(range(m)) np.random.shuffle(indices) for i in indices: xi = X[i] yi = y[i] error = dot_product(xi, weights) - yi gradient = [xi_j * error for xi_j in xi] # 更新权重 weights -= learning_rate * np.array(gradient) return weights def dot_product(a, b): """ 计算两个向量之间的内积 """ return sum(x*y for x,y in zip(a,b)) ``` 此代码片段展示了如何利用SGD来拟合线性回归模型。需要注意的是实际应用中通常还需要加入正则项防止过拟合等问题的发生。 #### 应用场景 - **大规模数据处理**:对于非常庞大的数据集来说,传统批处理方法可能难以承受内存开销以及长时间运行带来的不便。而SGD能够有效降低资源消耗并加快运算速度。 - **在线学习**:当面对持续流入的新鲜数据流时,可以采用增量式的SGD来进行实时更新而不必每次都重新训练整个模型。 - **分布式计算环境支持**:得益于较低的通信成本及易于并行化的特性,SGD非常适合部署于多节点架构之上完成复杂任务求解工作[^3]。 尽管如此,由于依赖单一观测值估计整体趋势,因此可能会引入较大波动造成不稳定的收敛路径[^2]。此外,合理设置初始步长也是确保良好性能的关键因素之一。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天狼啸月1990

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值