тензорный поток, пользовательские потери, custom_gradient, temp tf.Variable приводит к ошибке - PullRequest
0 голосов
/ 16 апреля 2020

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

Связывание связанной проблемы github, которая содержит минимальный рабочий пример (MWE) и дополнительную информацию об отладке: https://github.com/tensorflow/tensorflow/issues/31945

MWE здесь, скопируйте -пост из сообщения на github:

import tensorflow as tf
# from custom_gradient import custom_gradient  # my corrected version
from tensorflow import custom_gradient


def layer(t, name):
    var = tf.Variable(1.0, dtype=tf.float32, use_resource=True, name=name)
    return t * var


@custom_gradient
def custom_gradient_layer(t):
    result = layer(t, name='outside')

    def grad(*grad_ys, variables=None):
        assert variables is not None
        print(variables)
        grads = tf.gradients(
            layer(t, name='inside'),
            [t, *variables],
            grad_ys=grad_ys,
        )
        grads = (grads[:1], grads[1:])
        return grads

    return result, grad

Который будет выбрасывать ValueError: not enough values to unpack....

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

Итак, с одной входной переменной у нас будет одна оценка градиента. Здесь TF ожидает 2, хотя у нас есть только одна входная переменная из-за временной переменной, которая в некоторых случаях неизбежна.

Мой псевдокод MWE выглядит примерно так:

@tf.custom_gradient
def custom_loss(in):

    temp = tf.Variable(tf.zeros([2 * N - 1]), dtype = tf.float32)

    ## compute loss function
    ...

     def grad(df):
         grad = df * partial_derivative
         return grad

    return loss, grad

Andre

...