Python 如何为GradientDescentOptimizer设置自适应学习率?

Python 如何为GradientDescentOptimizer设置自适应学习率?,python,tensorflow,Python,Tensorflow,我用TensorFlow来训练神经网络。这就是我如何初始化GradientDescentOptimizer: init = tf.initialize_all_variables() sess = tf.Session() sess.run(init) mse = tf.reduce_mean(tf.square(out - out_)) train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse) 这里的问

我用TensorFlow来训练神经网络。这就是我如何初始化
GradientDescentOptimizer

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

mse        = tf.reduce_mean(tf.square(out - out_))
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)
这里的问题是,我不知道如何设置学习率的更新规则或衰减值


这里如何使用自适应学习速率?

首先,
tf.train.GradientDescentOptimizer
设计用于在所有步骤中对所有变量使用恒定的学习速率。TensorFlow还提供了开箱即用的自适应优化器,包括和,这些优化器可用作插入式替换

但是,如果您想用梯度下降控制学习速率,则可以利用以下事实:的
学习速率
参数可以是
张量
对象。这允许您为每个步骤中的学习率计算不同的值,例如:

learning_rate = tf.placeholder(tf.float32, shape=[])
# ...
train_step = tf.train.GradientDescentOptimizer(
    learning_rate=learning_rate).minimize(mse)

sess = tf.Session()

# Feed different values for learning rate to each training step.
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.01})
sess.run(train_step, feed_dict={learning_rate: 0.01})

或者,您可以创建一个标量
tf.变量
,用于保存学习率,并在每次需要更改学习率时分配它。

Tensorflow提供了一个操作,可自动将指数衰减应用于学习率张量:。有关正在使用的it的示例,请参阅。然后使用上面@mrry的建议将此变量作为学习率参数提供给您选择的优化器

要查看的关键摘录是:

# Optimizer: set up a variable that's incremented once per batch and
# controls the learning rate decay.
batch = tf.Variable(0)

learning_rate = tf.train.exponential_decay(
  0.01,                # Base learning rate.
  batch * BATCH_SIZE,  # Current index into the dataset.
  train_size,          # Decay step.
  0.95,                # Decay rate.
  staircase=True)
# Use simple momentum for the optimization.
optimizer = tf.train.MomentumOptimizer(learning_rate,
                                     0.9).minimize(loss,
                                                   global_step=batch)
注意要最小化的
global\u step=batch
参数。这告诉优化器在每次训练时为您有效地增加“batch”参数。

来自官方文档

global_step = tf.Variable(0, trainable=False)
starter_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,
                                       100000, 0.96, staircase=True)

# Passing global_step to minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss..., global_step=global_step))

梯度下降算法使用您可以在中提供的恒定学习速率。您可以通过Mrry显示的各种学习率

但是,你也可以使用收敛速度更快且适应情况的方法来代替它

根据我的理解,以下是一个简短的解释:

  • 动量SGD沿相关方向导航,并减弱不相关方向的振荡。它只是将上一步方向的一小部分添加到当前步骤。这样可以在正确的方向上放大速度,并减弱错误方向上的振荡。这个分数通常在(0,1)范围内。使用自适应动量也是有意义的。在开始学习时,一个大的动量只会阻碍你的进步,所以使用0.01这样的数值是有意义的,一旦所有的高梯度消失,你可以使用一个更大的动量。动量有一个问题:当我们非常接近目标时,在大多数情况下,我们的动量非常高,它不知道应该减速。这可能导致它错过或围绕极小值振荡
  • 内斯特罗夫加速梯度通过提前开始减速来克服这个问题。在动量中,我们首先计算梯度,然后在那个方向上做一个跳跃,这个跳跃被之前的动量放大了。NAG做同样的事情,但顺序不同:首先我们根据存储的信息进行一次大的跳跃,然后计算梯度并进行一次小的修正。这一看似无关紧要的变化带来了显著的实际加速
  • AdaGrad或自适应梯度允许学习速率根据参数进行调整。它对不频繁的参数执行较大的更新,对频繁的参数执行较小的更新。因此,它非常适合稀疏数据(NLP或图像识别)。另一个优点是,它基本上消除了调整学习速度的需要。每个参数都有自己的学习率,由于算法的特殊性,学习率是单调递减的。这导致了最大的问题:在某个时间点,学习率很低,以至于系统停止学习
  • AdaDelta解决了AdaGrad中学习率单调递减的问题。在AdaGrad中,学习率的计算近似为1除以平方根之和。在每一个阶段,你给总和加上另一个平方根,这会导致分母不断减少。在ADADDelta中,它使用滑动窗口,而不是对所有过去的平方根求和,从而允许总和减小RMSprop与ADADDelta非常相似
  • Adam或自适应动量算法是一种类似于ADADDelta的算法。但除了存储每个参数的学习速率外,它还分别存储每个参数的动量变化

    A:


如果您想为
0
等时段设置特定的学习率。然后,你可以将你的学习率定义为一个条件张量,以全局步长为条件,并将其作为常态反馈给优化者

您可以通过一组嵌套的
tf.cond
语句来实现这一点,但递归构建张量更容易:

def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
    assert len(reduction_steps) + 1 == len(learning_rates)
    if len(reduction_steps) == 1:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: learning_rates[1]
        )
    else:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: make_learning_rate_tensor(
                reduction_steps[1:],
                learning_rates[1:],
                global_step,)
            )

回答得很好。同样的技术可以用于渐变剪裁吗
tf.clip\u by_norm
不接受用于clip norm的张量,那么在optimizer.compute\u梯度(cost,vars)
中对gv执行
[(tf.minimum(gv[0],ct),gv[1])应该可以,是的。(尽管查看
tf.clip\u by\u norm
,但唯一阻止它接受张量作为输入的是
常量op.constant(1.0/clip\u norm)
。将该表达式替换为
math\u ops.inv(clip\u norm)
将使其与占位符(或任何其他张量)输入一起工作。)@mrry我按照你说的做了,有些人说训练速度慢多了。是否需要它?通常,您调用的
batch
变量称为
global\u step
,并且有几个方便的函数,其中一个函数用于创建它
tf.train.create\u global\u step()
(它只是创建一个整数
tf.variable
,并将其添加到
tf.GraphKe>)
global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)