阅读文献——各种 gradient descent 方法

文献链接:An overview of gradient descent optimization algorithms

我一直对于 gradient descent 的机制没有搞透,就很好奇这梯度到底怎么搞的。(我觉得关键是因为我高数学的太水,学梯度的时候没有用非数学的想法去理解它)

先又重复一遍老内容:

Batch Gradient Descent

也就是最朴素的GD,就真的很朴素:
θ   =   θ   − η ∇ θ J ( θ ) \theta~=~\theta~-\eta\nabla_{\theta}J(\theta) θ = θ ηθJ(θ)

for i in range(nb_epochs):
  params_grad = evaluate_gradient(loss_function, data, params)
  params = params - learning_rate * params_grad

Stochastic Gradient Descent

这中方法每一次只用一个例子来更新,不像上面的把所有的training data 都计算一遍。所以就快很多,而且可以on-line学习。

θ   =   θ   − η ∇ θ J ( θ ;   x i ;   y i ) \theta~=~\theta~-\eta\nabla_{\theta}J(\theta;~x^i;~y^i) θ = θ ηθJ(θ; xi; yi)

但还是,虽然每次只计算一个example,但是还是data里面的全部过一遍。

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

mini-batch Gradient Descent

这里就是我们非常常用的方法了,就是随机选一个batch,然后每次计算一个batch_size 的examples:
θ   =   θ   − η ∇ θ J ( θ ;   x ( i : i + n ) ;   y ( i : i + n ) ) \theta~=~\theta~-\eta\nabla_{\theta}J(\theta;~x^{(i:i+n)};~y^{(i:i+n)}) θ = θ ηθJ(θ; x(i:i+n); y(i:i+n))

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的方法就是mini-batch 的方法的一种batch size == 1 的特殊情况。

challenges

存在的问题就是:

  • 我们需要选择一个合适的learning rate(这里用了 η \eta η来表示)
  • learning rate最好能随着访问的次数而有所不同——经常访问的 η \eta η小,不经常访问的 η \eta η大。
  • 我们需要避免被困在局部最优里,最坏的情况是被困在鞍点,鞍点的每个方向的gradient 都是0。

解决措施

我只看了四种常用的方法——Momentum, NAG, Adagrad, Adam

Momentum

这种比较简单,就是加一个momentum,给他一个下降的动力,使SGD加速。

v t   =   γ v t − 1   +   η ∇ θ J ( θ ) v_t~=~\gamma v_{t-1}~+~\eta\nabla_{\theta}J(\theta) vt = γvt1 + ηθJ(θ)
θ   =   θ   −   v t \theta ~=~\theta~-~v_t θ = θ  vt

γ v t − 1 \gamma v_{t-1} γvt1 就是加上的动量。 γ \gamma γ 一般设置为0.9。 v t v_t vt θ \theta θ的更新量, v t − 1 v_{t-1} vt1 是上一时刻的更新量,也就是说, t t t 时刻的更新量采用了一部分之前的更新量(也就是根据过去的经验)。

Nesterov accelerated gradient(NAG)

我们想要我们的参数更加超前一点,变得更加“先知”。举个形象的例子就是,我们给沿坡下降的小球加上动量之后,我们还希望它能够预测前面的情况,能够在到达最低点的时候不要再冲到另一边的坡上了。

所以,我们用来计算的梯度的参数 θ \theta θ,我们令他等于 ( θ − γ v t − 1 ) (\theta-\gamma v_{t-1}) (θγvt1),用上一步得到的v来得到一个下一步 θ 的估计值。

v t   =   γ v t − 1   +   η ∇ θ J ( θ − γ v t − 1 ) v_t~=~\gamma v_{t-1}~+~\eta\nabla_{\theta}J(\theta-\gamma v_{t-1}) vt = γvt1 + ηθJ(θγvt1)
θ   =   θ   −   v t \theta ~=~\theta~-~v_t θ = θ  vt
在这里插入图片描述
对比上面两种方法,如上图,非常形象。Momentum就是,先按照计算出的梯度方向前进一小部(第一个小的蓝箭头),然后根据过去积累的经验 vt-1方向前进一大步(大的蓝箭头)。

而NAG,是先按照过去积累的经验走一大步(棕色箭头),然后再根据现在计算出的方向加以校正(红色箭头)。就得到最终下面的绿色箭头。

Adagrad

我们还想每个参数单独更新,每个 time step 都单独更新每个参数。

g t , i = ∇ θ J ( θ t , i ) g_{t,i} = \nabla_{\theta}J(\theta_{t,i}) gt,i=θJ(θt,i)
θ t + 1 , i   =   θ t , i   −   η ⋅ g t , i \theta_{t+1,i}~=~\theta_{t,i}~-~\eta\cdot g_{t,i} θt+1,i = θt,i  ηgt,i

然后如果我们想自动改变learning rate,可以这样:

g t , i = ∇ θ J ( θ t , i ) g_{t,i} = \nabla_{\theta}J(\theta_{t,i}) gt,i=θJ(θt,i)
θ t + 1 , i   =   θ t , i   −   η G t , i i + ϵ ⋅ g t , i \theta_{t+1,i}~=~\theta_{t,i}~-~\frac{\eta}{\sqrt{G_{t,ii}+\epsilon}} \cdot g_{t,i} θt+1,i = θt,i  Gt,ii+ϵ ηgt,i

其中 G t G_{t} Gt 是一个矩阵,第i,i 个元素是关于 θi的所有得到的gradient 的平方的和。(从开始到时间t),所以 G t , i i G_{t,ii} Gt,ii就是对于θi的所有梯度的平方的和。

还有一种Adam

唉写8动了……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值