打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Caffe中的SGD的变种优化算法(1)
Caffe中还有一个很重要的部分,那就是优化算法。在专栏的一开始,我们就从优化入手,聊了两个优化算法——随机梯度下降和动量(感谢众多知友指出我之前翻译的错误……)。下面我们沿着前面的步伐,继续前进。
写在前面
说实话设计优化算法和解释优化算法的合理性实际上是一个不太容易的事情。这里我们主要关注算法的实际效果,因此我们对于算法的理论推导就暂时放在一边了。而关于理论,我们只简单讲两句,不做过多的深入,重点是看算法在我们设计的场景下的表现。
非凸函数
之前在我们的算法演示中,我们展示的函数都是凸函数。凸函数有哪些好处,谁来讲一讲?
图片源自网络金坷垃(侵删)
它通常有唯一的极值点。
Hessian矩阵正定。
而下面我们将展示一个函数,这个函数可没有这么多好的性质了:
在等高线图上,它的样子是这样的:
这里的配色采用绘图中的经典彩虹色,其中颜色越靠近蓝色表示函数值越大,颜色越靠近红色表示函数值越小。这和我们的直觉是相符的,一三象限的数字大,二四象限的数字小。
我们的第一个尝试就是从一个比较正常的位置出发——(5,5)点,看看各种算法的效果
在这个新的环境下,我们的老算法——梯度下降,动量,Nesterov算法会不会焕发第二春呢?
有请老队员上场
首先是梯度下降法,由于前面我们已经贴过代码了,这里我们就不再贴代码了,直接上结果:
res, x_arr = gd([5,5], 0.0008, g)
contour(X,Y,Z, x_arr)
为了保证算法经过50轮迭代不会超出我们限定的范围,我们调整了它的learning rate。可以看出算法在迭代过程中先是冲向了局部最优点,也就是我们常说的鞍点,然后发现不对,调转头冲向了真正的优化点,祝它一路走好……
然后是动量算法:
res, x_arr = momentum([5, 5], 3e-4, g)
contour(X,Y,Z, x_arr)
一切顺利!不同的演员同样的剧本,演出来的效果还是不错的。
好了,到这里我们的老队员登场完毕,下面看看新队员了。
Adagrad
Adagrad是一种自适应的梯度下降方法,它希望根据梯度的更新量调节梯度实际的影响值。如果一个变量的梯度更新量比较大,那么再后面的更新过程中我们会适当减少它的更新量,如果更新量比较小,那么我们可以适当地增加它的更新量。
它的参数更新公式如下所示:
它的核心代码如下所示:
def adagrad(x_start, step, g, delta=1e-8):
x = np.array(x_start, dtype='float64')
sum_grad = np.zeros_like(x)
for i in range(50):
grad = g(x)
sum_grad += grad * grad
x -= step * grad / (np.sqrt(sum_grad) + delta)
if abs(sum(grad)) < 1e-6:
break;
return x
我们直接来看看它的表现:
res, x_arr = adagrad([5, 5], 1.3, g)
contour(X,Y,Z, x_arr)
看上去和前面的算法没什么差别嘛……
Rmsprop
前面的Adagrad有一个很大的问题,那就是随着优化的进行,更新公式的分母项会变得越来越大。所以理论上更新量会越来越小,下面的算法Rmsprop就试图解决这个问题。在它的算法中,分母的梯度平方和不再随优化而递增,而是做加权平均:
它的代码如下所示:
def rmsprop(x_start, step, g, rms_decay = 0.9, delta=1e-8):
x = np.array(x_start, dtype='float64')
sum_grad = np.zeros_like(x)
passing_dot = [x.copy()]
for i in range(50):
grad = g(x)
sum_grad = rms_decay * sum_grad + (1 - rms_decay) * grad * grad
x -= step * grad / (np.sqrt(sum_grad) + delta)
passing_dot.append(x.copy())
if abs(sum(grad)) < 1e-6:
break;
return x, passing_dot
我们同样来看看它的表现:
res, x_arr = rmsprop([5, 5], 0.3, g)
contour(X,Y,Z, x_arr)
看上去和前面的表现还是差不多的。
AdaDelta
Rmsprop已经很好地解决了一部分的问题,但是在AdaDelta的眼中似乎还不够。在介绍它的论文中,作者详细阐述了Adagrad算法中得到的参数更新量的“单位”已经不太对了,于是给出了一堆公式用以证明我们需要增加一些计算来使得计算单位恢复正常,于是就有了下面的公式:
具体的代码如下:
def adadelta(x_start, step, g, momentum = 0.9, delta=1e-1):
x = np.array(x_start, dtype='float64')
sum_grad = np.zeros_like(x)
sum_diff = np.zeros_like(x)
passing_dot = [x.copy()]
for i in range(50):
grad = g(x)
sum_grad = momentum * sum_grad + (1 - momentum) * grad * grad
diff = np.sqrt((sum_diff + delta) / (sum_grad + delta)) * grad
x -= step * diff
sum_diff = momentum * sum_diff + (1 - momentum) * (diff * diff)
passing_dot.append(x.copy())
if abs(sum(grad)) < 1e-6:
break;
return x, passing_dot
它的表现如下:
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
支持向量机(SVM)的约束和无约束优化、理论和实现
机器学习之线性回归:算法兑现为python代码
DL之DNN优化技术:DNN优化器的参数优化—更新参数的四种最优化方法(SGD/Momentum/AdaGrad/Adam)的案例理解、图表可视化比较
一文看懂各种神经网络优化算法:从梯度下降到Adam方法
零基础入门深度学习(6)
降维讲解:使用python实现简单的神经网络(BP算法)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服