我正在使用Tensorflow建立和训练几个神经网络。这些,网络正在对相关任务(自然语言处理)进行监督学习。
我所有的神经网络之间的共同之处是,它们共享一些早期的层次(有些共享,另一些共享更多)。
我希望能够从一个体系结构中共享经过训练的公共层权重,从而初始化另一个体系结构。
我现在做事情的方式是,每次我想转移权重时,我都在编写一段单独的(临时的)代码。这扰乱了我的项目,而且很费时。
有没有人知道有一种方法可以让我自动完成重量转移的过程。例如,假设要自动检测公共层,然后初始化相应的权重。
发布于 2017-08-08 13:29:16
您可以专门为感兴趣的变量集创建一个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方法。原则上,我个人不太喜欢这一点,因为我认为集合的内容应该与它们的语义目的相匹配(毕竟,代码的其他部分可能将相同的集合用于其他目的),但这取决于我猜的情况。
发布于 2017-08-08 13:37:20
如果我正确理解,您已经保存了一些权重,您希望能够在不同的网络之间使用。
当初始化一个特定的网络时,您可以使用一个共享函数,它通过共享层构造计算图,并且在训练前有一个单独的函数来加载权重。
我通常有一个专门用于构造图的模块,它具有不同的功能来构建每个部分,即
def build_graph():
with tf.Graph().as_default() as graph:
build_shared_layers()
build_other_layers()
build_training_ops()
return graphbuild_shared_layers()函数将设置在所有网络之间共享的变量和操作,但是使用trainable=False标志(我假设您在某个地方为这些层保存了权重)。您还将为变量提供名称,以便在加载函数中进行稍后的引用。
然后,在训练一个新的网络之前,只需使用一个var_list加载权重。您可以为此使用图形集合:
tf.add_to_collection('var_list', some_var)
tf.add_to_collection('var_list', another_var)然后,只需获取集合,并有一个函数来执行如下操作:
def load_existing_weights(sess, path, var_list):
saver = tf.train.Saver(var_list=var_list)
ckpt = tf.train.get_checkpoint_state(path)
saver.restore(sess, ckpt.model_checkpoint_path)
...
...
with tf.Session(graph=graph) as sess:
load_existing_weights(sess, FLAGS.save_path, var_list)
# get on with the training below...编辑:意识到我忘了添加文档链接.如另一个答案所示,请查看tf.train.Saver,特别是var_list参数。
https://stackoverflow.com/questions/45569330
复制相似问题