作者丨小小鱼@知乎

来源丨https://zhuanlan.zhihu.com/p/41799394

本文旨在优化一维函数,实际上模型参数有数百万维以上,差距很大,因此本文最好作为辅助法的理解,而非对算法优劣的判断依据。

在深度学习中,有很多种优化算法,这些算法需要在极高维度(通常参数有数百万个以上)也即数百万维的空间进行梯度下降,从最开始的初始点开始,寻找最优化的参数,通常这一过程可能会遇到多种的情况,诸如:

1、提前遇到局部最小值从而卡住,再也找不到全局最小值了。

2、遇到极为平坦的地方:“平原”,在这里梯度极小,经过多次迭代也无法离开。同理,鞍点也是一样的,在鞍点处,各方向的梯度极小,尽管沿着某一个方向稍微走一下就能离开。

3、“悬崖”,某个方向上参数的梯度可能突然变得奇大无比,在这个地方,梯度可能会造成难以预估的后果,可能让已经收敛的参数突然跑到极远地方去。

为了可视化&更好的理解这些优化算法,我首先拼出了一个很变态的一维函数:

其导数具有很简单的形式:

具体长得像:

具有悬崖和大量的局部最小值,足以模拟较为复杂的优化情况了。

算法1:纯粹的梯度下降法

该算法很简单,表述如下:

          首先给出学习率lr,初始x        while True:x = x - lr*df/dx

根据学习率的不同,可以看到不同的效果。学习率过小,卡在局部极小值,学习率过大,压根不收敛。

梯度下降法

算法2:梯度下降法+动量

算法在纯粹的梯度下降法之上,外加了梯度,从而记录下了历史的梯度情况,从而减轻了卡在局部最小值的危险,在梯度=0的地方仍然会有一定的v剩余,从而在最小值附近摇摆。

       首先给出学习率lr,动量参数m初始速度v=0,初始xwhile True:v = m * v - lr * df/dxx += v

下面可以看图:

梯度下降+动量, lr=0.05

梯度下降+动量, lr=0.01

梯度下降+动量, lr=0.002

从中我们可以看出:

1、lr越小越稳定,太大了很难收敛到最小值上,但是太小的话收敛就太慢了。

2、动量参数不能太小,0.9以上表现比较好,但是又不能太大,太大了无法停留在最小值处。

算法3:AdaGrad算法

AdaGrad算法的思想是累计历史上出现过的梯度(平方),用积累的梯度平方的总和的平方根,去逐元素地缩小现在的梯度。某种意义上是在自行缩小学习率,学习率的缩小与过去出现过的梯度有关。

缺点是:刚开始参数的梯度一般很大,但是算法在一开始就强力地缩小了梯度的大小,也称学习率的过早过量减少。

算法描述:

给出学习率lr,delta=1e-7
累计梯度r=0,初始x
while True:g = df/dxr  = r + g*gx = x - lr / (delta+ sqrt(r)) * g

效果并不是很好......

算法4:RMSProp

AdaGrad算法在前期可能会有很大的梯度,自始至终都保留了下来,这会使得后期的学习率过小。RMSProp在这个基础之上,加入了平方梯度的衰减项,只能记录最近一段时间的梯度,在找到碗状区域时能够快速收敛。

算法描述:

给出学习率lr,delta=1e-6,衰减速率p
累计梯度r=0,初始x
while True:g = df/dxr  = p*r + (1-p)*g*gx = x - lr / (delta+ sqrt(r)) * g

RMSProp,p=0.99

RMSProp,p=0.9RMSProp,p=0.8

衰减速率情况复杂,建议自行调参.......

算法5:Adam算法

Adam算法和之前类似,也是自适应减少学习率的算法,不同的是它更新了一阶矩和二阶矩,用一阶矩有点像有动量的梯度下降,而用二阶矩来降低学习率。

此外还使用了类似于s = s / (1-p1^t)这样的公式,这样的公式在t较为小的时候会成倍增加s,从而让梯度更大,参数跑的更快,迅速接近期望点。而后续t比较大的时候,s = s / (1-p1^t)基本等效于s=s,没什么用。

