Spec-Zone.ru › TensorFlow 2.4

tf.custom_gradient

Просмотреть исходный код на GitHub

Декоратор для определения функции с пользовательским градиентом.

Просмотр псевдонимов

Псевдонимы для миграции

См. Руководство по миграции для получения дополнительных сведений.

tf.compat.v1.custom_gradient

tf.custom_gradient(
    f=None
)

Этот декоратор позволяет точно контролировать градиенты последовательности операций. Это может быть полезно по многим причинам, включая предоставление более эффективного или численно устойчивого градиента для последовательности операций.

Например, рассмотрим следующую функцию, которая часто встречается при вычислении кросс-энтропии и логарифмических правдоподобий:

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.

Переменная dy определяется как градиент из предыдущего уровня. То есть градиент из всех слоёв или функций, исходящих из данного слоя.

По правилу цепи мы знаем, что dy/dx = dy/x_0 * dx_0/dx_1 * ... * dx_i/dx_i+1 * ... * dx_n/dx

В этом случае градиент нашей текущей функции определяется как dx_i/dx_i+1 = (1 - 1 / (1 + e)). Градиент из предыдущего уровня dy будет dx_i+1/dx_i+2 * dx_i+2/dx_i+3 * ... * dx_n/dx. Затем произведение градиента из предыдущего уровня и текущего градиента передаётся на следующий уровень.

В случае, если функция принимает несколько переменных в качестве входных данных, функция grad также должна возвращать то же количество переменных. Рассмотрим пример функции z = x * y.

@tf.custom_gradient
def bar(x, y):
  def grad(upstream):
    dz_dx = y
    dz_dy = x
    return upstream * dz_dx, upstream * dz_dy
  z = x * y
  return z, grad
x = tf.constant(2.0, dtype=tf.float32)
y = tf.constant(3.0, dtype=tf.float32)
with tf.GradientTape(persistent=True) as tape:
  tape.watch(x)
  tape.watch(y)
  z = bar(x, y)
z
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>
tape.gradient(z, x)
<tf.Tensor: shape=(), dtype=float32, numpy=3.0>
tape.gradient(z, y)
<tf.Tensor: shape=(), dtype=float32, numpy=2.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 будет вычислять градиент первого порядка от grad_fn относительно dy, который используется для генерации графов градиента по прямой из графов градиента по обратной связи, но не совпадает со вторым порядком градиента от op относительно x.

Вместо этого оберните вложенные @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 контролируют ожидаемые значения возвращаемых данных внутренней функции.

См. также tf.RegisterGradient, которая регистрирует функцию градиента для примитивной операции TensorFlow. tf.custom_gradient, с другой стороны, позволяет точно контролировать вычисление градиента последовательности операций.

Обратите внимание, что если декорированная функция использует Variableы, то окружающий контекст переменных должен использовать ResourceVariableы.

Аргументы
f функция f(*x), которая возвращает кортеж (y, grad_fn) , где:
  • x — последовательность (вложенных структур) Tensor входных данных функции.
  • y — (вложенная структура) Tensor выходные данные применения операций TensorFlow в f к x.
  • grad_fn — функция с сигнатурой g(*grad_ys) , которая возвращает список Tensor такой же длины, как (сглаженные) x — производные Tensor в y относительно Tensor в x. grad_ys — последовательность Tensor такой же длины, как (сглаженные) y, содержащие начальные значения градиентов для каждой Tensor в y.

В чисто математическом смысле производные функции f с вектором-аргументом и вектором-значением должны быть ее матрицей Якоби J. Здесь мы представляем матрицу Якоби J как функцию grad_fn, которая определяет, как J преобразует вектор grad_ys при левом умножении на него (grad_ys * J, произведение вектора и матрицы Якоби, или VJP). Это функциональное представление матрицы удобно использовать для вычисления правила цепи (например, в алгоритме обратного распространения).

Если f использует Variableы (которые не являются частью входных данных), то есть через get_variable, то grad_fn должна иметь сигнатуру g(*grad_ys, variables=None), где variables — список Variableов, а возвращает кортеж из 2 элементов (grad_xs, grad_vars), где grad_xs — то же самое, что и выше, а grad_vars — list<Tensor> с производными Tensorов в y относительно переменных (то есть grad_vars содержит по одному тензору на каждую переменную в переменных).

Возвращает
Функция h(x) , которая возвращает то же значение, что и f(x)[0] , а ее градиент (вычисленный с помощью tf.gradients) определяется f(x)[1].

© 2020 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 3.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/versions/r2.4/api_docs/python/tf/custom_gradient

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API