花书《深度学习》《Deep Learning》学习笔记chapt

2019-03-07  本文已影响0人  no0758

第6章在泛泛而谈,初学者感觉很难了解到实际性的东西,不过也根据章节结构结合相关资料做下梳理。

6.1 XOR

**

6.2 基于梯度的学习

参考链接:An overview of gradient descent optimization algorithms

梯度下降法:

拟合函数:h(x)

损失函数J(\theta)

梯度:\frac{\partial{J(\theta)}}{\partial\theta}

迭代过程:沿着负梯度方向更新参数\theta = \theta - \alpha*\frac{\partial{J(\theta)}}{\partial\theta},其中\alpha为学习率(learning rate)或称步长,直到达到终止条件。

(1)三种梯度下降变体

a.全量梯度下降法(Batch gradient descent)

采用全部训练样本更新参数

for i in range ( nb_epochs ): # nb_epochs 为最大迭代次数
    params_grad = evaluate_gradient ( loss_function , data , params )
    params = params - learning_rate * params_grad

使用全部训练集,可以保证每次更新都会朝着正确的方向进行,最后收敛于极值点;但是学习时间太长,计算冗余且不能进行在线模型参数更新。

b.随机梯度下降法(Stochastic gradient descent)

每次从训练样本中随机取一个样本来更新参数

for i in range ( nb_epochs ):
    np.random.shuffle( data )
    for example in data :
        params_grad = evaluate_gradient ( loss_function , example , params )
        params = params - learning_rate * params_grad

计算速度快,但每次更新不一定会按照正确的方向进行,造成扰动,使得迭代次数增多,即收敛速度变慢,最终会收敛于极值点。

c.批量梯度下降(Mini-batch gradient descent)

每次从所有的训练样本中选取一部分样本来更新模型参数。

for i in range ( nb_epochs ):
    np.random.shuffle( data )
    for batch in get_batches ( data , batch_size =50):
        params_grad = evaluate_gradient ( loss_function , batch , params )
        params = params - learning_rate * params_grad

相对于SGD,更新过程更加稳定;相对于全量梯度下降,学习速度加快。

(2)挑战

(3)梯度下降优化算法(Gradient descent optimization algorithms)

a.Momentum

冲量梯度下降法就是在原来的梯度上加上了冲量(积累量)。个人理解就是当梯度与冲量方向一致时,增加参数更新的增量,加快了收敛;当梯度与冲量方向不一致时,减少了增量,使得参数更新过程的震荡减少。本质上与SGD没有区别。
v_t = \gamma v_{t-1}+\eta \nabla_{\theta}J(\theta)
\theta = \theta - v_t

有无冲量的参数更新过程

b.Nesterov accelerated gradient

NAG比Momentum的速度更快,因为把原来计算\nabla_{\theta}J(\theta)换成计算\nabla_{\theta}J(\theta-\gamma v_{t-1}),就是在提前计算了下一个梯度。
v_t = \gamma v_{t-1}+\eta \nabla_{\theta}J(\theta-\gamma v_{t-1})
\theta = \theta - v_t

c.Adagrad

前面的两种方法,在更新参数时,学习速率\eta并没有发生变化。Adagrad是一种自适应学习速率的梯度优化算法。对于更新频繁的参数,学习速率会较小,对于更新不频繁的参数,学习速率会较大,挺适合处理适合处理稀疏特征数据。

\theta_{t+1} = \theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}}\odot g_t

G_t是个对角矩阵,其中第i行的对角元素e_{ii}为过去到当前第i个参数\theta_i的梯度的平方和,\epsilon为平滑参数,避免分母为0,通常取1e-8。开根号只是为了优化下算法性能。

从公式可以看出,G_t的对角元素的值是不断累加的,学习速率衰减很快。为了避免学习速率衰减过快的问题,提出Adadelta算法

d.Adadelta

学习率衰减的分母采用梯度平方的移动平均。

得到

E[g^2]_t = \gamma E[g_{t-1}^2]+(1-\gamma)g_t^2

\theta_{t+1} = \theta_{t}-\frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}\odot g_t

上式有个问题在于\eta\theta的单位不匹配,故采用参数更新的平方的移动平均来替代学习率。

得到

E[\triangle \theta^2 ]_t = \gamma E[\triangle \theta_{t-1}^2]+(1-\gamma)\triangle \theta_t^2

