为TensorFlow中的LSTM创建可训练初始状态

为TensorFlow中的LSTM创建可训练初始状态,tensorflow,lstm,recurrent-neural-network,Tensorflow,Lstm,Recurrent Neural Network,我有一个序列太长,无法放入内存中,但初始状态非常关键,所以我也想将其训练为一个变量。如何训练初始状态变量在序列开始时传入,但在序列的其余部分继续使用输出状态 到目前为止,我得到的是: cell = tf.contrib.rnn.BasicLSTMCell(num_lstm_cells, state_is_tuple=True) init_vars = cell.zero_state(batch_size, tf.float32) init_c = tf.Variable

我有一个序列太长,无法放入内存中,但初始状态非常关键,所以我也想将其训练为一个变量。如何训练初始状态变量在序列开始时传入,但在序列的其余部分继续使用输出状态

到目前为止,我得到的是:

    cell = tf.contrib.rnn.BasicLSTMCell(num_lstm_cells, state_is_tuple=True)

    init_vars = cell.zero_state(batch_size, tf.float32)
    init_c = tf.Variable(init_vars.c, trainable=True)
    init_h = tf.Variable(init_vars.h, trainable=True)
    init_state = tf.contrib.rnn.LSTMStateTuple(init_c, init_h)

    state_vars = cell.zero_state(batch_size, tf.float32)
    state_c = tf.Variable(state_vars.c, trainable=False)
    state_h = tf.Variable(state_vars.h, trainable=False)
    state = tf.contrib.rnn.LSTMStateTuple(state_c, state_h)

    layer = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=0.7)
    val, new_state = tf.nn.dynamic_rnn(layer, lstm_input, initial_state=state, dtype=tf.float32)

    with tf.control_dependencies([state[0].assign(new_state[0]), state[1].assign(new_state[1])]):
        output = tf.identity(val)

    inititalise_c = tf.assign(state[0], init_state[0])
    inititalise_h = tf.assign(state[1], init_state[1])
    initialise_state = tf.group([inititalise_c, inititalise_h])
我的想法是,我有一个可训练的初始状态变量(init_vars)和一个不可训练的状态(state_vars),我通过调用
initialise_state
op,在每个序列的开头将初始状态分配给它

我不认为这会起作用,因为init_状态实际上不是培训的一部分,它只是用于复制。我该怎么做


编辑:我已在测试中确认初始状态未被训练,并且保持所有0

如何在训练网络和初始状态之间切换?冻结模型,使初始状态可训练,训练一段时间。然后切换冻结状态。

我不确定您想做什么,但是,为什么不将新的状态分配给另一个状态变量,如下所示

batch_size = 10
num_lstm_cells = 20
num_times = 5
input_dims = 6

lstm_input = tf.random_normal([batch_size, num_times, input_dims],0.,1.0)

cell = tf.contrib.rnn.BasicLSTMCell(num_lstm_cells, state_is_tuple=True)

init_vars = cell.zero_state(batch_size, tf.float32)
init_c = tf.Variable(init_vars.c, trainable=True)
init_h = tf.Variable(init_vars.h, trainable=True)
init_state = tf.contrib.rnn.LSTMStateTuple(init_c, init_h)

state_vars = cell.zero_state(batch_size, tf.float32)
state_c = tf.Variable(state_vars.c, trainable=False)
state_h = tf.Variable(state_vars.h, trainable=False)
state = tf.contrib.rnn.LSTMStateTuple(state_c, state_h)

layer = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=0.7)
val, new_state = tf.nn.dynamic_rnn(layer, lstm_input, initial_state=state, dtype=tf.float32)

trained_state_c = tf.assign(state[0], new_state[0])
trained_state_h = tf.assign(state[1], new_state[1])
trained_state = tf.contrib.rnn.LSTMStateTuple(trained_state_c, trained_state_h)

我最终解决了这个问题,在一个单独的变量范围内创建了一个初始状态变量。然后使用Optimizer.Minimize()中的var_list可选参数,我可以指定在每个序列的开头训练初始状态。在训练初始状态之后,我会将其复制到这个单独的变量范围,并训练序列其余部分的图形

    with tf.variable_scope("state"):
        state_c = tf.Variable(tf.random_uniform([batch_size, num_lstm_cells], 0, 1), trainable=True)
        state_h = tf.Variable(tf.random_uniform([batch_size, num_lstm_cells], 0, 1), trainable=True)
        state = tf.contrib.rnn.LSTMStateTuple(state_c, state_h)

    with tf.variable_scope("nn"):
        layer = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=0.7)
        val, new_state = tf.nn.dynamic_rnn(layer, lstm_input, initial_state=state, dtype=tf.float32)

        logits = tf.layers.dense(val, units=5, activation=tf.nn.relu)
        losses = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=targets)

    init_c = tf.Variable(tf.zeros([batch_size, num_lstm_cells]), trainable=False)
    init_h = tf.Variable(tf.zeros([batch_size, num_lstm_cells]), trainable=False)
    init_state = tf.contrib.rnn.LSTMStateTuple(init_c, init_h)

    restore_c = tf.assign(state[0], init_state[0])
    restore_h = tf.assign(state[1], init_state[1])
    restore_state = tf.group([restore_c, restore_h])

    save_c = tf.assign(init_state[0], state[0])
    save_h = tf.assign(init_state[1], state[1])
    save_state = tf.group([save_c, save_h])

    propagate_c = tf.assign(state[0], new_state[0])
    propagate_h = tf.assign(state[1], new_state[1])
    propagate_state = tf.group([propagate_c, propagate_h])

    nn_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "nn")
    state_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "state")

    total_loss = tf.reduce_mean(losses)

    train_nn_step = tf.train.AdamOptimizer().minimize(total_loss, var_list=nn_vars)
    train_nn_state_step = tf.train.AdamOptimizer().minimize(total_loss, var_list=[nn_vars, state_vars])
因此,您可以通过调用以下命令来启动序列:

  • sess.run(restore\u state)
    将初始状态复制回图形
  • ,er=sess.run([train\u nn\u state\u step,error])
    训练初始状态和nn
  • sess.run(保存状态)
    保存初始状态
  • sess.run(传播\u状态)
    将状态传播到下一列车步骤
  • 然后通过调用以下命令来训练序列的其余部分:

  • ,er=sess.run([train\u nn\u step,error])
    只训练神经网络
  • sess.run(传播状态)
    继续通过

  • 这取决于你所说的“训练”初始状态。在“训练”之后,您希望每个新输入序列都有一个固定的(并且可能是良好的)初始状态吗?是的。几乎所有序列都以相同的状态开始。