Почему `tf.train.Optimizer (). Compute_gradients (loss)` также возвращает переменные, которых нет в подграфе `loss`? - PullRequest
0 голосов
/ 22 октября 2018

Я вручную собираю статистику градиентов модели Multi-Tasking , график которой схематически выглядит следующим образом:

input -> [body_var1 ... body_varN] --> [task1_var1 ... task1_varM] <-- loss_1
                                   \-> [task2_var1 ... task2_varM] <-- loss_2

I 'Определение отдельного оптимизатора для каждой потери следующим образом (фактический код значительно сложнее, для этого вопроса упрощено следующее):

# for simplicity, just demonstrate the case with the 1st task
task_index = 1

# here we define the optimizer (create an instance in graph)
loss = losses[task_index]
optimizer = tf.train.GradientDescentOptimizer()
grads_and_vars = optimizer.compute_gradients(loss)

# now let's see what it returns
for g, v in grads_and_vars:
    print('  grad:', g, ', var:', v)

Итак, приведенный выше код явно создает отдельный оптимизатор только для ветвизадачи 1, затем мы создаем операции вычисления градиента с optimizer.compute_gradients(loss) и печатаем переменные, к которым мы применяем градиенты.

Ожидаемые результаты :

grad: body_var1_grad, var: body_var1    # \
...                                     # --> body vars and gradients
grad: body_varN_grad, var: body_varN    # /
grad: task1_var1_grad, var: task1_var1  # \
...                                     # --> task 1 vars and gradients
grad: task1_var1_grad, var: task1_var1  # /

Так что я ожидаю, что оптимизатор содержит только операции градиентного вычисления для ветви, к которой он был применен (т. Е. Ветви для 1-й задачи)

Фактические результаты

grad: body_var1_grad, var: body_var1    # \
...                                     # --> body vars and gradients
grad: body_varN_grad, var: body_varN    # /
grad: task1_var1_grad, var: task1_var1  # \
...                                     # --> task 1 vars and gradients
grad: task1_var1_grad, var: task1_var1  # /
grad: None, var: task2_var1             # \
...                                     # --> task 2 vars, with None gradients
grad: None, var: task2_var1             # /

Таким образом, похоже, что optimizer.compute_gradients(loss) захватывает не только подграф, который выводит в loss (который может быть извлечен с помощью tf.graph_util.extract_sub_graph), но также и все обучаемые переменные, которые связаны с loss без креатинаg переменная градиента для них (поэтому возвращаемые переменные градиента None).

Вопрос: нормально ли такое поведение?

1 Ответ

0 голосов
/ 23 октября 2018

Да, это так, потому что compute_gradients () вычисляет градиенты loss относительно списка tf.Variable объектов, который передается параметру var_list.Если var_list не указано, функция вычисляет градиенты по всем переменным из коллекции GraphKeys.TRAINABLE_VARIABLES .Кроме того, если loss не зависит от определенных переменных, градиенты loss относительно этих переменных не определены, то есть возвращается None.Судя по предоставленному вами коду, похоже, это так.

Если вы хотите, чтобы optimizer вычислял градиенты только по определенным переменным, вы должны составить список таких переменных и передать егоvar_list параметр compute_gradients().

...