解决tf.train.MomentumOptimizer 发生NaN问题

之前一直用的的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)

 

你可能感兴趣的:(tensorflow)