AdamOptimizer|AdamOptimizer Loss Null

【AdamOptimizer|AdamOptimizer Loss Null】之前一直用的的tensorflow的AdamOptimizer,由于想要复现下别人的论文,看到论文中的参数有momentum,因此需要用tf.train.MomentumOptimizer优化器,本来可以正常训练的代码再开始训练两步后就显示loss为NaN了。试了调整学习率和动量都没用。后来,到github上查了一下,发现有人提示修改如下.(参考链接https://github.com/tensorlayer/openpose-plus/issues/50)
opt = tf.train.MomentumOptimizer(lr_v, 0.9)
train_op = opt.minimize(total_loss, global_step=global_step)
将上面这段代码改为
tvars = tf.layers.get_variables_with_name('model', True, True)
grads, _ = tf.clip_by_global_norm(tf.gradients(total_loss, tvars), 100)
optimizer = tf.train.MomentumOptimizer(lr_v, 0.9)
train_op = optimizer.apply_gradients(zip(grads, tvars), global_step=global_step)
代码中第一行是获取可训练的变量,我换成了tf.trainable_variables()来实现。这样一来就可以正常训练了。
分析下原因吧,应该是momentum冲量过大导致梯度爆炸,因此需要对梯度进行约束。tf.clip_by_global_norm(tf.gradients(loss, tvars), 100) 就是约束梯度的函数,限制梯度值小于100。如此就不会因为梯度爆炸导致loss很大了。
查看tf.clip_by_global_norm的文档解释,发现文中提到该函数的耗时较长,因为需要计算全局梯度。tf.clip_by_norm函数是限制每个梯度值,因此耗时较短。又查找了一些材料后,可以将代码修改成如下:(参考链接https://blog.csdn.net/linuxwindowsios/article/details/67635867)
optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9)
grads = optimizer.compute_gradients(loss)
for i, (g, v) in enumerate(grads):
if g is not None:
grads[i] = (tf.clip_by_norm(g, 100), v)# clip gradients
train_op = optimizer.apply_gradients(grads, global_step=global_step)

    推荐阅读