Tensorflow:关于 adam 优化器的困惑

Tensorflow: Confusion regarding the adam optimizer

我对 adam 优化器在 tensorflow 中的实际工作方式感到困惑。

我读 docs 的方式是说每次梯度下降迭代都会改变学习率。

但是当我调用函数时,我给它一个学习率。而且我不会调用该函数来让我们说,做一个时代(隐式调用 # 迭代以便完成我的数据训练)。我明确地为每个批次调用函数

for epoch in epochs
     for batch in data
          sess.run(train_adam_step, feed_dict={eta:1e-3})

所以我的预计到达时间不能更改。而且我没有传递时间变量。或者这是某种生成器类型的东西,每次我调用优化器时创建会话 t 都会递增?

假设它是某种生成器类型的东西并且学习率正在无形中降低:我怎样才能在不降低学习率的情况下达到 运行 adam 优化器?在我看来 RMSProp 基本相同,我唯一要做的就是将超参数 momentumdecay 更改为分别匹配 beta1beta2。对吗?

我觉得文档很清楚,我把算法伪代码贴在这里:

你的参数:

  • learning_rate: 1e-4 和 1e-2 之间为标准
  • beta1: 默认为 0.9
  • beta2:默认为 0.999
  • epsilon: 默认为1e-08

    The default value of 1e-8 for epsilon might not be a good default in general. For example, when training an Inception network on ImageNet a current good choice is 1.0 or 0.1.


初始化:

m_0 <- 0 (Initialize initial 1st moment vector)
v_0 <- 0 (Initialize initial 2nd moment vector)
t <- 0 (Initialize timestep)

m_tv_t 将为网络的每个参数跟踪梯度及其平方的 移动平均值 。 (所以如果你有 1M 个参数,Adam 会在内存中多保留 2M 个参数)


在每次迭代时 t,对于模型的每个参数

t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)

m_t <- beta1 * m_{t-1} + (1 - beta1) * gradient
v_t <- beta2 * v_{t-1} + (1 - beta2) * gradient ** 2
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)

这里lr_tlearning_rate有点不同,因为对于早期的迭代,移动平均线还没有收敛所以我们必须通过乘以sqrt(1 - beta2^t) / (1 - beta1^t)来归一化。当t为高(t > 1./(1.-beta2))时,lr_t几乎等于learning_rate


要回答你的问题,你只需要传递一个固定学习率,保持beta1beta2默认值,也许修改epsilon,Adam 会施展魔法 :)


Link 与 RMSProp

具有 beta1=1 的 Adam 等同于具有 momentum=0 的 RMSProp。 Adam的自变量beta2和RMSProp的自变量decay相同

但是,RMSProp 不保持梯度的移动平均值。但是它可以像MomentumOptimizer一样保持动力。

rmsprop 的详细说明。

  • 保持梯度平方的移动(贴现)平均值
  • 将梯度除以这个平均值的根
  • (能保持势头)

这是伪代码:

v_t <- decay * v_{t-1} + (1-decay) * gradient ** 2
mom = momentum * mom{t-1} + learning_rate * gradient / sqrt(v_t + epsilon)
variable <- variable - mom

RMS_PROP 和 ADAM 都具有自适应学习率。

基础RMS_PROP

cache = decay_rate * cache + (1 - decay_rate) * dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)

你可以看到原来这有两个参数decay_rate & eps

然后我们可以加一个动量让我们的梯度更稳定然后我们可以写

cache = decay_rate * cache + (1 - decay_rate) * dx**2
**m = beta1*m + (1-beta1)*dx**  [beta1 =momentum parameter in the doc ]
x += - learning_rate * dx / (np.sqrt(cache) + eps)

现在你可以在这里看到如果我们保持 beta1 = o 然后它是 rms_prop 没有动量。

然后是 ADAM 基础知识

cs-231 Andrej Karpathy中最初是这样描述亚当的

Adam is a recently proposed update that looks a bit like RMSProp with momentum

是的!那么与动量 rms_prop 有什么区别呢?

m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
**x += - learning_rate * m / (np.sqrt(v) + eps)**

他在更新方程中再次提到 m , v 更平滑

因此与 rms_prop 的不同之处在于更新噪音较小。

为什么会发出这种声音?

那么在初始化过程中,我们将 m 和 v 初始化为零。

m=v=0

为了减少这种初始化效果,总是要进行一些预热。那么等式就像

m = beta1*m + (1-beta1)*dx          beta1 -o.9 beta2-0.999
**mt = m / (1-beta1**t)**
v = beta2*v + (1-beta2)*(dx**2)
**vt = v / (1-beta2**t)**
x += - learning_rate * mt / (np.sqrt(vt) + eps)

现在我们 运行 进行几次迭代。清楚地注意粗线,您可以看到 t 何时增加(迭代次数)以下事情发生在 mt 上,

mt=m