Machine learning 有没有一种方法可以使用Tensorflow自动化迁移学习?

Machine learning 有没有一种方法可以使用Tensorflow自动化迁移学习?,machine-learning,tensorflow,Machine Learning,Tensorflow,我正在使用Tensorflow构建和训练几个神经网络。这些网络在相关任务(自然语言处理)上进行监督学习 我所有的神经网络之间的共同点是,它们共享一些早期的层(一些共享另外两层) 我希望能够分享从一个架构到初始化另一个架构的公共层的训练权重 我现在做事情的方式是,每次我想要传递权重时,我都要编写一段单独的(特别的)代码。这会使我的项目变得杂乱无章,而且很耗时 有没有人知道一种方法可以让我自动化重量转移的过程。例如,要自动检测公共层,则初始化相应的权重。您可以为感兴趣的变量集创建一个特定的权重,并且

我正在使用Tensorflow构建和训练几个神经网络。这些网络在相关任务(自然语言处理)上进行监督学习

我所有的神经网络之间的共同点是,它们共享一些早期的层(一些共享另外两层)

我希望能够分享从一个架构到初始化另一个架构的公共层的训练权重

我现在做事情的方式是,每次我想要传递权重时,我都要编写一段单独的(特别的)代码。这会使我的项目变得杂乱无章,而且很耗时

有没有人知道一种方法可以让我自动化重量转移的过程。例如,要自动检测公共层,则初始化相应的权重。

您可以为感兴趣的变量集创建一个特定的权重,并且您可以在另一个图形中还原这些变量,只要它们具有相同的名称。您可以使用集合存储这些变量,然后为集合创建保护程序:

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
变量只是包含在集合中的一个变量,因此当您在第二个图中创建传输的变量时,您可以说
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...
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.GrapKeys.TRAINABLE_VARIABLES
,而是将要优化的变量列表(
train_vars
)作为参数
var_list
传递给优化器的方法。原则上我个人不太喜欢这个,因为我认为集合的内容应该与其语义目的相匹配(毕竟,代码的其他部分可能会将同一集合用于其他目的),但这取决于我猜的情况。

您可以专门为感兴趣的变量集创建一个图形,并且您可以在另一个图形中恢复这些变量,只要它们具有相同的名称。您可以使用集合存储这些变量,然后为集合创建保护程序:

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
变量只是包含在集合中的一个变量,因此当您在第二个图中创建传输的变量时,您可以说
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...
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.GrapKeys.TRAINABLE_VARIABLES
,而是将要优化的变量列表(
train_vars
)作为参数
var_list
传递给优化器的方法。原则上我个人不太喜欢这个,因为我认为集合的内容应该与其语义目的相匹配(毕竟,代码的其他部分可能会将同一集合用于其他目的),但这取决于我猜的情况。

如果我理解正确,您已经保存了一些权重,希望能够在不同网络之间使用

初始化特定网络时,可以使用一个共享函数,该函数通过共享层构造计算图,并使用一个单独的函数