Tensorflow:如何替换或修改梯度?
0 944
0

我想替换或修改tensorflow中的OP或部分图的梯度。 如果我能在计算中使用现有的梯度,那就更理想了。 在某些方面,这与tf.stop_gradient()所做的相反:我不想在计算梯度时添加一个被忽略的计算,而是想要一个只在计算梯度时使用的计算。

一个简单的例子是,通过将梯度与常数相乘来简单地缩放梯度(但不将正向计算乘以常数)。 另一个例子是将梯度剪切到给定的范围。

收藏
2021-02-18 10:37 更新 karry •  4552
共 1 个回答
高赞 时间
0

对于TensorFlow1.7和TensorFlow2.0,请看下面的编辑。 首先定义自定义梯度:

@tf.RegisterGradient("CustomGrad")def _const_mul_grad(unused_op, grad):
  return 5.0 * grad

由于你不希望在前向传递中发生任何事情,所以用新的梯度覆盖标识操作的梯度:

g = tf.get_default_graph()with g.gradient_override_map({"Identity": "CustomGrad"}):
  output = tf.identity(input, name="Identity")

这里有一个示例,该层使用相同的方法,在向后传递中剪辑梯度,在向前传递中不做任何事情:

import tensorflow as tf@tf.RegisterGradient("CustomClipGrad")def _clip_grad(unused_op, grad):
  return tf.clip_by_value(grad, -0.1, 0.1)input = tf.Variable([3.0], dtype=tf.float32)
g = tf.get_default_graph()with g.gradient_override_map({"Identity": "CustomClipGrad"}):
  output_clip = tf.identity(input, name="Identity")
grad_clip = tf.gradients(output_clip, input)# output without gradient clipping in the backwards pass for comparison:
output = tf.identity(input)
grad = tf.gradients(output, input)with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  print("with clipping:", sess.run(grad_clip)[0])
  print("without clipping:", sess.run(grad)[0])

编辑TensorFlow 1.7和TensorFlow 2.0 从1.7开始,有一种新的方法可以使用较短的语法重新定义梯度,这也适用于Tensorflow 2.0。它还允许同时重新定义多个操作的梯度。以下是上面为TensorFlow 1.7和TensorFlow 2.0重写的示例: 后向通道中缩放梯度的层:

@tf.custom_gradientdef scale_grad_layer(x):
  def grad(dy):
    return 5.0 * dy
  return tf.identity(x), grad

后向通道中剪切梯度的层:

@tf.custom_gradientdef clip_grad_layer(x):
  def grad(dy):
    return tf.clip_by_value(dy, -0.1, 0.1)
  return tf.identity(x), grad

via:https://stackoverflow.com/a/43948872/14964791

收藏
2021-02-18 11:07 更新 anna •  5048