我正在使用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)
这里的问题是我不知道如何为学习率或衰减值设置更新规则 .
我如何在这里使用自适应学习率?
4 回答
首先,
tf.train.GradientDescentOptimizer
旨在对所有步骤中的所有变量使用恒定学习率 . TensorFlow还提供开箱即用的自适应优化器,包括tf.train.AdagradOptimizer和tf.train.AdamOptimizer,这些可用作插入式替换 .但是,如果您想用其他方式控制学习率,那么您可以利用tf.train.GradientDescentOptimizer constructor的
learning_rate
参数可以是Tensor
对象这一事实 . 这允许您为每个步骤中的学习率计算不同的值,例如:或者,您可以创建一个保持学习速率的标量
tf.Variable
,并在每次要更改学习速率时分配它 .Tensorflow提供了一种操作,可自动将指数衰减应用于学习速率张量:tf.train.exponential_decay . 有关它的使用示例,请参阅this line in the MNIST convolutional model example . 然后使用上面的@mrry建议将此变量作为learning_rate参数提供给您选择的优化器 .
要看的关键摘录是:
请注意
global_step=batch
参数以最小化 . 这告诉优化器每次训练时都会为你帮助增加'batch'参数 .梯度下降算法使用您可以在during the initialization中提供的常量学习率 . 您可以通过Mrry表现的方式传递各种学习率 .
但是你可以使用more advanced optimizers而不是它,它具有更快的收敛速度并适应这种情况 .
以下是基于我的理解的简要说明:
momentum helps SGD沿相关方向导航并软化无关紧要的振荡 . 它只是将前一步骤的一部分方向添加到当前步骤 . 这实现了在正确的方向上放大速度并且在错误的方向上软化振荡 . 该分数通常在(0,1)范围内 . 使用自适应动量也是有意义的 . 在学习开始时,一个巨大的动力只会阻碍你的进步,所以使用像0.01这样的东西很有意义,一旦所有的高梯度消失,你就可以使用更大的时刻 . 动量存在一个问题:当我们非常接近目标时,我们在大多数情况下的势头非常高,并且不知道它应该减速 . 这可能导致它在最小值周围错过或振荡
nesterov accelerated gradient 通过开始减速来克服这个问题 . 在动量中,我们首先计算梯度,然后在那个方向上跳跃,放大我们之前的动量 . NAG做了同样的事情,但是按照另一种顺序:首先我们根据存储的信息进行大跳,然后我们计算渐变并进行小的修正 . 这种看似无关紧要的变化带来了显着的实际加速 .
AdaGrad 或自适应梯度允许学习速率基于参数进行调整 . 它为不频繁的参数执行更大的更新,为频繁的参数执行更小的更新 . 因此,它非常适合稀疏数据(NLP或图像识别) . 另一个优点是它基本上不需要调整学习速率 . 每个参数都有自己的学习速率,并且由于算法的特殊性,学习速率是单调递减的 . 这导致了最大的问题:在某些时间点,学习速度很小,系统停止学习
AdaDelta 解决了AdaGrad单调降低学习率的问题 . 在AdaGrad中,学习率大致计算为1除以平方根的总和 . 在每个阶段,您将另一个平方根添加到总和,这会导致分母不断减少 . 在AdaDelta中,它不是对所有过去的平方根求和,而是使用滑动窗口,允许总和减少 . RMSprop 与AdaDelta非常相似
Adam 或自适应动量是一种类似于AdaDelta的算法 . 但除了存储每个参数的学习率之外,它还分别存储每个参数的动量变化
A few visualizations:
来自tensorflow官方文档