TensorFlow中的引导反向传播

Pet*_*ter 8 backpropagation tensorflow

我想在TensorFlow实现在此引入"引导反向传播"的技术论文和其在此描述的配方.

计算上意味着当我计算梯度时,例如输入wrt.NN的输出,我将不得不修改每个RELU单元计算的梯度.具体地说,这些单元上的反向传播信号必须在零上设置阈值,以使该技术起作用.换句话说,必须忽略RELU的负面偏导数.

鉴于我只对测试示例应用这些梯度计算感兴趣,即我不想更新模型的参数 - 我该怎么做?

到目前为止,我尝试过两件事(不成功):

  1. 使用tf.py_func包装我的简单numpy版本的RELU,然后有资格通过g.gradient_override_map上下文管理器重新定义它的渐变操作.

  2. 收集BackProp的前向/后向值并对源自Relus的那些值应用阈值.

我用两种方法都失败了,因为他们需要一些目前我没有的TF内部知识.

任何人都可以建议任何其他路线,或草拟代码?

非常感谢.

Fal*_*con 7

更好的解决方案(你的方法1)ops.RegisterGradienttf.Graph.gradient_override_map.它们一起覆盖内,用于预定义的运算的梯度计算,例如RELU gradient_override_map仅使用Python代码上下文.

@ops.RegisterGradient("GuidedRelu")
def _GuidedReluGrad(op, grad):
    return tf.where(0. < grad, gen_nn_ops._relu_grad(grad, op.outputs[0]), tf.zeros(grad.get_shape()))

...
with g.gradient_override_map({'Relu': 'GuidedRelu'}):
    y = tf.nn.relu(x)
Run Code Online (Sandbox Code Playgroud)

这是引导relu的完整示例实现:https://gist.github.com/falcondai/561d5eec7fed9ebf48751d124a77b087

更新:在Tensorflow> = 1.0中,tf.select重命名为tf.where.我相应地更新了代码段.(感谢@sbond将此引起我的注意:)

  • 请注意,您需要在`gradient_override_map`上下文中包含涉及relu op*的图形构造. (3认同)

kev*_*man 6

tf.gradientsgrad_ys可用于这一目的的参数.假设您的网络只有一个relu层,如下所示:

before_relu = f1(inputs, params)
after_relu = tf.nn.relu(before_relu)
loss = f2(after_relu, params, targets)
Run Code Online (Sandbox Code Playgroud)

首先,计算导数到after_relu.

Dafter_relu = tf.gradients(loss, after_relu)[0]
Run Code Online (Sandbox Code Playgroud)

然后对您发送的渐变进行阈值处理.

Dafter_relu_thresholded = tf.select(Dafter_relu < 0.0, 0.0, Dafter_relu)
Run Code Online (Sandbox Code Playgroud)

计算实际的梯度params.

Dparams = tf.gradients(after_relu, params, grad_ys=Dafter_relu_thresholded)
Run Code Online (Sandbox Code Playgroud)

您可以轻松地为具有多个relu层的网络扩展此相同方法.