您可以专门为感兴趣的变量集创建一个tf.Saver,只要它们具有相同的名称,您就可以在另一个图表中恢复它们。您可以使用集合来存储这些变量,然后为集合创建保护程序:
TRANSFERABLE_VARIABLES = "transferable_variable"
# ...
my_var = tf.get_variable(...)
tf.add_to_collection(TRANSFERABLE_VARIABLES, my_var)
# ...
saver = tf.Saver(tf.get_collection(TRANSFERABLE_VARIABLES), ...)
这应该允许您在一个图表中调用save 并在另一个图表中调用restore 来传递权重。
如果您想避免将任何内容写入磁盘,那么我认为除了手动复制/粘贴值之外别无他法。但是,这也可以通过使用集合和完全相同的构造过程在相当程度上实现自动化:
model1_graph = create_model1()
model2_graph = create_model2()
with model1_graph.as_default(), tf.Session() as sess:
# Train...
# Retrieve learned weights
transferable_weights = sess.run(tf.get_collection(TRANSFERABLE_VARIABLES))
with model2_graph.as_default(), tf.Session() as sess:
# Load weights from the other model
for var, weight in zip(tf.get_collection(TRANSFERABLE_VARIABLES),
transferable_weights):
var.load(weight, sess)
# Continue training...
同样,这仅在公共层的构造相同时才有效,因为两个图的集合中变量的顺序应该相同。
更新:
如果您想确保恢复的变量不用于训练,您有几种可能,尽管它们可能都需要对您的代码进行更多更改。 trainable 变量只是包含在集合tf.GrapKeys.TRAINABLE_VARIABLES 中的变量,因此当您在第二个图中创建传输的变量时,您可以只说trainable=False,并且恢复过程应该相同。如果您想更加动态并自动执行,这或多或少是可能的,但请记住这一点:必须在创建优化器之前知道必须用于训练的变量列表,并且之后不能更改(不创建新的优化器)。知道了这一点,我认为没有任何解决方案不通过传递带有来自第一个图中的可转移变量的名称的列表。例如:
with model1_graph.as_default():
transferable_names = [v.name for v in tf.get_collection(TRANSFERABLE_VARIABLES)]
然后,在第二个图的构建过程中,在定义模型之后,就在创建优化器之前,您可以执行以下操作:
train_vars = [v for v in tf.get_collection(tf.GrapKeys.TRAINABLE_VARIABLES)
if v.name not in transferable_names]
# Assuming that `model2_graph` is the current default graph
tf.get_default_graph().clear_collection(tf.GrapKeys.TRAINABLE_VARIABLES)
for v in train_vars:
tf.add_to_collection(tf.GrapKeys.TRAINABLE_VARIABLES, v)
# Create the optimizer...
另一种选择是不修改集合tf.GrapKeys.TRAINABLE_VARIABLES,而是将要优化的变量列表(示例中为train_vars)作为参数var_list 传递给优化器的minimize 方法。原则上我个人不太喜欢这样,因为我认为集合的内容应该符合它们的语义目的(毕竟代码的其他部分可能将同一个集合用于其他目的),但这取决于我猜的情况。