【问题标题】:Why `tf.train.Optimizer().compute_gradients(loss)` also returns variables not in the subgraph of `loss`?为什么`tf.train.Optimizer().compute_gradients(loss)`也返回不在`loss`子图中的变量?
【发布时间】:2018-10-22 20:55:36
【问题描述】:

我正在手动收集 Multi-Tasking 模型的梯度统计信息,其 图表 的示意图如下所示:

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

我为每个损失定义了一个单独的优化器如下(实际代码很复杂,以下针对这个问题进行了简化):

# 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  # /

所以我希望优化器只包含应用它的分支的梯度计算操作(即第一个任务的分支)

实际结果

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 的可训练变量而不创建梯度他们的变量(所以返回的梯度变量是None)。

问题:这样的行为正常吗?

【问题讨论】:

    标签: tensorflow neural-network deep-learning backpropagation


    【解决方案1】:

    是的,因为compute_gradients() 相对于传递给var_list 参数的tf.Variable 对象列表计算loss 的梯度。如果未提供var_list,则该函数将针对GraphKeys.TRAINABLE_VARIABLES 集合中的所有变量计算梯度。此外,如果loss 不依赖于某些变量,则未定义loss 相对于这些变量的梯度,即返回None。根据您提供的代码,情况似乎是这样。

    如果您希望optimizer 仅计算某些变量的梯度,您应该列出这些变量并将其传递给compute_gradients() 的var_list 参数。

    【讨论】:

    • 或者如何通过subgraph_grads_and_vars = [(g,v) for g,v in grads_and_vars if g is not None]计算子图梯度列表
    猜你喜欢
    • 2019-01-13
    • 1970-01-01
    • 2020-02-23
    • 2017-12-12
    • 2019-04-03
    • 2021-08-28
    • 2018-12-27
    • 2021-10-22
    • 2021-10-22
    相关资源
    最近更新 更多