算法如下:

给出学习率lr,delta=1e-8,衰减速率p1=0.9,p2=0.999
累计梯度r=0,初始x ,一阶矩s=0,二阶矩r=0
时间t = 0
while True:t += 1g = df/dx s = p1*s + (1-p1) *gr = p2*r +(1-p2)*g*gs = s / (1-p1^t)r = r / (1-p2^t)x = x - lr / (delta+ sqrt(r)) * s

Adam算法,鬼一样的表现

是的,你没有看错,这玩意压根不收敛......表现极差。

在算法中仔细研究后才发现,是在t很小的前几步的时候,p2=0.999太大了,导致r = r / (1-p2^t) 中,1-p2^t接近0,r迅速爆炸,百步之内到了inf。后来修改p2=0.9后效果就好得多了。

Adam算法,神级表现

最后还是Adam效果最好了 :),尽管学习率还是需要相当的调参。

算法6:牛顿法

牛顿法是二阶近似方法的一种,其原理类似于将某函数展开到二次方(二次型)项:

如果幸运的话,这个展开式是一个开口向上的曲面,一步就走到这个曲面的最低点:

初始x
while True:g = df(x)  # 一阶导数gg = ddf(x)   # 二阶导数x = x - g/gg   # 走到曲面的最低点

可怜的牛顿法,静态图

图片如上,看了真可怜........其实牛顿法要求的是H矩阵正定(一维情况下是二阶导数大于零),在多维中,这样的情况难以满足,大量出现的极小值,悬崖,鞍点都会造成影响,导致无法顺利进行下去,为了更好地进行牛顿法,我们需要正则化它。

算法7:牛顿法+正则化

牛顿法加上正则化可以避免卡在极小值处,其方法也很简单:更新公式改成如下即可。

一维的算法如下:

初始x  ,正则化强度alpha
while True:g = df(x)  # 一阶导数         gg = ddf(x)   # 二阶导数         x = x - g/(gg+alpha)   # 走到曲面的最低点

效果图:

牛顿法+正则化

看了真可怜.........二次方法真心在非凸情况很糟糕。此外算法涉及H矩阵的逆,这需要O(n^3)的计算量,非深度学习可用。

参考文献

[1]Ian Goodfellow,深度学习Deep Learning,人民邮电出版社,170-190

代码

