このページは Cloud Translation API によって翻訳されました。
Switch to English

tf.custom_gradient

TensorFlow 1バージョン GitHubでソースを表示

カスタムグラデーションで関数を定義するデコレーター。

このデコレータにより、操作のシーケンスの勾配を細かく制御できます。これは、一連の操作に対してより効率的または数値的に安定した勾配を提供することを含む、複数の理由で役立つ場合があります。

たとえば、クロスエントロピーと対数尤度の計算で一般的に発生する次の関数を考えます。

 def log1pexp(x):
  return tf.math.log(1 + tf.exp(x))
 

数値が不安定であるため、x = 100で評価されるこの関数の勾配はNaNです。例えば:

 x = tf.constant(100.)
y = log1pexp(x)
dy = tf.gradients(y, x) # Will be NaN when evaluated.
 

勾配式は、数値的に安定させるために分析的に簡略化できます。

 @tf.custom_gradient
def log1pexp(x):
  e = tf.exp(x)
  def grad(dy):
    return dy * (1 - 1 / (1 + e))
  return tf.math.log(1 + e), grad
 

この定義により、x = 100の勾配は1.0として正しく評価されます。

カスタムグラデーションをネストすると、直感的でない結果になる可能性があります。既定の動作は、n次の導関数に対応していません。例えば

 @tf.custom_gradient
def op(x):
  y = op1(x)
  @tf.custom_gradient
  def grad_fn(dy):
    gdy = op2(x, y, dy)
    def grad_grad_fn(ddy):  # Not the 2nd order gradient of op w.r.t. x.
      return op3(x, y, dy, ddy)
    return gdy, grad_grad_fn
  return y, grad_fn
 

関数grad_grad_fnは、 dyに関してgrad_fn一次勾配を計算します。これは、後方モード勾配グラフから前方モード勾配グラフを生成するために使用されますが、 xに関するop 2次勾配とはgrad_fnます。

代わりに、ネストされた@tf.custom_gradientsを別の関数でラップします。

 @tf.custom_gradient
def op_with_fused_backprop(x):
  y, x_grad = fused_op(x)
  def first_order_gradient(dy):
    @tf.custom_gradient
    def first_order_custom(unused_x):
      def second_order_and_transpose(ddy):
        return second_order_for_x(...), gradient_wrt_dy(...)
      return x_grad, second_order_and_transpose
    return dy * first_order_custom(x)
  return y, first_order_gradient
 

内側の@tf.custom_gradient -decorated関数への追加の引数は、最も内側の関数の予期される戻り値を制御します。

プリミティブTensorFlow演算の勾配関数を登録するtf.RegisterGradientも参照してください。一方、 tf.custom_gradientを使用すると、一連の操作の勾配計算を細かく制御できます。

装飾された関数がVariable使用する場合、囲んでいる変数スコープはResourceVariableを使用する必要があることに注意してください。

f タプル(y, grad_fn)を返す関数f(*x) (y, grad_fn)ここで、

  • xは、関数へのTensor入力(の入れ子構造)のシーケンスです。
  • yは、 f TensorFlow演算をxに適用したTensor出力(のネスト構造)です。
  • grad_fn署名を持つ関数であるg(*grad_ys)のリストを返しTensor (平坦化)としての同じサイズx -の誘導体TensorにおけるS yに対してTensorにおけるS xgrad_ysは、(平坦化された) yと同じサイズのTensorのシーケンスであり、 yTensor初期値の勾配を保持します。

純粋な数学的意味では、ベクトル引数のベクトル値関数fの導関数は、そのヤコビ行列Jなければなりません。ここでは、ヤコビアンJを、関数grad_fnとして表現していますgrad_fnこれは、 Jがベクトルgrad_ysを左乗算したときに、どのように変換するかを定義します( grad_ys * J 、ベクトル-ヤコビアン積、またはVJP)。この行列の関数表現は、チェーンルールの計算(たとえば、逆伝播アルゴリズム)に使用すると便利です。

場合f使用Variable (入力の一部ではない)のを、すなわちスルーget_variable 、次いでgrad_fn署名有するべきであるg(*grad_ys, variables=None)variablesリストであるVariable Sを、2タプルを返します(grad_xs, grad_vars) 、ここでgrad_xsは上記と同じで、 grad_varsは変数に関するTensoryの導関数を含むlist<Tensor>です(つまり、grad_varsは変数の変数ごとに1つのTensorを持っています)。

f(x)[0]と同じ値を返し、その勾配( tf.gradientsによって計算さtf.gradients )がf(x)[1]によって決定される関数h(x)