深度学习课程--assign2--optimizer优化器

梯度更新的算法

SGD梯度更新知识点:

随机梯度算法是基于梯度下降算法产生的
假设在regression problem中:
h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n h_{\theta}(x) = \theta _0 + \theta _1 x_1 + \theta _2 x_2 + ... + \theta _n x_n hθ(x)=θ0+θ1x1+θ2x2+...+θnxn
计算函数的损失函数cost- J ( θ ) J(\theta) J(θ)
J ( θ ) = 1 2 ∑ i = 1 n ( h θ ( x ) − y ) 2 ,   w h e r e   1 / 2   是 为 了 求 导 后 消 除 平 方 2 J(\theta) = \frac{1}{2} \sum_{i = 1}^n (h_{\theta}(x)-y)^2, ~ where~1/2~ 是为了求导后消除平方2 J(θ)=21i=1n(hθ(x)y)2, where 1/2 2
我们的目标是最小化函数的cost函数,即是 J ( θ ) J(\theta) J(θ), 由于存在很多歌参数 θ i \theta _i θi, 我们需要对每一个参数求偏导数,得到第一轮的梯度,然后反向更新
现假设我们对其中一个参数 θ j \theta_j θj, 求偏导:如下
∂ ∂ θ j J ( θ ) = ∂ ∂ θ j 1 2 ( h θ ( x ) − y ) 2 = ( h θ ( x ) − y ) ∗ ∂ ∂ θ j ( h θ − y ) = ( h θ ( x ) − y ) ∗ ∂ ∂ θ j ( ∑ i = 0 n θ i x i − y ) = ( h θ ( x ) − y ) x j \frac{\partial}{\partial \theta _j} J(\theta) = \frac{\partial}{\partial \theta _j} \frac{1}{2}(h_{\theta}(x)-y)^2 = (h_{\theta}(x)-y) * \frac{\partial}{\partial \theta _j}(h_{\theta}-y) = (h_{\theta}(x)-y)* \frac{\partial}{\partial \theta _j} (\sum_{i = 0}^n \theta _i x_i - y) =(h_{\theta}(x)-y)x_j θjJ(θ)=θj21(hθ(x)y)2=(hθ(x)y)θj(hθy)=(hθ(x)y)θj(i=0nθixiy)=(hθ(x)y)xj
加上learning rate α \alpha α,可以得到 完整的下降公式
θ j = θ j − α ( h θ ( x ) − y ) x j \theta _j = \theta _j - \alpha(h_{\theta}(x)-y)x_j θj=θjα(hθ(x)y)xj
θ j \theta _j θj 的初始值可以自己定, α \alpha α 也可自己定, x j x_j xj 已知,所以现在就是 h θ ( x ) h_{\theta}(x) hθ(x)函数未知,但我们求的是参数 所以可以给所有参数一个初始值,再用下降更新公式迭代,直到最后的迭代公式得到的超参数。

这就是梯度下降的流程,由于每一步的更新需要计算所有的参数的梯度,迭代速度会很慢,于是现在引用随机梯度下降算法,意思是每一次更新的时候就只使用一个样本进行梯度下降

因为这个样本是随机的,所以每次迭代没有办法得到一个准确的梯度,这样一来虽然每一次迭代得到的损失函数不一定是朝着全局最优方向,但是大体的方向还是朝着全局最优解的方向靠近,直到最后,得到的结果通常就会在全局最优解的附近。这种算法相比普通的梯度下降算法,
收敛的速度更快,所以在一般神经网络模型训练中,随机梯度下降算法 SGD 是一种非常常见的优化算法

梯度的更新是为了能够最稳最快到底山底。山底是指loss function的最小值。
下面将会介绍几种常规的梯度更新算法的内容以及代码实现,并比较各自的效果

SGD算法

SGD称为随机梯度算法,是最简单的更新算法。该方法通过在小批量数据上计算损失函数的梯度而迭代地更新权重W偏置项b。SGD在高度非凸数据的损失表面上远远超越了朴素梯度下降法,这种简单的爬山法技术已经主导了现代的非凸优化
该方法简单,直接就是用原始参数减去 学习率✖️ 参数的倒数
即 w = w - learning_rate ✖️ dw
或者写成: params = params - learning_rate * params_grad

SGD with Momentum算法

该算法在SGD的基础上添加了 Momentum和Velocity。Momentum将是一个值。而Velocity将会变成一个矢量[] or {}。
代码是
先更新velocity ,再更新参数

velocitys = momentum*velocitys - learning_rate*grads
params = params + velocitys

加上动量的原理是想要让震荡慢慢的缓和,并达到终止。

Nesterov Momentum 算法

这是Momentum的升级版,能使得损失函数收敛的更快

velocity = np.zeros_like(params)
velocity_prev = velocity 
velocity = momentum*velocity -  learning_rate * grads
#再次更新 velocity 
velocity = velocity + momentum * (velocity - velocity_prev)
params = params + velocity

Adagrad算法

cache = np.zeros_like(params)
cache = cache + grads**2 
params = params - learning_rate* grads/(np.sqrt(cache)+epsilon)
	   = params - (learning_rate/(np.sqrt(cache)+epsilon)) * grads

epsilon是为了防止值的溢出,set为一个很小的数字。
而这里做的变化是使得每个方向的梯度都有自己的learning rate 不再是固定learning rate值来调节grads。而这个变化是为了梯度较大的方向上梯度更新越来越慢,虽然梯度较小的方向的梯度更新也会越来越慢,但是变慢的速度明显小于前者。才会稳当的下去山底。
【简单的说就是,抑制大梯度方向上的更新,扩大小梯度方向上的更新,使得各个方向的梯度更新趋向一致。】
但也有缺点,因为当caceh越来越大,grads / (cache + epsilon) 会趋向于0,梯度更新消失。

RMSProp算法

RMSProp是Adagrad算法的进阶。它使用衰减系数来解决Adagrad后面导致梯度更新变成0而终止的问题。
引入decay_rate = 0.99

cache = np.zeros_like(params)
cache = decay_rate * cache + (1-decay_rate)* grads**2
params = params - learning_rate * grads / (np.sqrt(cache)+epsilon)

Adam算法

adam算法是RMSProp和Nesterov Momentum的combination。

扫描二维码关注公众号,回复: 12908680 查看本文章
#此时momentum是list or dist 
momentum = beta1 * momentum + (1-beta1)*grads 
velocity = beta2 * velocity + (1-beta2)*grads**2
cache_m = momentum / (1-beta1 ** t)
cache_v = velocity / (1-beta2 **t )
params = params - learning_rate * cache_m / (np.sqrt(cache_v)+epsilon)
t = t + 1  #每次迭代都要更新 

Nadam算法

momentum = beta1 * momentum + (1-beta1)*grads 
velocity = beta2 * velocity + (1-beta2)*grads**2
cache_m = momentum / (1-beta1 ** t)
cache_v = velocity / (1-beta2 **t )
#上面部分是Adam部分 
params = params - learning_rate/(np.sqrt(cache_v+eps) + beta1*chche_m +(1-beta1)*grads/(1-beta1**t))

猜你喜欢

转载自blog.csdn.net/Jiana_Feng/article/details/109713195