#coding:utf-8
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as pltdef f(x):return (0.15*x)**2 + np.cos(x) + np.sin(3*x)/3 + np.cos(5*x)/5 + np.sin(7*x)/7def df(x):return (9/200)*x - np.sin(x) -np.sin(5*x) + np.cos(3*x) + np.cos(7*x)points_x = np.linspace(-20, 20, 1000)
points_y = f(points_x)# 纯粹的梯度下降法,GD
for i in range(10):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始lr = pow(2,-i)*16x = -20.0GD_x, GD_y = [], []for it in range(1000):GD_x.append(x), GD_y.append(f(x))dx = df(x)x = x - lr * dxplt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(GD_x, GD_y, c="r", linestyle="-")plt.title("Gradient descent,lr=%f"%(lr))plt.savefig("Gradient descent,lr=%f"%(lr) + ".png")plt.clf()# 动量 + 梯度下降法
for i in range(10):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始lr = 0.002m = 1 - pow(0.5,i)x = -20v = 1.0GDM_x, GDM_y = [], []for it in range(1000):GDM_x.append(x), GDM_y.append(f(x))v = m * v - lr * df(x)x = x + vplt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(GDM_x, GDM_y, c="r", linestyle="-")plt.scatter(GDM_x[-1],GDM_y[-1],90,marker = "x",color="g")plt.title("Gradient descent + momentum,lr=%f,m=%f"%(lr,m))plt.savefig("Gradient descent + momentum,lr=%f,m=%f"%(lr,m) + ".png")plt.clf()# AdaGrad
for i in range(15):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始lr = pow(1.5,-i)*32delta = 1e-7x = -20r = 0AdaGrad_x, AdaGrad_y = [], []for it in range(1000):AdaGrad_x.append(x), AdaGrad_y.append(f(x))g = df(x)r = r + g*g # 积累平方梯度x = x - lr /(delta + np.sqrt(r)) * gplt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(AdaGrad_x, AdaGrad_y, c="r", linestyle="-")plt.scatter(AdaGrad_x[-1],AdaGrad_y[-1],90,marker = "x",color="g")plt.title("AdaGrad,lr=%f"%(lr))plt.savefig("AdaGrad,lr=%f"%(lr) + ".png")plt.clf()# RMSProp
for i in range(15):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始lr = pow(1.5,-i)*32delta = 1e-6rou = 0.8x = -20r = 0RMSProp_x, RMSProp_y = [], []for it in range(1000):RMSProp_x.append(x), RMSProp_y.append(f(x))g = df(x)r = rou * r + (1-rou)*g*g # 积累平方梯度x = x - lr /(delta + np.sqrt(r)) * gplt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(RMSProp_x, RMSProp_y, c="r", linestyle="-")plt.scatter(RMSProp_x[-1],RMSProp_y[-1],90,marker = "x",color="g")plt.title("RMSProp,lr=%f,rou=%f"%(lr,rou))plt.savefig("RMSProp,lr=%f,rou=%f"%(lr,rou) + ".png")plt.clf()# Adam
for i in range(48):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始lr = pow(1.2,-i)*2rou1,rou2 = 0.9,0.9  # 原来的算法中rou2=0.999,但是效果很差delta = 1e-8x = -20s,r = 0,0t = 0Adam_x, Adam_y = [], []for it in range(1000):Adam_x.append(x), Adam_y.append(f(x))t += 1g = df(x)s = rou1 * s + (1 - rou1)*gr = rou2 * r + (1 - rou2)*g*g # 积累平方梯度s = s/(1-pow(rou1,t))r = r/(1-pow(rou2,t))x = x - lr /(delta + np.sqrt(r)) * splt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(Adam_x, Adam_y, c="r", linestyle="-")plt.scatter(Adam_x[-1],Adam_y[-1],90,marker = "x",color="g")plt.title("Adam,lr=%f"%(lr))plt.savefig("Adam,lr=%f"%(lr) + ".png")plt.clf()# 牛顿法
for i in range(72):# 绘制原来的函数plt.plot(points_x, points_y, c="b", alpha=0.5, linestyle="-")# 算法开始alpha= pow(1.2,-i)*20x = -20.0Newton_x, Newton_y = [], []for it in range(1000):Newton_x.append(x), Newton_y.append(f(x))g = df(x)gg = ddf(x)x = x - g/(gg+alpha)plt.xlim(-20, 20)plt.ylim(-2, 10)plt.plot(Newton_x, Newton_y, c="r", linestyle="-")plt.scatter(Newton_x[-1],Newton_y[-1],90,marker = "x",color="g")plt.title("Newton,alpha=%f"%(alpha))plt.savefig("Newton,alpha=%f"%(alpha) + ".png")plt.clf()

觉得有用麻烦给个在看啦~  

