这篇论文比较短,先看了这篇,本来应该先把ADAGRAD看了的。普通的基于梯度下降的方法,普遍依赖于步长,起始点的选择,所以,受ADAGRAD的启发,作者提出了一种ADADELTA的方法。

\[\Delta x_t = -\frac{\mathrm{RMS}[\Delta x]_{t-1}}{\mathrm{RMS}[g]_t}g_t
\]

其中\(g_t=\frac{\partial f(x_t)}{\partial x_t}\),所以下一步迭代就是:

\[x_{t+1} = x_t + \Delta x_t
\]

主要内容

ADAGRAD方法:

\[\Delta x_t = -\frac{\eta}{\sqrt{\sum_{\tau=1}^t g_{\tau}^2}}g_t
\]

也就是,步长与之前所有的梯度有关,显然这个步长是会逐渐减少的。但是这个缺点也很明显,如果起始点的梯度很大,那么就会导致后续步长很小,而一开始的梯度很小,就会导致后续步长很大,产生振荡,有些怪怪的。

而ADADELTA希望只关心一部分的梯度,比如

\[\sqrt{\sum_{\tau=t-k}^tg_{\tau}^2}
\]

但是这么做,每次迭代都必须记录\(k\)个梯度,这显得不怎么效率,于是,作者相处了一个法子:

\[E[g^2]_t = \rho E[g^2]_{t-1} + (1-\rho)g_t^2
\]

可以看到,对于\(g_1\),\(t+1\)步之后其影响为:\(\rho^t(1-\rho) g_1\),对整个迭代造成的影响是一个等比序列:

\[(1-\rho), \rho (1-\rho), \ldots, \rho^t(1-\rho)
\]

最后趋向于:

\[1-\rho^{t+1} \rightarrow1
\]

这么做就俩劝其美啦。

记:

\[\mathrm{RMS}[g]_t = \sqrt{E[g^2]_t + \epsilon}
\]

其中\(\epsilon\)是为了让除法有意义而添加的小量。

所以

\[\Delta x_t = -\frac{\eta}{\mathrm{RMS}[g]_t}g_t
\]

这还不是最终版本,另一个启发决定了\(\eta\)的选择。

我们知道,很多问题是有实际含义的,\(x\)可能是有单位的,比如是米,天等,所以,一个很自然的期望是,\(\Delta x\)的单位和\(x\)是保持一致的。但是:

\[\mathrm{units \: of \:}\Delta x \propto \mathrm{units \: of \:} g \propto \frac{\partial f}{\partial x}\propto \frac{1}{\mathrm{units \: of \:} x}
\]

也就是说\(\Delta x\)的步长单位和梯度单位是一致的,就像是\(l=vt\),\(\Delta t\)的步长单位是\(m/s\),是时间单位的倒数。

而利用二阶导数迭代步长就符合单位一致(如Newton方法):

\[\Delta x \propto H^{-1} g \propto \frac{\frac{\partial f}{\partial x}}{\frac{\partial^2 f}{\partial x^2}} \propto \mathrm{units \: of \:} x
\]

其中\(H\)为Hessian矩阵。

又注意到:

\[\Delta x = \frac{\frac{\partial f}{\partial x}}{\frac{\partial^2 f}{\partial x^2}} \Rightarrow \frac{1}{\frac{\partial^2 f}{\partial x^2}} = \frac{\Delta x}{\frac{\partial f}{\partial x}}
\]

于是,完全体的ADADELTA方法变为如下:

\[\Delta x_t = -\frac{\mathrm{RMS}[\Delta x]_{t-1}}{\mathrm{RMS}[g]_t}g_t
\]

分子式\(t-1\)的原因式\(\Delta x_t\)压根不知道,所木有办法,就将就一下。

算法

完整的算法如下:

需要注意一点的是,在实际实验中,我们设置\(E[\Delta x^2]_0=1\)而不是如算法中所说的0。因为,如果设置为0,那么意味着第一步只进行相当微小的迭代,所以之后也都是微小的迭代。或许作者是将\(\epsilon\)设置为\(1\)?而不是一个小量?

