【问题标题】:Tensorflow save final state of LSTM in dynamic_rnn for predictionTensorflow 将 LSTM 的最终状态保存在 dynamic_rnn 中用于预测
【发布时间】:2017-12-25 19:51:06
【问题描述】:

我想保存我的 LSTM 的最终状态,以便在我恢复模型时包含它并可用于预测。如下所述,当我使用tf.assign 时,Saver 只知道最终状态。但是,这会引发错误(也在下面解释)。

在训练期间,我总是将最终的 LSTM 状态反馈回网络,如 this post 中所述。以下是代码的重要部分:

构建图表时:

            self.init_state = tf.placeholder(tf.float32, [
                self.n_layers, 2, self.batch_size, self.n_hidden
            ])

            state_per_layer_list = tf.unstack(self.init_state, axis=0)

            rnn_tuple_state = tuple([
                tf.contrib.rnn.LSTMStateTuple(state_per_layer_list[idx][0],
                                              state_per_layer_list[idx][1])

                for idx in range(self.n_layers)
            ])

            outputs, self.final_state = tf.nn.dynamic_rnn(
                cell, inputs=self.inputs, initial_state=rnn_tuple_state)

在训练期间:

        _current_state = np.zeros((self.n_layers, 2, self.batch_size,
                                   self.n_hidden))

            _train_step, _current_state, _loss, _acc, summary = self.sess.run(
                [
                    self.train_step, self.final_state,
                    self.merged
                ],
                feed_dict={self.inputs: _inputs,
                           self.labels:_labels, 
                           self.init_state: _current_state})

当我稍后从检查点恢复我的模型时,最终状态也没有恢复。正如this post 中所述,问题在于 Saver 不知道新状态。该帖子还提出了一个基于tf.assign 的解决方案。很遗憾,我不能使用建议的

            assign_op = tf.assign(self.init_state, _current_state)
            self.sess.run(assign_op)

因为 self.init 状态不是变量而是占位符。我收到错误

AttributeError: 'Tensor' 对象没有属性 'assign'

我已经尝试解决这个问题几个小时了,但我无法让它工作。

感谢任何帮助!

编辑:

我已将 self.init_state 更改为

            self.init_state = tf.get_variable('saved_state', shape=
            [self.n_layers, 2, self.batch_size, self.n_hidden])

            state_per_layer_list = tf.unstack(self.init_state, axis=0)

            rnn_tuple_state = tuple([
                tf.contrib.rnn.LSTMStateTuple(state_per_layer_list[idx][0],
                                              state_per_layer_list[idx][1])

                for idx in range(self.n_layers)
            ])

            outputs, self.final_state = tf.nn.dynamic_rnn(
                cell, inputs=self.inputs, initial_state=rnn_tuple_state)

在训练期间,我没有为 self.init_state 提供值:

            _train_step, _current_state, _loss, _acc, summary = self.sess.run(
                [
                    self.train_step, self.final_state,
                    self.merged
                ],
                feed_dict={self.inputs: _inputs,
                           self.labels:_labels})

但是,我仍然无法运行分配操作。知道我得到了

