本文主要是对CS231n相应部分做一些详细的阐释
为了解释Nesterov动量更新的原理,我们从速度更新表达式开始说起。
v = mu * v - learning_rate * dx
(为了说明下面的推论还是需要一些前提的,为了不影响整体感,把这些放到本小节的后面)
其实这个式子背后提现了这样一个原理:下一时刻的速度应该由 「当前的速度」以及「质点因受力产生的速度变化」两部分共同构成。
式子的前一部分( mu * v)代表质点当前的速度状态,它是由上一个时刻的速度乘以摩擦系数得到,后一部分(learning_rate * dx)代表了作用在这个质点因重力产生的加速度进而产生了速度的变化,但是dx中的x是上一时刻的位置,dx确切的含义是上一时刻的位置带入到梯度解析式中得到关于这一时刻的重力对质点的速度影响。
这样你就看出毛病了把——利用上一时刻质点的位置信息计算这一时刻的加速度是否合适?是不是觉得有点不妥?总觉得这一时刻的影响效果应该由这一时刻的相关信息计算出来,也就是这一时刻的加速度应该用这一时刻的位置信息来计算比较合适。但是这一时刻的位置信息又取决于当前的速度信息,当前的速度信息中的一部分又需要当前的位置信息,有点死循环了。
解决的方法是引入一个新的概念——“趋势点”。(这是我对lookahead这个词的意译)
利用趋势点来近似的代替“这一时刻的位置”从而计算出当前时刻重力对质点的速度影响(重力加速度),之后在用这个速度和这一时刻的「当前速度」相结合得到下一时刻的速度。
“趋势点”是这样定义的:如果没有重力(也就是没有后一项),质点下一时刻的位置就是x + mu*v,我们可以称这个位置叫做“趋势位置”(lookahead)。这里也可以借助一下极限的思想,如果时间比较短的时候,x + mu * v 所表示的位置是质点最终到达的位置的一个临域。
代码表示成下面:
x_ahead = x + mu * v # 先计算出趋势点
v = mu * v - learning_rate * dx_ahead # 将趋势点带入梯度中作为当前的加速度效果
x += v
原理就是这样,但是在实践中人们希望用新方法中更新表达式的样子和之前方法中表达式样子接近。换句话说我们是要通过一些数学技巧把当前这个式子形式转换一下。
核心技巧就是把上面式子中的x_head用x来进行代替,换句话说并不让x_head显式的出现在更新的式子里,而是变通的用其他的量来代替。这里涉及到好几个变量,而且还涉及到这些变量在不同的迭代时刻,为了掰扯清楚这件事情,我们定义下面的变量:
真实位置: TP(Ture Postion)
趋势位置:LH(lookahead)
速度:V(这没啥可说的)
与时刻相关的下标: last(上一次) now(这一次) next(下一次)
摩擦系数 : μ \mu μ
学习率: α \alpha α
在一开始我们的关系是这样(允许“趋势位置”显式出现)
L H n o w = T P l a s t + μ V l a s t LH_{now} = TP_{last} + {\mu}V_{last} LHnow=TPlast+μVlast
V n o w = μ V l a s t − α d ( L H n o w ) V_{now}={\mu}V_{last} - {\alpha}d(LH_{now}) Vnow=μVlast−αd(LHnow)
T P n o w = T P l a s t + V n o w TP_{now} =TP_{last} + V_{now} TPnow=TPlast