ADADELTA 代码

import numpy as np
import matplotlib.pyplot as plt

这次用比较怪一点的方式来写,首先,创建一个类,用来存放函数\(f\)和梯度\(g\)

class ADADELTA:
def __init__(self, function, gradient, rho=0.7):
assert hasattr(function, "__call__"), "Invalid function"
assert hasattr(gradient, "__call__"), "Invalid gradient"
assert 0 < rho < 1, "Invalid rho"
self.__function = function
self.__gradient = gradient
self.rho = rho
self.acc_gradient = 0 #初始化accumulate gradient
self.acc_updates = 1 #初始化accumulate updates
self.progress = [] @property
def function(self):
return self.__function @property
def gradient(self):
return self.__gradient def reset(self):
self.acc_gradient = 0 #初始化accumulate gradient
self.acc_updates = 1 #初始化accumulate updates
self.progress = []

计算累计梯度

\[E[g^2]_t = \rho E[g^2]_{t-1} + (1-\rho)g_t^2
\]
def accumulate_gradient(self, gt):
self.acc_gradient = self.rho * self.acc_gradient \
+ (1 - self.rho) * gt ** 2
return self.acc_gradient
ADADELTA.accumulate_gradient = accumulate_gradient

更新\(E[\Delta x]_t\)

\[E[\Delta x^2]_t = \rho E[\Delta x^2]_{t-1} + (1-\rho)\Delta x_t^2
\]
def accumulate_updates(self, deltax):
self.acc_updates = self.rho * self.acc_updates \
+ (1 - self.rho) * deltax ** 2
return self.acc_updates
ADADELTA.accumulate_updates = accumulate_updates

计算更新步长:

\[\Delta x_t = -\frac{\mathrm{RMS}[\Delta x]_{t-1}}{\mathrm{RMS}[g]_t}g_t
\]
def step(self, x, smoothingterm=1e-8):
gt = self.gradient(x)
self.accumulate_gradient(gt)
RMS_gt = np.sqrt(self.acc_gradient + smoothingterm)
RMS_up = np.sqrt(self.acc_updates + smoothingterm)
deltax = -RMS_up / RMS_gt * gt
self.accumulate_updates(deltax)
return x + deltax
ADADELTA.step = step

进行t步

def process(self, startx, t, smoothingterm=1e-8):
x = startx
for i in range(t):
self.progress.append(x)
x = self.step(x, smoothingterm)
return self.progress
ADADELTA.process = process

可视化

def plot(self):
x = np.arange(1, len(self.progress) + 1)
y = np.array([
self.function(item) for item in self.progress
])
fig, ax = plt.subplots(constrained_layout=True)
ax.plot(x, y)
ax.set_xlabel("steps")
ax.set_ylabel("value of function")
ax.set_title("value with steps")
plt.show()
ADADELTA.plot = plot
def function(x):
return x[0] ** 2 + 50 * x[1] ** 2 def gradient(x):
return 2 * x[0] + 100 * x[1]
test = ADADELTA(function, gradient, 0.9)
test.reset()
startx = np.array([10, 10])
test.process(startx, 50)
test.plot()

