【问题标题】:Tensorflow: Using weights trained in one model inside another, different modelTensorflow:在另一个不同的模型中使用在一个模型中训练的权重
【发布时间】:2016-12-28 08:46:33
【问题描述】:

我正在尝试使用小批量在 Tensorflow 中训练 LSTM,但在训练完成后,我想通过一次提交一个示例来使用该模型。我可以在 Tensorflow 中设置图表来训练我的 LSTM 网络,但之后我无法以我想要的方式使用训练后的结果。

设置代码如下所示:

#Build the LSTM model.
cellRaw = rnn_cell.BasicLSTMCell(LAYER_SIZE)
cellRaw = rnn_cell.MultiRNNCell([cellRaw] * NUM_LAYERS)

cell = rnn_cell.DropoutWrapper(cellRaw, output_keep_prob = 0.25)

input_data  = tf.placeholder(dtype=tf.float32, shape=[SEQ_LENGTH, None, 3])
target_data = tf.placeholder(dtype=tf.float32, shape=[SEQ_LENGTH, None])
initial_state = cell.zero_state(batch_size=BATCH_SIZE, dtype=tf.float32)

with tf.variable_scope('rnnlm'):
    output_w = tf.get_variable("output_w", [LAYER_SIZE, 6])
    output_b = tf.get_variable("output_b", [6])

outputs, final_state = seq2seq.rnn_decoder(input_list, initial_state, cell, loop_function=None, scope='rnnlm')
output = tf.reshape(tf.concat(1, outputs), [-1, LAYER_SIZE])
output = tf.nn.xw_plus_b(output, output_w, output_b)

...注意两个占位符,input_data 和 target_data。我没有打扰包括优化器设置。训练完成并结束训练后,我想设置一个新的会话,使用经过训练的 LSTM 网络,其输入由完全不同的占位符提供,例如:

with tf.Session() as sess:
with tf.variable_scope("simulation", reuse=None):
    cellSim = cellRaw
    input_data_sim  = tf.placeholder(dtype=tf.float32, shape=[1, 1, 3])
    initial_state_sim = cell.zero_state(batch_size=1, dtype=tf.float32)
    input_list_sim = tf.unpack(input_data_sim)

    outputsSim, final_state_sim = seq2seq.rnn_decoder(input_list_sim, initial_state_sim, cellSim, loop_function=None, scope='rnnlm')
    outputSim = tf.reshape(tf.concat(1, outputsSim), [-1, LAYER_SIZE])

    with tf.variable_scope('rnnlm'):
        output_w = tf.get_variable("output_w", [LAYER_SIZE, nOut])
        output_b = tf.get_variable("output_b", [nOut])

    outputSim = tf.nn.xw_plus_b(outputSim, output_w, output_b)

第二部分返回以下错误:

tensorflow.python.framework.errors.InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder' with dtype float
 [[Node: Placeholder = Placeholder[dtype=DT_FLOAT, shape=[], _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

...大概是因为我正在使用的图表仍然将旧的训练占位符附加到经过训练的 LSTM 节点上。什么是“提取”经过训练的 LSTM 并将其放入具有不同输入风格的新的不同图表的正确方法? Tensorflow 的变量范围功能似乎解决了这样的问题,但是示例in the documentation 都在讨论使用变量范围作为管理变量名称的一种方式,以便同一段代码将在同一图中生成类似的子图。 “重用”功能似乎接近我想要的,但我发现上面链接的 Tensorflow 文档根本不清楚它的作用。不能给单元格本身命名(换句话说,

cellRaw = rnn_cell.MultiRNNCell([cellRaw] * NUM_LAYERS, name="multicell")

无效),虽然我可以为 seq2seq.rnn_decoder() 命名,但如果我未更改地使用该节点,我可能无法删除 rnn_cell.DropoutWrapper()。

问题:

将经过训练的 LSTM 权重从一张图移动到另一张图的正确方法是什么?

说启动一个新会话“释放资源”,但不会擦除内存中的图形是否正确?

在我看来,“重用”功能允许 Tensorflow 在当前变量范围之外搜索具有相同名称(存在于不同范围内)的变量,并在当前范围内使用它们。它是否正确?如果是,链接到该变量的非当前范围内的所有图边会发生什么情况?如果不是,如果您尝试在两个不同的范围内使用相同的变量名,为什么 Tensorflow 会抛出错误?在两个不同的范围内定义两个具有相同名称的变量似乎是完全合理的,例如conv1/sum1 和 conv2/sum1。

在我的代码中,我在一个新的范围内工作,但是如果没有数据从初始默认范围输入到占位符中,该图表将无法运行。出于某种原因,默认范围是否始终“在范围内”?

如果图边可以跨越不同的范围,并且不同范围内的名称不能共享,除非它们引用完全相同的节点,那么这似乎违背了首先具有不同范围的目的。我在这里误会了什么?

谢谢!

【问题讨论】:

    标签: python tensorflow lstm


    【解决方案1】:

    将经过训练的 LSTM 权重从一张图移动到另一张图的正确方法是什么?

    您可以先创建解码图(使用 saver 对象保存参数),然后创建一个 GraphDef 对象,您可以将其导入更大的训练图中:

    basegraph = tf.Graph()
    with basegraph.as_default():
       ***your graph***
    
    traingraph = tf.Graph()
    with traingraph.as_default():
         tf.import_graph_def(basegraph.as_graph_def())
         ***your training graph***
    

    确保在为新图表启动会话时加载变量。

    我没有使用此功能的经验,因此您可能需要进一步研究一下

    是否可以说开始一个新会话“释放资源”,但不会擦除内存中的图形?

    是的,图形对象仍然持有它

    在我看来,“重用”功能允许 Tensorflow 在当前变量范围之外搜索具有相同名称(存在于不同范围内)的变量,并在当前范围内使用它们。它是否正确?如果是,链接到该变量的非当前范围内的所有图边会发生什么情况?如果不是,如果您尝试在两个不同的范围内使用相同的变量名,为什么 Tensorflow 会抛出错误?在两个不同的范围内定义两个具有相同名称的变量似乎是完全合理的,例如conv1/sum1 和 conv2/sum1。

    不,重用是确定当您在现有名称上使用 get_variable 时的行为,当它为 true 时将返回现有变量,否则将返回一个新变量。通常 tensorflow 不应该抛出错误。您确定您使用的是 tf.get_variable 而不仅仅是 tf.Variable?

    在我的代码中,我在一个新的范围内工作,但是如果没有数据从初始默认范围输入到占位符中,图表将无法运行。出于某种原因,默认范围是否始终处于“范围内”?

    我真的不明白你的意思。并不总是必须使用。如果运行操作不需要占位符,则不必定义它。

    如果图边可以跨越不同的范围,并且不同范围内的名称不能共享,除非它们引用完全相同的节点,那么这似乎违背了首先具有不同范围的目的。我在这里有什么误解?

    我认为您对作用域的理解或使用存在缺陷,见上文

    【讨论】:

    • re:倒数第二个问题:我正在尝试训练一个模型,然后在同一个 Python 脚本中重用它。我根本没有使用 Saver。当我尝试重用模型时,Tensorflow 会抱怨,因为我没有提供特定于训练的占位符。它们不需要重复使用,但它们仍然存在于图表中。
    • 回复:第一个问题:如果我必须更改输入占位符,此解决方案将如何工作?我正在小批量训练,但在没有小批量的情况下重新使用模型,这似乎没有机会改变输入尺寸。
    • Re:倒数第三个问题:事实证明,MultiRNNCell 是一个包装器,它创建的节点与包装器对象本身不同。是否有任何地方记录了如何保存和恢复这种对象/节点集合?恢复后节点上发生的边缘会发生什么?当在新范围内调用 tf.get_variable() 时,节点上的边会发生什么?在此操作期间,reuse=true 是否会改变边和节点之间的任何关系?我找不到解决这些问题的具体文档。
    • re:倒数第二个问题:我正在尝试训练一个模型,然后在同一个 Python 脚本中重用它。我根本没有使用 Saver。当我尝试重用模型时,Tensorflow 会抱怨,因为我没有提供特定于训练的占位符。它们不是重复使用所必需的,但它们仍然存在于图表中如果您在没有保护程序的情况下重复使用模型,则无法关闭会话,因为变量的值将会丢失。因此,如果没有 Tensorflow 抱怨变量尚未初始化,我真的看不出解码如何工作......
    • @VincentRenkens:这种方法(您在答案中概述的方法)是在 TensorFlow 中执行迁移学习的正确方法吗?也就是我把basegraph中原始模型的源码,在上面加载预训练的权重,加上自己的ops,然后end to end训练模型?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2018-07-28
    • 1970-01-01
    相关资源
    最近更新 更多