深度学习中7种最优化算法的可视化与理解相关推荐

  1. 深度学习中常用优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)

    本文转载自:https://www.cnblogs.com/guoyaohua/p/8542554.html 在机器学习.深度学习中使用的优化算法除了常见的梯度下降,还有 Adadelta,Adagr ...

  2. 深度学习中常用的Adam算法

    一.Adam算法 Adam(Adaptive momentum)是一种自适应动量的随机优化方法(A method for stochastic optimization),经常作为深度学习中的优化器算 ...

  3. 深度学习中的Adam优化算法详解

    Adam论文:https://arxiv.org/pdf/1412.6980.pdf (一).什么是Adam算法? Adam(Adaptive momentum)是一种自适应动量的随机优化方法(A m ...

  4. 深度学习中常用的优化算法(SGD, Nesterov,Adagrad,RMSProp,Adam)总结

    深度学习中常用的优化算法(SGD, Nesterov,Adagrad,RMSProp,Adam)总结 1. 引言 在深度学习中我们定义了损失函数以后,会采取各种各样的方法来降低损失函数的数值,从而使模 ...

  5. 机器学习、深度学习中常用的优化算法详解——梯度下降法、牛顿法、共轭梯度法

    一.梯度下降法 1.总述: 在机器学习中,基于基本的梯度下降法发展了三种梯度下降方法,分别为随机梯度下降法,批量梯度下降法以及小批量梯度下降法. (1)批量梯度下降法(Batch Gradient D ...

  6. 深度学习中的Epoch,Batchsize,Iterations深刻理解

    [嵌牛导读]Epoch,Batchsize,Iterations,这三个都是深度学习训练模型时经常遇到的概念.你一定有过这样的时刻,面对这几个词傻傻分不清楚,这三个概念究竟是什么,它们又有什么区别? ...

  7. 深度学习中的软件加速算法

    深度学习算法对于人工智能的推动作用不言而喻,但其对计算力的要求也显而易见.如何使其运行更高效是摆在不少工程师面前的难题,通常他们会在代码中直接采用一个比较成熟的矩阵运算数学库,开源项目OpenBLAS ...

  8. 机器学习(深度学习)中的反向传播算法与梯度下降

    这是自己在CSDN的第一篇博客,目的是为了给自己学习过的知识做一个总结,方便后续温习,避免每次都重复搜索相关文章. 一.反向传播算法 定义:反向传播(Backpropagation,缩写为BP)是&q ...

  9. 深度学习中常用的优化算法

    参考<动手学深度学习> https://zh.d2l.ai/chapter_optimization/index.html 一维梯度下降 我们先以简单的一维梯度下降为例,解释梯度下降算法可 ...

最新文章

  1. python3 内置函数map 返回的迭代器转为列表
  2. ubuntu19 安装git_如何在Ubuntu 20.04上安装Git
  3. C#实现对指定文件夹中文件按修改时间排序
  4. mysql filck_顺序全局id生成方案-flickr(转载)
  5. Spring Boot : Bean标签属性
  6. Android将ScrollView移动到最底部
  7. c语言xyz最小值,有关问题XYZ的10种语言解决方案(一)之C语言篇
  8. matlab中输入x. 与x的区别
  9. linux 查看新增文件夹记录_微信7.0.23测试版,新增查看访客记录,朋友圈内容能折叠?...
  10. iPhone Objective-C EXC_BAD_ACCESS问题
  11. 快讯丨业界首本云网络图书发布
  12. 迅捷pdf在线转换html,迅捷pdf在线转换成word免费版在线版
  13. python制作密码字典_Python实现生成密码字典的方法示例
  14. 全渠道数字化营销平台
  15. Linux防火墙iptables学习笔记
  16. 为啥OpenStack厂商要参加双态运维大会?
  17. matlab读多个excel,读取excel 多个表格文件数据-怎样利用matlab去读取一个excel表中多个sheet的数......
  18. 电脑it族宝典常用电脑的从怎样保护自己的眼睛
  19. TransTrack: Multiple-Object Tracking with Transformer
  20. shapely包的使用

热门文章

  1. 黄家懿:河北高校邀请赛 -- 二手车交易价格预测决赛答辩
  2. 《C#精彩实例教程》小组阅读11 -- C#结构与类
  3. 前后端分离的探索(五)
  4. 如何全面认识联邦学习
  5. 针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言427-438条如下:
  6. 确认了!MySQL 狠甩 Oracle 稳居 Top1!
  7. 人工智能加“医真云”,每年让5700万人告别误诊
  8. 599元的智能视频音箱发布,百度准备补贴几个亿?
  9. AI一分钟 | AI机器人竟混入大学哲学课堂并顺利结业,居然无人察觉!
  10. 用 MySQL 实现分布式锁,你听过吗?