ADADELTA: AN ADAPTIVE LEARNING RATE METHOD的更多相关文章

  1. Deep Learning 32: 自己写的keras的一个callbacks函数,解决keras中不能在每个epoch实时显示学习速率learning rate的问题

    一.问题: keras中不能在每个epoch实时显示学习速率learning rate,从而方便调试,实际上也是为了调试解决这个问题:Deep Learning 31: 不同版本的keras,对同样的 ...

  2. Keras 自适应Learning Rate (LearningRateScheduler)

    When training deep neural networks, it is often useful to reduce learning rate as the training progr ...

  3. Dynamic learning rate in training - 培训中的动态学习率

    I'm using keras 2.1.* and want to change the learning rate during training. I know about the schedul ...

  4. mxnet设置动态学习率(learning rate)

    https://blog.csdn.net/xiaotao_1/article/details/78874336 如果learning rate很大,算法会在局部最优点附近来回跳动,不会收敛: 如果l ...

  5. 学习率(Learning rate)的理解以及如何调整学习率

    1. 什么是学习率(Learning rate)?   学习率(Learning rate)作为监督学习以及深度学习中重要的超参,其决定着目标函数能否收敛到局部最小值以及何时收敛到最小值.合适的学习率 ...

  6. 跟我学算法-吴恩达老师(mini-batchsize,指数加权平均,Momentum 梯度下降法,RMS prop, Adam 优化算法, Learning rate decay)

    1.mini-batch size 表示每次都只筛选一部分作为训练的样本,进行训练,遍历一次样本的次数为(样本数/单次样本数目) 当mini-batch size 的数量通常介于1,m 之间    当 ...

  7. learning rate warmup实现

    def noam_scheme(global_step, num_warmup_steps, num_train_steps, init_lr, warmup=True): ""& ...

  8. pytorch learning rate decay

    关于learning rate decay的问题,pytorch 0.2以上的版本已经提供了torch.optim.lr_scheduler的一些函数来解决这个问题. 我在迭代的时候使用的是下面的方法 ...

  9. machine learning (5)---learning rate

    degugging:make sure gradient descent is working correctly cost function(J(θ)) of Number of iteration ...

随机推荐

  1. Linux系统中安装软件方法总结

    Linux系统中安装软件方法总结 [1]Linux系统中安装软件的几种方式 [2] Linux配置yum源(本地源和网络源) [3] SuSE下zypper源配置 [4] SUSE zypper 本地 ...

  2. swift 实现QQ好友列表功能

    最近项目中有类似QQ好友列表功能,整理了一下,话不多说,直接上代码 import UIKit class QQFriend: NSObject { var name: String? var intr ...

  3. ClassLoad类加载器与双亲委派模型

    1. 类加载器 Class类描述的是整个类的信息,在Class类中提供的方法getName()是根据ClassPath配置的路径来进行类加载的.若类加载的路径为文件.网络等时则必须进行类加载这是就需要 ...

  4. 【编程思想】【设计模式】【行为模式Behavioral】访问者模式Visitor

    Python版 https://github.com/faif/python-patterns/blob/master/behavioral/visitor.py #!/usr/bin/env pyt ...

  5. Linux基础命令---ab测试apache性能

    ab ab指令是apache的性能测试工具,它可以测试当前apache服务器的运行性能,显示每秒中可以处理多少个http请求. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.F ...

  6. vue-cli4脚手架搭建三

    组件传值 <script> import LunBo from "./LunBo"; export default { name: 'Home', components ...

  7. 云服务器ECS部署和卸载RabbitMQ

    云服务器ECS部署RabbitMQ RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件,用于在分布式系统中存储转发消息,有良好的易用性.扩展性和高可用性.本文介绍如何通过ECS实例 ...

  8. log4j漏洞的产生原因和解决方案,小白都能看懂!!!!

    核弹级bug Log4j,相信很多人都有所耳闻了,这两天很多读者都在问我关于这个bug的原理等一些问题,今天咱们就专门写一篇文章,一起聊一聊这个核弹级别的bug的产生原理以及怎么防止 产生原因 其实这 ...

  9. 开发中Design Review和Code Review

    一.Design Review 详解 翻译为设计评审,也就是对需求设计进行审核,防止出现异常问题,例如下面的这些 可用性 外部依赖有哪些?如果这些外部依赖崩溃了我们有什么处理措施? 我们SLA是什么? ...

  10. 小迪安全 Web安全 基础入门 第六天 - 信息打点-Web架构篇&域名&语言&中间件&数据库&系统&源码获取

    一 . Web架构 语言.常用的Web开发语言有PHP,Java,Python,JavaScript,.net等.具体可参考w3school的介绍. 中间件. (1)常见的Web服务器中间件:IIS. ...