cs231n学习之参数更新(6)

前言

本文旨在学习和记录,如需转载,请附出处https://www.jianshu.com/p/7b00149dc797

参数更新

神经网络学习的目标是找到一组使损失函数尽可能小的参数,这个过程一般称作最优化问题。
一般计算参数的梯度来更新参数,沿着梯度的方向进行参数更新,然后重复多次,直到收敛,这个最基础的参数更新方法叫做随机梯度下降(stochastic gradient descent, SGD)

  • 基于梯度的优化方法
    目标函数:最小化或最大化的函数,通常也称损失函数、误差函数。一般格式为x^{*}=argminf(x);
    梯度下降:对误差函数求导,往其导数的反方向移动一小步来减小误差函数;
    局部极小点:临界点小于周围所有的临近点,不可能通过无穷小的步长来减小f(x);
    局部极大点:与局部极小点相反;
    鞍点:临界点既不是最小也不是最大;
    在深度学习中,优化的函数可能不是非凸的,很可能存在许多全局极小点或者鞍点时,优化算法可能无法找到全局最小点;但是即使找到的不是全局最小点,他找到的局部极小点对应于误差函数显著低的值,通常代表网络收敛了。
  • 导数的导数
    一阶导数随输入的变化,也叫二阶导数,可以衡量曲率
    . 如果二阶导数为0,即没有曲率,就是平坦的线,用梯度就可以预测值,如果梯度为1,步长为\epsilon,则此时将下降\epsilon;
    . 如果二阶导数为正数,函数曲线向下凹陷,实际下降比\epsilon要少,比预期要下降慢;
    . 如果二阶导数为负数,函数曲线向上凹陷,实际下降比\epsilon要多,比预期要下降快;
  • Hessian矩阵:一个多元函数的二阶导数构成的方阵
    Hessian矩阵是实对称的,可以将其分解为一组实特征值和一组特征向量的正交基。特定方向d上的二阶导数可以写成d^THd,当d是H的一个特征向量时,这个方向的二阶导数就是对应的特征值;对于其他方向的二阶导数可以写成所以特征值的加权平均,且与d夹角越小的特征向量的权重越来越大。最大特征值确定为最大二阶导数。

f(x)在当前点x_{0}的近似二阶泰勒级数:f(x)\approx f(x_{0})+(x-x_{0})g+1/2(x-x_{0})^{2}H(x-x_{0}),其中g为梯度,H是x_{0}的Hessian值。
如果使用学习率\epsilon,则新的点为x_{0}- g\epsilon,带入二阶泰勒级数的近似,可以得到:
f(x_{0}-g\epsilon)\approx f(x_{0})-g^{T}g\epsilon +1/2\epsilon^{2}g^{T}Hg
上式三项分别为:函数的原始值、函数梯度导致的预期更新和函数曲率带来的校正。当最后一项较大的时候,梯度下降有可能是上升的。当第三项为0或者负数时,近似的泰勒展开表明梯度下降将一直下降。在实际情况上,泰勒级数不会在\epsilon大的时候也保持准确。所以当g^{T}Hg为正时,通过计算,使近似的泰勒级数下降的最多最优步长为:
\epsilon^{*}=\frac{g^{T}g}{g^{T}Hg}
最坏情况下,g与H最大特征值对应的特征向量对齐,最优步长为\frac{1}{最大特征值}
二阶导数的另一个作用:
二阶导数测试:确定一个临界点是否为局部极大值、局部极小值或者鞍点。
. 临界点导数都为0,如果其二阶导数大于0意味着导数随着右移动越来越大,则为局部极小值;
. 临界点导数都为0,如果其二阶导数小于0意味着导数随着右移动越来越小,则为局部极大值;
. 临界点的二阶导数为0,无法确定,鞍点或者平坦区域。
扩展到多维情况下,单个点上每个方向的二阶导数是不同的,Hessian矩阵的条件数会影响梯度下降,一个方向上导数增加的很快,另一方向却很慢,梯度下降无法判断这种变化,病态的条件会难以选择合适的步
长。步长不能太大,以免冲过了最小而具有较强正曲率方向上升;而且这步长太小,在其他较小曲率上进展会不明显。

image.png

一、SGD

标准的SGD更新策略:
X = X-lr*dx
SGD的缺点

  1. 优化效率低
    如果损失在一个方向上变换的较快而在另一方向上变换的较慢,它的梯度非常缓慢在慢的那个方向上,而在快的方向上抖动剧烈。这是因为梯度的方向并没有指定最小值的方向,梯度不知道网那个方向去下降,是病态的变换;
    cs231课件截图.png
  2. 难以跳出局部最小值或鞍点
    因为更新策略只考虑了梯度,在局部最小值和鞍点的梯度都为0,此时梯度下降将停滞不前;
  3. mini-batch容易引入噪声
    对m个训练样本的随机采样,其梯度并不会在极小点消失。而且随机采样的点并不能代表全局数据集。

二、带动量的SGD

momentum动量

v=\alpha v-lr*g
\theta = \theta+v
之前一般的SGD优化只考虑了梯度,步长只跟梯度和学习率有关;现在,步长需要考虑梯度序列的大小和排序,当很多梯度指向相同的方向的时候,步长最大,速度一直在-g方向一直加速,直到最大速度,步长大小为:
\frac{lr*||g||}{1-\alpha}

image.png