TypeError:预期的 float32 传递给 op 'Assign' 的参数 'value',得到 (LSTMStateTuple(c=array([[ 0.07291573, -0.06366599, -0.23425588, ..., 0.05307654,

【问题讨论】:

  • 您的问题真的看起来像您链接的问题的副本。接受的答案确实建议您将占位符转换为 tf.Variable,以便您可以使用 TensorFlow 分配操作更新网络中的状态。
  • 是的,我试过了。也许我在转换它时犯了一个错误。如何正确将其转换为 tf.Variable?使用 self.init_state = tf.Variable(self.init_state) 初始化所有变量时会抛出错误
  • 我改变了原来的问题(见编辑)。它仍然无法按照其他帖子中解释的方式工作。我错过了什么吗?

标签: python machine-learning tensorflow lstm rnn


【解决方案1】:

为了保存最终状态,您可以创建一个单独的 TF 变量,然后在保存图形之前,运行 assign 操作以将您的最新状态分配给该变量,然后保存图形。您唯一需要记住的是在声明 Saver 之前声明该变量;否则它不会被包含在图表中。

这里对此进行了详细讨论,包括工作代码: TF LSTM: Save State from training session for prediction session later

*** 更新:后续问题的答案:

您似乎正在使用BasicLSTMCell,以及state_is_tuple=True。我之前提到的讨论使用了GRUCellstate_is_tuple=False。两者之间的细节有些不同,但总体方法可能相似,因此希望这对您有用:

在训练期间,您首先将零作为initial_state 输入到dynamic_rnn,然后继续将其自己的输出作为initial_state 的输入重新输入。因此,我们的dynamic_rnn 调用的最后输出状态是您要保存以供以后使用的状态。由于它是由 sess.run() 调用产生的,因此它本质上是一个 numpy 数组(不是张量,也不是占位符)。所以问题相当于“我如何将一个 numpy 数组与图中的其他变量一起保存为 Tensorflow 变量。”这就是为什么您将最终状态分配给一个仅用于此目的的变量。

所以,代码是这样的:

    # GRAPH DEFINITIONS:
    state_in = tf.placeholder(tf.float32, [LAYERS, 2, None, CELL_SIZE], name='state_in')
    l = tf.unstack(state_in, axis=0)
    state_tup = tuple(
        [tf.nn.rnn_cell.LSTMStateTuple(l[idx][0], l[idx][1])
        for idx in range(NLAYERS)])
    #multicell = your BasicLSTMCell / MultiRNN definitions
    output, state_out = tf.nn.dynamic_rnn(multicell, X, dtype=tf.float32, initial_state=state_tup)

    savedState = tf.get_variable('savedState', shape=[LAYERS, 2, BATCHSIZE, CELL_SIZE])
    saver = tf.train.Saver(max_to_keep=1)

    in_state = np.zeros((LAYERS, 2, BATCHSIZE, CELL_SIZE))

    # TRAINING LOOP:
    feed_dict = {X: x, Y_: y_, batchsize: BATCHSIZE, state_in:in_state}
    _, out_state = sess.run([training_step, state_out], feed_dict=feed_dict)
    in_state = out_state

    # ONCE TRAINING IS OVER:
    assignOp = tf.assign(savedState, out_state)
    sess.run(assignOp)
    saver.save(sess, pathModel + '/my_model.ckpt')

    # RECOVERING IN A DIFFERENT PROGRAM:

    gInit = tf.global_variables_initializer().run()
    lInit = tf.local_variables_initializer().run()
    new_saver = tf.train.import_meta_graph(pathModel + 'my_model.ckpt.meta')
    new_saver.restore(sess, pathModel + 'my_model.ckpt')
    # retrieve State and get its LAST batch (latest obervarions)
    savedState = sess.run('savedState:0') # this is FULL state from training
    state = savedState[:,:,-1,:]  # -1 gets only the LAST batch of the state (latest seen observations)
    state = np.reshape(state, [state.shape[0], 2, -1, state.shape[2]]) #[LAYERS, 2, 1 (BATCH), SELL_SIZE]
    #x = .... (YOUR INPUTS)
    feed_dict = {'X:0': x, 'state_in:0':state}
    #PREDICTION LOOP:
    preds, state = sess.run(['preds:0', 'state_out:0'], feed_dict = feed_dict)
    # so now state will be re-fed into feed_dict with the next loop iteration

如前所述,这是对GRUCell(其中state_is_tuple = False)适用的改进方法。我对其进行了调整以尝试使用BasicLSTMCellstate_is_tuple=True。它有效,但不如原始方法准确。我还不知道这是否只是因为对我来说 GRU 比 LSTM 好还是出于其他原因。看看这是否适合你...

另外请记住,正如您在恢复和预测代码中看到的那样,您的预测可能基于与训练循环不同的批次大小(我猜是 1 批次?)所以您必须考虑如何处理你恢复的状态——只取最后一批?或者是其他东西?此代码仅采用已保存状态的最后一层(即训练中的最新观察结果),因为这与我相关...

【讨论】:

  • 是的。我已经看到了该讨论并在我的帖子中提供了链接。但是,提供的代码遗漏了主要部分,这就是它没有帮助的原因。如果我理解正确,您帖子中的“savedState”变量仅用于在每个时期为其分配最新的 LSTM 状态?但是你如何在训练期间输入 lstm 状态呢?您是否使用如上所述的占位符?在您的帖子中,从未完全指定“feed dict”。
  • 另外,恢复变量的代码也不清楚。您运行 sess.run('savedState:0') 以获得训练中的最终 lstm 状态。但是你如何将这些信息输入网络呢?它被赋予了哪个变量或占位符?
  • Apols .. 您的问题询问如何保存 FINAL 状态以进行预测,所以我假设您对之前的所有操作都很好。我会在几秒钟内更新我的答案..
  • 谢谢,我会尝试为我正在使用的 contrib.rnn.LSTMCell 调整代码!
猜你喜欢
  • 2018-06-22
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多