\theta_{t+1} = \theta_{t}-\frac{\sqrt{E[\triangle \theta^2 ]_{t-1}}}{\sqrt{E[g^2]_t+\epsilon}}\odot g_t(当前\triangle \theta_t未知)

e.RMSprop

RMSprop其实就是Adadelta的中间形式,即

\theta_{t+1} = \theta_{t}-\frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}\odot g_t

f.Adam

Adam算法式结合了RMSprop和Momentum,即

m_t = \beta_1m_{t-1}+(1-\beta_1)g_t

v_t = \beta_2v_{t-1}+(1-\beta_2)g_t^2

在进行偏差修正。(可以了解下指数加权平均的偏差修正(Bias correction in exponentially weighted averages)),得到:

\overset{\wedge}{m_t} = \frac{m_t}{1-\beta_1^t}

\overset{\wedge}{v_t} = \frac{v_t}{1-\beta_2^t}

最终得到参数的更新公式为:

\theta_{t+1} = \theta_t-\frac{\eta}{\sqrt{\overset{\wedge}{v_t}}+\epsilon}\odot\overset{\wedge}{m_t}

g.AdaMax

v_t中的g_t^2就相当于对g_tL^2范数,将其泛化到L^p范数。虽然当p值较大时,数值会变得不稳定。但当p—>\infty时,得到:

u_t = \beta_2^{\infty}v_{t-1}+(1-\beta_2)|g_t|^{\infty}

=max(\beta_2v_{t-1},|g_t|)

u_t替代Adam中的\sqrt{\overset{\wedge}{v_t}}+\epsilon得到

\theta_{t+1} = \theta_t-\frac{\eta}{u_t}\odot\overset{\wedge}{m_t}

h.Nadam

借鉴Adam和NAG算法

先看下NAG算法,在提前计算下一个梯度,即\nabla J(\theta-\gamma m_{t-1})

m_t = \gamma m_{t-1}+\eta \nabla_{\theta}J(\theta-\gamma m_{t-1})
\theta = \theta - m_t

Nadam中把这种“先见之明”的思想用到了对参数\theta的更新上,可以看下这个过程:

m_t = \gamma m_{t-1}+\eta \nabla_{\theta}J(\theta)
\theta = \theta - (\gamma m_t+\eta g_t) , g_t=\nabla_{\theta}J(\theta)

先记下这个“先见之明”,之后会用到

回顾Adam的公式

\theta_{t+1} = \theta_t-\frac{\eta}{\sqrt{\overset{\wedge}{v_t}}+\epsilon}\overset{\wedge}{m_t},拆分\overset{\wedge}{m_t}得到,

\theta_{t+1} = \theta_t-\frac{\eta}{\sqrt{\overset{\wedge}{v_t}}+\epsilon}\frac{ \beta_1m_{t-1}+(1-\beta_1)g_t}{1-\beta_1^t}

=\theta_t-\frac{\eta}{\sqrt{\overset{\wedge}{v_t}}+\epsilon}(\overset{\wedge}{m}_{t-1}+\frac{ (1-\beta_1)g_t}{1-\beta_1^t})

应用下“先见之明”,Nadam对参数的更新为
\theta_{t+1}= \theta_t-\frac{\eta}{\sqrt{\overset{\wedge}{v_t}}+\epsilon}(\overset{\wedge}{m}_{t}+\frac{ (1-\beta_1)g_t}{1-\beta_1^t})

来一张现成的图对比下上文提到的几个梯度:


来源:http://cs231n.github.io/neural-networks-3/,原地址是动图

从左图中可以看到,SGD很慢,但会往正确的方向前进,Momentum和NAG速度较快,但有很大的偏离,NAG由于提前预估下一梯度的位置,因此对偏离的响应会快一点。而 Adagrad、Adadelta与RMSprop由于具有自适应学习率的能力,能够快速在正确的方向上得到收敛。
从右图可以看出,SGD基本就在鞍点附近震荡,很难脱离鞍点。而Momentum和NAG本质没有自适应学习率,一开始仍然在鞍点附近震荡,但由于速度会比SGD快,荡久了然后脱离了鞍点。其他三种Adagrad、Adadelta与RMSprop很快脱离了鞍点。

上一篇 下一篇

猜你喜欢

热点阅读