对一个方向梯度较大和一个方向梯度较小的情况下,采用普通的SGD会很震荡,采用带momentum的SGD会缓和这种情况,因为在梯度较小的那个方向一些在累积梯度,而另外方向虽然梯度很大,但是一直震荡,累加起来就变小了,所以会更快的向最小点靠近。
image.png

Nesterov动量

v_{t+1} = \alpha*v_{t}-lr\bigtriangledown f(x_{t}+\alpha v_{t})
x_{t+1}=x_{t}+v_{t+1}

image.png

\hat x_{t}=x_{t}+\alpha v_{t},则有
v_{t+1}=\alpha*v_{t}-lr\bigtriangledown f(\hat x_{t})
\hat x_{t+1}=x_{t+1}+\alpha v_{t+1}=x_t+v_{t+1}+\alpha v_{t+1}
\hat x_{t+1}=x_t+v_{t+1}+\alpha v_{t+1}+\alpha v_{t}-\alpha v_{t}=\hat x_{t}+v_{t+1}+\alpha (v_{t+1}-v_{t})
Nesterov动量和momentum动量之间的区别就在于计算梯度上。Nesterov动量中,梯度计算在施加当前速度之后,相当于momentum动量上添加了校正因子。利用速度更新把loss带到一定地方再计算梯度,然后混合速度得到实际的更新方向。

三、AdaGrad

AdaGrad算法为每个参数自适应的调整学习率.
h = h+grad*grad
w=w-lr\frac{1}{\sqrt h}grad
AdaGrad保存了以前所有梯度的平方和,在更新参数时,除以了所有梯度平方和的根号,调整学习的尺度。对于变化较大的参数的学习率将变小,变化小的参数将会得到加速。
但是,如果一直学习下去,其梯度将为为0

四、RMSProp

RMSProp是改进的AdaGrad优化算法,它在计算梯度平方和时采用了加权,指数衰减平方来计算,逐步遗忘过去的梯度。
h =\alpha h+(1-\alpha )grad*grad
w=w-lr\frac{1}{\sqrt h}grad
另外,使用Nesterov动量的RMSProp可以描述为:
grad = \bigtriangledown f(w_{t}+\alpha v_{t})
h =\alpha h+(1-\alpha )grad*grad
v_{t+1} = \alpha*v_{t}-\frac {lr}{\sqrt {h}}*grad)
w_{t+1}=w_{t}+v_{t+1}

def rmsprop(w, dw, config=None):
    """
    Uses the RMSProp update rule, which uses a moving average of squared
    gradient values to set adaptive per-parameter learning rates.

    config format:
    - learning_rate: Scalar learning rate.
    - decay_rate: Scalar between 0 and 1 giving the decay rate for the squared
      gradient cache.
    - epsilon: Small scalar used for smoothing to avoid dividing by zero.
    - cache: Moving average of second moments of gradients.
    """
    if config is None: config = {}
    config.setdefault('learning_rate', 1e-2)
    config.setdefault('decay_rate', 0.99)
    config.setdefault('epsilon', 1e-8)
    config.setdefault('cache', np.zeros_like(w))

    next_w = None
    config['cache'] = config['decay_rate']*config['cache']+(1-config['decay_rate'])*dw*dw
    next_w = w-config['learning_rate']*dw/(np.sqrt(config['cache'])+1e-7)

    return next_w, config

五、Adam

Adam算法是AdaGrad/RMSProp和动量方法的结合
t = t+1
s=\beta_{1} s+(1-\beta_{1})grad
r =\beta_{2} s+(1-\beta_{2})grad *grad
\hat s = \frac{s}{1-\beta_{1}^t}修正
\hat r = \frac{r}{1-\beta_{2}^t}
w=w-lr*\frac{\hat s}{\sqrt{\hat r}}+eps
以下代码未写修正。

def adam(w, dw, config=None):
    """
    Uses the Adam update rule, which incorporates moving averages of both the
    gradient and its square and a bias correction term.

    config format:
    - learning_rate: Scalar learning rate.
    - beta1: Decay rate for moving average of first moment of gradient.
    - beta2: Decay rate for moving average of second moment of gradient.
    - epsilon: Small scalar used for smoothing to avoid dividing by zero.
    - m: Moving average of gradient.
    - v: Moving average of squared gradient.
    - t: Iteration number.
    """
    if config is None: config = {}
    config.setdefault('learning_rate', 1e-3)
    config.setdefault('beta1', 0.9)
    config.setdefault('beta2', 0.999)
    config.setdefault('epsilon', 1e-8)
    config.setdefault('m', np.zeros_like(w))
    config.setdefault('v', np.zeros_like(w))
    config.setdefault('t', 0)

    next_w = None
    config['m'] = config['m']*config['beta1']+(1-config['beta1'])*dw
    config['v'] = config['v']*config['beta2']+(1-config['beta2'])*dw*dw
    next_w = w - config['learning_rate']*config['m']/(np.sqrt(config['v']+config['epsilon']))
   
    return next_w, config

实验结果


loss.png

train accuracy.png

valid accuracy.png

总结

现在常用的优化算法有SGD,带动量的SGD(momentum/Nesterov),AdaGrad,RMSProp,Adam。其中,后三种是自适应学习率算法,这几种都是比较常用的,目前并没有一个统一的标准说哪一个算法更好,一般使用时都取决于是否对该方法比较熟悉或者以便调节超参数。

参考

  1. cs231课件
  2. 花书
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容