本文主要是对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+Vnow
这其实就是把上面的更新代码翻译成数学语言表达的样子,下标是特别有用的东西,这个方法灵感来自于SVM中SMO方法的推导,其实仔细想想,迭代这个概念我们在数学中还真的没有明确的遇到过,我们从来没有在数学中用一个变量表示不同时刻的值,或者说很少用一个明确的表示方法来将同一个自变量的不同时刻区别开来如果他们需要出现在同一个式子里。
在这三个式子里, T P l a s t TP_{last} TPlast, V l a s t V_{last} Vlast是已知量,需要推导出 L H n o w LH_{now} LHnow, V n o w V_{now} Vnow , T P n o w TP_{now} TPnow
下面我们考虑这样一个问题
已知 L H n o w LH_{now} LHnow(将来会用x来代替), V l a s t V_{last} Vlast,需要推导出 V n o w V_{now} Vnow, L H n e x t LH_{next} LHnext。
要推导 L H LH LH, T P TP TP是不可缺少中间变量的,但是不能出现在式子中,需要变通的方式代替它。
根据上面的式子我们知道
L H n e x t = T P n o w + μ V n o w LH_{next} = TP_{now} + {\mu}V_{now} LHnext=TPnow+μVnow
而 T P n o w = T P l a s t + V n o w TP_{now} = TP_{last} + V_{now} TPnow=TPlast+Vnow
其中 T P l a s t = L H n o w − μ V l a s t TP_{last} = LH_{now} - {\mu}V_{last} TPlast=LHnow−μVlast(由 上面的 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 推导而来)
带入得到: L H n e x t = L H n o w − μ V l a s t + V n o w + μ V n o w LH_{next} = LH_{now} - {\mu}V_{last} +V_{now} + {\mu}V_{now} LHnext=LHnow−μVlast+Vnow+μVnow
其中 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)
于是更新的主要式子就是:
1 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)
2 L H n e x t = L H n o w − μ V l a s t + V n o w + μ V n o w LH_{next} = LH_{now} - {\mu}V_{last} +V_{now} + {\mu}V_{now} LHnext=LHnow−μVlast+Vnow+μVnow
你会发现第二个式子既需要 V n o w V_{now} Vnow也需要 V l a s t V_{last} Vlast
所以需要一个单独的变量「v_prev」来保存 V l a s t V_{last} Vlast ,之后再把这两个式子中的 L H LH LH换成「x」,V换成「v」,就得到了更新代码:
v_prev = v # 需要一个单独的变量保存上一次的速度
v = mu * v - learning_rate * dx # 对应上面的1式
x += -mu * v_prev + (1 + mu) * v # 对应上面的2式
本小结用到推论前提