TensorFlow中的引导反向传播

时间:2016-07-13 00:20:41

标签: tensorflow backpropagation

我想在TensorFlow中实现此 Paper 中引入的“引导反向传播”技术,并在此 recipe 中进行了描述。

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

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

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

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

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

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

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

    非常感谢。

2 个答案:

答案 0 :(得分:7)

使用ops.RegisterGradientgradient_override_map的更好解决方案(您的方法1)。它们一起覆盖预定义Op的梯度计算,例如,仅使用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) 上下文中重新调用。

tf.select

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

更新:在Tensorflow&gt; = 1.0中,tf.where重命名为 In [14]: df1 Out[14]: Send_Customer Pay_Customer 0 1000000000009548332 2000000000087113758 1 1000000000072327616 2000000000087113758 2 1000000000081537869 2000000000087113758 3 1000000000007725765 2000000000078800989 4 1000000000031950290 2000000000078800989 5 1000000000082570417 2000000000078800989 6 1000000000009548332 1000000000142041382 7 1000000000072327616 1000000000142041382 8 2000000000097181041 1000000000004033594 。我相应地更新了片段。 (感谢@sbond将此引起我的注意:)

答案 1 :(得分:6)

grad_ys具有可用于此目的的relu参数。假设您的网络只有一个before_relu = f1(inputs, params) after_relu = tf.nn.relu(before_relu) loss = f2(after_relu, params, targets) 层,如下所示:

after_relu

首先,计算导数至Dafter_relu = tf.gradients(loss, after_relu)[0]

Dafter_relu_thresholded = tf.select(Dafter_relu < 0.0, 0.0, Dafter_relu)

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

params

将实际渐变w.r.t计算为Dparams = tf.gradients(after_relu, params, grad_ys=Dafter_relu_thresholded)

relu

您可以轻松地为具有多个{{1}}图层的网络扩展此方法。