Adam 优化器在 200k 批次后失控,训练损失增加
Adam optimizer goes haywire after 200k batches, training loss grows
我在训练网络时看到了一个非常奇怪的行为,在经过几次 100k 次迭代(8 到 10 小时)的良好学习后,一切都崩溃了,训练损失 增长:
训练数据本身是随机的,分布在许多 .tfrecord
个文件中,每个文件包含 1000
个示例,然后在输入阶段再次洗牌并批处理为 200
个示例。
背景
我正在设计一个同时执行四种不同回归任务的网络,例如确定物体出现在图像中的可能性并同时确定其方向。该网络从几个卷积层开始,其中一些具有残差连接,然后分支成四个完全连接的部分。
由于第一个回归结果是概率,我使用交叉熵作为损失,而其他人使用经典的 L2 距离。然而,由于它们的性质,概率损失约为 0..1
,而方向损失可能更大,例如 0..10
。我已经标准化了输入和输出值并使用了裁剪
normalized = tf.clip_by_average_norm(inferred.sin_cos, clip_norm=2.)
在情况变得非常糟糕的情况下。
我一直(成功地)使用 Adam 优化器优化包含所有不同损失的张量(而不是 reduce_sum
ing 它们),如下所示:
reg_loss = tf.reduce_sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
loss = tf.pack([loss_probability, sin_cos_mse, magnitude_mse, pos_mse, reg_loss])
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate,
epsilon=self.params.adam_epsilon)
op_minimize = optimizer.minimize(loss, global_step=global_step)
为了在TensorBoard中显示结果,我其实是这样做的
loss_sum = tf.reduce_sum(loss)
标量摘要。
Adam 设置为学习率 1e-4
和 epsilon 1e-4
(我看到与 epislon 默认值相同的行为,当我将学习率保持在 1e-3
).正则化对此也没有影响,它在某些时候始终如一地进行这种操作。
我还应该补充一点,停止训练并从最后一个检查点重新开始——这意味着训练输入文件也被重新洗牌——导致相同的行为。在这一点上,训练似乎总是表现得相似。
是的。这是 Adam 的一个已知问题。
Adam 的方程是
t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)
m_t <- beta1 * m_{t-1} + (1 - beta1) * g
v_t <- beta2 * v_{t-1} + (1 - beta2) * g * g
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)
其中 m
是平均梯度的指数移动平均值,v
是梯度平方的指数移动平均值。问题是,当你训练了很长时间,并且接近最优时,那么 v
会变得很小。如果突然间梯度开始再次增加,它将被一个非常小的数字除并爆炸。
默认 beta1=0.9
和 beta2=0.999
。所以 m
的变化比 v
快得多。所以m
可以重新开始变大,而v
还小,追不上。
要解决此问题,您可以增加 epsilon
,默认情况下为 10-8
。从而解决了几乎被 0 除的问题。
根据您的网络,0.1
、0.01
或 0.001
中的 epsilon
值可能比较合适。
是的,这可能是某种超级复杂的不稳定 numbers/equations 情况,但可以肯定的是,您的训练率只是太高了,因为您的损失会迅速减少,直到 25K,然后在同一水平上振荡很多。尝试将它减少 0.1,看看会发生什么。您应该能够达到更低的损失值。
继续探索! :)
我在训练网络时看到了一个非常奇怪的行为,在经过几次 100k 次迭代(8 到 10 小时)的良好学习后,一切都崩溃了,训练损失 增长:
训练数据本身是随机的,分布在许多 .tfrecord
个文件中,每个文件包含 1000
个示例,然后在输入阶段再次洗牌并批处理为 200
个示例。
背景
我正在设计一个同时执行四种不同回归任务的网络,例如确定物体出现在图像中的可能性并同时确定其方向。该网络从几个卷积层开始,其中一些具有残差连接,然后分支成四个完全连接的部分。
由于第一个回归结果是概率,我使用交叉熵作为损失,而其他人使用经典的 L2 距离。然而,由于它们的性质,概率损失约为 0..1
,而方向损失可能更大,例如 0..10
。我已经标准化了输入和输出值并使用了裁剪
normalized = tf.clip_by_average_norm(inferred.sin_cos, clip_norm=2.)
在情况变得非常糟糕的情况下。
我一直(成功地)使用 Adam 优化器优化包含所有不同损失的张量(而不是 reduce_sum
ing 它们),如下所示:
reg_loss = tf.reduce_sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
loss = tf.pack([loss_probability, sin_cos_mse, magnitude_mse, pos_mse, reg_loss])
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate,
epsilon=self.params.adam_epsilon)
op_minimize = optimizer.minimize(loss, global_step=global_step)
为了在TensorBoard中显示结果,我其实是这样做的
loss_sum = tf.reduce_sum(loss)
标量摘要。
Adam 设置为学习率 1e-4
和 epsilon 1e-4
(我看到与 epislon 默认值相同的行为,当我将学习率保持在 1e-3
).正则化对此也没有影响,它在某些时候始终如一地进行这种操作。
我还应该补充一点,停止训练并从最后一个检查点重新开始——这意味着训练输入文件也被重新洗牌——导致相同的行为。在这一点上,训练似乎总是表现得相似。
是的。这是 Adam 的一个已知问题。
Adam 的方程是
t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)
m_t <- beta1 * m_{t-1} + (1 - beta1) * g
v_t <- beta2 * v_{t-1} + (1 - beta2) * g * g
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)
其中 m
是平均梯度的指数移动平均值,v
是梯度平方的指数移动平均值。问题是,当你训练了很长时间,并且接近最优时,那么 v
会变得很小。如果突然间梯度开始再次增加,它将被一个非常小的数字除并爆炸。
默认 beta1=0.9
和 beta2=0.999
。所以 m
的变化比 v
快得多。所以m
可以重新开始变大,而v
还小,追不上。
要解决此问题,您可以增加 epsilon
,默认情况下为 10-8
。从而解决了几乎被 0 除的问题。
根据您的网络,0.1
、0.01
或 0.001
中的 epsilon
值可能比较合适。
是的,这可能是某种超级复杂的不稳定 numbers/equations 情况,但可以肯定的是,您的训练率只是太高了,因为您的损失会迅速减少,直到 25K,然后在同一水平上振荡很多。尝试将它减少 0.1,看看会发生什么。您应该能够达到更低的损失值。
继续探索! :)