我想根据损失函数相对于权重的梯度值来实现一个停止条件。例如,假设我有以下代码:
optimizer = tf.train.AdamOptimizer()grads_and_vars = optimizer.compute_gradients(a_loss_function)train_op = optimizer.apply_gradients(grads_and_vars)
然后我想像这样运行图:
for step in range(TotSteps): output = sess.run([input], feed_dict=some_dict) if(grad_taken_in_some_way < some_treshold): print("训练结束。") break
我不知道应该向sess.run()
传递什么参数才能同时获取梯度值(除了其他我需要的东西)。我甚至不确定这是否是正确的做法,还是应该采用不同的方法。我尝试过几次,但每次都失败了。希望有人能提供一些提示。提前感谢!
编辑:英语修正
编辑2:Iballes的回答正是我想要做的。不过,我仍然不确定如何对所有梯度进行归一化和求和。因为我的CNN中有不同的层和不同形状的权重,如果我只是按照你的建议去做,会在add_n()
操作上得到一个错误(因为我试图将形状不同的矩阵相加)。所以我可能应该做类似以下的事情:
grad_norms = [tf.nn.l2_normalize(g[0], 0) for g in grads_and_vars] grad_norm = [tf.reduce_sum(grads) for grads in grad_norms]final_grad = tf.reduce_sum(grad_norm)
有人可以确认一下吗?
回答:
你的代码行output = sess.run([input], feed_dict=some_dict)
让我觉得你对sess.run
命令有些误解。你所称的[input]
应该是一组由sess.run
命令获取的张量。因此,它是输出而不是输入。为了回答你的问题,我们假设你正在做类似output = sess.run(loss, feed_dict=some_dict)
的事情(以便监控训练损失)。
此外,我猜你想使用梯度的范数(梯度本身是一个多维量)来制定你的停止标准。因此,你需要在每次执行图时获取梯度范数。为此,你需要做两件事。1)将梯度范数添加到计算图中。2)在训练循环中的每次sess.run
调用中获取它。
关于1)你已经通过以下代码将梯度添加到图中:
optimizer = tf.train.AdamOptimizer()grads_and_vars = optimizer.compute_gradients(a_loss_function)
现在你可以在grads_and_vars
中找到保存梯度的张量(图中每个训练变量一个)。让我们对每个梯度取范数,然后将它们相加:
grad_norms = [tf.nn.l2_loss(g) for g, v in grads_and_vars]grad_norm = tf.add_n(grad_norms)
这样你就有了梯度范数。
关于2)在你的循环中,通过告诉sess.run
命令来获取梯度范数和损失:
for step in range(TotSteps): l, gn = sess.run([loss, grad_norm], feed_dict=some_dict) if(gn < some_treshold): print("训练结束。") break