TensorFlow复制变量但不可训练以预训练下一层。

3

我想实现自编码器(确切地说是堆叠卷积自编码器)

在这里,我想先预训练每一层,然后进行微调

所以我为每层的权重创建了变量

例如,第一层的 W_1 = tf.Variable(initial_value, name,trainable=True 等)

我已经预训练了第一层的 W_1

接下来我想预训练第二层的权重 (W_2)

这里我应该使用 W_1 来计算第二层的输入。

但是 W_1 是可训练的,因此如果我直接使用 W_1,则 tensorflow 可能会一并训练 W_1。

因此,我应该创建 W_1_out,它保留了 W_1 的值,但不可训练

说实话,我尝试修改了这个网站的代码

https://github.com/cmgreen210/TensorFlowDeepAutoencoder/blob/master/code/ae/autoencoder.py

在第102行,它通过以下代码创建变量

self[name_w + "_fixed"] = tf.Variable(tf.identity(self[name_w]),
                                            name=name_w + "_fixed",
                                            trainable=False)

然而,它调用错误是因为它使用了未初始化的值。

我应该怎么做才能复制变量但使其不可训练以预训练下一层?


请查看以下链接:enter link description here - educob
1个回答

3

不确定是否仍然相关,但我会尝试。

通常,在这种情况下,我会执行以下操作:

  • 根据您正在构建的模型填充(默认)图形,例如对于第一次训练步骤,只需创建您提到的第一个卷积层W1。当您训练第一层时,可以在训练完成后存储保存的模型,然后重新加载它并添加所需的第二层W2操作。或者您可以直接在代码中从头开始构建整个W1图形,然后添加W2操作。

  • 如果您使用Tensorflow提供的恢复机制,则具有W1权重的优势已经是预先训练的权重。如果您不使用恢复机制,则必须手动设置W1权重,例如通过在下面的片段中显示的内容执行某些操作。

  • 然后,当您设置训练操作时,可以将变量列表作为var_list传递给优化器,该列表明确告诉优化器要更新哪些参数以最小化损失。如果将其设置为None(默认值),则仅使用tf.trainable_variables()中可以找到的内容,这反过来是所有可训练的tf.Variables的集合。也可以查看答案,该答案基本上说了同样的事情。
  • 在使用var_list参数时,图形集合非常方便。例如,您可以为要训练的每个层创建单独的图形集合。集合将包含每个层的可训练变量,然后您可以非常轻松地检索所需的集合并将其作为var_list参数传递(请参见下面的示例和/或上面链接的文档中的备注)。

如何覆盖变量的值:name是要覆盖的变量的名称,value是适当大小和类型的数组,sess是会话:

variable = tf.get_default_graph().get_tensor_by_name(name)
sess.run(tf.assign(variable, value))

请注意,name在结尾需要额外添加:0。例如,如果您的层权重被称为'weights1',则示例中的name应为'weights1:0'将张量添加到自定义集合中:请使用以下方式之一:
tf.add_to_collection('layer1_tensors', weights1)
tf.add_to_collection('layer1_tensors', some_other_trainable_variable)

请注意,第一行创建了一个集合,因为它还不存在,第二行将给定的张量添加到现有的集合中。
如何使用自定义集合:现在您可以像这样做:
# loss = some tensorflow op computing the loss
var_list = tf.get_collection_ref('layer1_tensors')
optim = tf.train.AdamOptimizer().minimize(loss=loss, var_list=var_list)

您也可以使用tf.get_collection('layer_tensors'),这将返回集合的副本。
当然,如果您不想执行任何操作,您可以在创建图形时对所有不希望可训练的变量使用trainable=False,就像您在问题中暗示的那样。但是,我不太喜欢这个选项,因为它要求您将布尔值传递到填充图形的函数中,这很容易被忽视,因此容易出错。而且,即使您决定这样做,您仍然需要手动恢复不可训练的变量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接