注意:这个答案和OP's answer 是相辅相成的。请先阅读OP's answer。
我今天在这个问题上花了 4 个小时。这是 TensorFlow 丑陋的地方之一(这就是为什么你应该使用 PyTorch 如果你喜欢图形操作)。
这里的关键点是:tf.Variable 不是图形元素(更多关于它的here),而是围绕 3 个操作的包装器:Assign 操作,Read op 和VariableV2 op 本质上是ref tensor(更多关于它here)。因此,您需要在 TensorFlow 框架中显式调用它。
如果我们仔细查看graph_editor 的代码,尤其是transform module,我们可以看到它只在tf.Graph 上运行,而不涉及TensorFlow 框架中的任何内容。因此,graph_editor.copy(和类似的)方法根本不会触及tf.Variable 对象。它只复制构成tf.Variable 构建块的张量和操作。
好的,那我们如何解决这个问题呢?
假设你有以下变量:
var = tf.get_trainable_variables()[0]
print(var.to_proto())
# variable_name: "dense_1/kernel:0"
# initializer_name: "dense_1/kernel/Assign"
# snapshot_name: "dense_1/kernel/read:0"
# initial_value_name: "dense_1/random_uniform:0"
# trainable: true
您知道在graph_editor.copy(...) 之后,您的dense_1 名称范围现在是dense_1b。然后,您只需使用info.transformed(...) 获取相应的操作和张量,然后执行以下操作:
from tensorflow.core.framework import variable_pb2
var_def = variable_pb2.VariableDef()
var_def.variable_name = 'dense_1b/kernel:0'
var_def.initializer_name = "dense_1b/kernel/Assign"
var_def.snapshot_name = "dense_1b/kernel/read:0"
var_def.initial_value_name = "dense_1/random_uniform:0"
var_def.trainable = True
现在,我想强调tf.Variable documentation的以下部分:
variable_def: ... 使用其内容重新创建变量对象,引用图中必须已经存在的变量节点。图表没有改变。
因此,tf.Variable 构造函数允许我们在现有的图形元素之上创建一个变量包装器。这正是我们所需要的:
cloned_var = tf.Variable(variable_def=var_def)
tf.add_to_collection(tf.GraphKeys.GLOBAL_VARIABLES, cloned_var)
解决了!
我使这个答案尽可能简单和具体,以展示tf.Variables 的基本机制。您现在可以轻松实现更一般情况下的代码以自动生成新变量。
PS:我讨厌 TensorFlow!