Tensorflow: сложенные двунаправленные LSTM

#tensorflow

#tensorflow

Вопрос:

Я хочу сложить два LSTM без использования MultiRNN оболочки. Однако следующий код приводит к ValueError: Shapes (3,) and (2,) are not compatible появлению because of inputs=states_fw_1 во втором LSTM. Как я могу передать скрытое состояние первого LSTM в качестве входных данных второму?

LSTM 1

     with tf.name_scope("BiLSTM_1"):
        with tf.variable_scope('forward_1'):
            cell_fw_1 = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)

        with tf.variable_scope('backward_srl'):
            cell_bw_srl = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)

        outputs_1, states_1 = tf.nn.bidirectional_dynamic_rnn(
            cell_fw=cell_fw_1,
            cell_bw=cell_bw_1,
            dtype=tf.float64,
            sequence_length=self.input_seq_len,
            inputs=self.embedded_input_layer,
            scope='BiLSTM_1')
  

Состояние — это кортеж

     states_fw_1, states_bw_1 = states
  

LSTM 2

     with tf.name_scope("BiLSTM_2"):
        with tf.variable_scope('forward'):
            cell_fw = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)

        with tf.variable_scope('backward'):
            cell_bw = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)

        outputs, states = tf.nn.bidirectional_dynamic_rnn(
            cell_fw=cell_fw,
            cell_bw=cell_bw,
            dtype=tf.float64,
            sequence_length=self.input_seq_len,
            inputs=states_fw_1,
            scope="BiLSTM_extraction")
  

Ответ №1:

Я изучаю TF 2 дня (так что я не профессионал), и мне было интересно решить эту проблему.

Вот мои выводы: вы хотите сделать то, что невозможно получить с помощью реализации ‘LSTMCell’. Вот почему:

  1. Вы хотите передать «states_fw_1 в следующий BI-LSTM. Итак, первый вопрос должен быть: каковы размеры «states_fw_1»? Для любой реализации RNN вам понадобится [batch_size, seq_len, input_size] . Для «states_fw_1» это [batch_size, hidden_size] (я только что проверил размер «states_fw_1», выполняемый ниже кода). Итак, вы можете видеть, что ваш вывод не соответствует требованиям RNN. Это связано с тем, что модель выводит только одно последнее состояние ячейки LSTM, а не всю историю (см. Документацию). И вас не интересует последнее состояние, потому что вы хотите передать состояние [t-step] на слой выше.’state_fw_1′ полезен, когда вы хотите классифицировать последовательность (не каждый элемент в последовательности) Редактировать: ‘state_fw_1’ содержит последнее «hidden_state» и последнее «memory_cell». Я думаю, что для классификации будет полезно только «hidden_state».

  2. Итак, вам просто нужно использовать объединенный вывод (из прямого и обратного прохода). И выходные данные ячейки ‘LSTMCell’ имеют размер [batch_size, seq_len, hidden_size * 2], (* 2 как вперед и назад), поэтому он подходит для следующего сложенного RNN (выходные данные поступают с каждого временного шага, а не с состояния).

Вот код, который я тестировал:

 import tensorflow as tf
import numpy as np

hidden_size = 21
seq_len = tf.placeholder(tf.int32, [None])
inputs = tf.placeholder(tf.float32, [None, None, 32])
with tf.variable_scope('BiLSTM_1'):
  with tf.variable_scope('forward_1'):
    cell_fw_1 = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)
  with tf.variable_scope('backward_srl'):
      cell_bw_1 = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)
  outputs_1, states_1 = tf.nn.bidirectional_dynamic_rnn(
      cell_fw=cell_fw_1,
      cell_bw=cell_bw_1,
      dtype=tf.float32,
      sequence_length=seq_len,
      inputs=inputs,
      scope='BiLSTM_1')

# Merge Output tensor from forward and backward pass. It size is [batch_size, seq_len, 2*hidden_size]
outputs_1 = tf.concat(outputs_1, 2)

with tf.name_scope("BiLSTM_2"):
  with tf.variable_scope('forward'):
      cell_fw = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)
  with tf.variable_scope('backward'):
      cell_bw = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True)
  outputs, states = tf.nn.bidirectional_dynamic_rnn(
      cell_fw=cell_fw,
      cell_bw=cell_bw,
      dtype=tf.float32,
      sequence_length=seq_len,
      inputs=outputs_1,
      scope="BiLSTM_2")

# Initializate the weights and biases
init = tf.initialize_all_variables()
batch_size = 5
seq_len_val = 10
train_inputs = np.zeros((batch_size, seq_len_val, 32))
train_seq_len = np.ones(batch_size) * seq_len_val
with tf.Session() as session:
  session.run(init)
  feed = {inputs: train_inputs, seq_len: train_seq_len}
  out,state,state_1 = session.run([outputs,states, states_1],feed)

print ("State size: ", state_1[0].c.shape, " Out Size: ", out[0][0].shape)
print ("Batch_size: ", batch_size, " Sequence Len: ", seq_len_val, " Hidden Size: ", hidden_size)
  

Ответ №2:

‘outputs_1’, возвращаемый LSTM 1, представляет собой кортеж, содержащий ‘outputs_fw’ и ‘outputs_bw’.

‘outputs_fw’ и ‘outputs_bw’ будут иметь размерность: [batch_size, sequence_length, hidden_size] .

Вы должны объединить скрытые состояния ‘outputs_fw’ и ‘outputs_bw’ (us tf.concat с axis = 2) и передать их в качестве входных данных в LSTM 2 вместо передачи ‘states_fw_1’ в качестве входных данных в LSTM 2.