これで紹介されている「ガイド付きバックプロパゲーション」の手法をTensorFlowに実装したいと思います 紙 そしてこれはこの レシピ で説明されています。
計算上、これは、たとえば入力wrtの勾配を計算するときに意味します。 NNの出力、私はすべてのRELUユニットで計算された勾配を変更するする必要があります。具体的には、この手法を機能させるには、これらのユニットで逆伝播された信号をゼロでしきい値処理する必要があります。言い換えると、負のRELUの偏導関数は無視する必要があります。
これらの勾配計算をテスト例にのみ適用することに関心がある場合、つまり、モデルのパラメーターを更新したくない場合、どのようにすればよいですか?
私はこれまでに2つのことを(失敗して)試しました:
tf.py_funcを使用して、RELUの単純なnumpyバージョンをラップします。これにより、g.gradient_override_mapコンテキストマネージャーを介してグラデーション操作を再定義できます。
BackPropの順方向/逆方向の値を収集し、Relusに由来する値にしきい値を適用します。
現在私が持っていないTFの内部に関する知識が必要なため、両方のアプローチで失敗しました。
誰かが他のルートを提案したり、コードをスケッチしたりできますか?
どうもありがとう。
ops.RegisterGradient
およびtf.Graph.gradient_override_map
を使用したより良いソリューション(アプローチ1)。これらは一緒になって、事前定義されたOpの勾配計算をオーバーライドします。 pythonコードのみを使用して、gradient_override_map
コンテキスト内でReluします。
@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)
ガイド付きreluの完全な実装例は次のとおりです。 https://Gist.github.com/falcondai/561d5eec7fed9ebf48751d124a77b087
Update:Tensorflow> = 1.0では、tf.select
はtf.where
に名前が変更されます。それに応じてスニペットを更新しました。 (これを私の注意を引いてくれてありがとう@sbond :)
tf.gradients
には、この目的に使用できるgrad_ys
パラメーターがあります。次のように、ネットワークにrelu
レイヤーが1つだけあるとします。
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
レイヤーを持つネットワークに簡単に拡張できます。