Tensorflow将LSTM的最终状态保存为动态预测

2024-04-26 21:15:45 发布

您现在位置:Python中文网/ 问答频道 /正文

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

在培训期间,我总是将最终的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)

培训期间:

^{pr2}$

当我以后从检查点恢复模型时,最终状态也不会恢复。正如this post中概述的那样,问题是保存程序不知道新状态。这篇文章还提出了一个基于tf.assign的解决方案。很遗憾,我不能使用建议的

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

因为自我初始化状态不是变量,而是占位符。我知道错误了

AttributeError:“Tensor”对象没有属性“assign”

我已经试着解决这个问题好几个小时了,但我还是不能使它起作用。在

感谢任何帮助!在

编辑:

我变了自我初始化状态到

            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)

在训练期间,我不给自我初始化状态以下内容:

            _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:传递给操作“Assign”的参数“value”时应为float32,但得到的是LSTMStateTuple(c=array([[0.07291573,-0.06366599,-0.23425588,…,0.05307654


Tags: selflayerinit状态layerstfliststate
1条回答
网友
1楼 · 发布于 2024-04-26 21:15:45

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

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

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

看起来您使用的是BasicLSTMCell,与state_is_tuple=True。我之前提到的讨论使用了GRUCell和{}。两者之间的细节有所不同,但总体方法可能相似,因此希望这对您有用:

在训练过程中,首先将0作为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。用cd4{3}来适应。它是可行的,但不如最初的方法准确。我还不知道是因为对我来说GRU比LSTM好还是其他原因。看看这个对你有用吗。。。在

还要记住,正如您在恢复和预测代码中看到的那样,您的预测很可能基于与训练循环不同的批大小(我猜批为1?)所以你必须考虑如何处理你的恢复状态,就拿最后一批?还是别的什么?这段代码只获取保存状态的最后一层(即,培训中最近的观察结果),因为这与我相关。。。在

相关问题 更多 >