Как изменить модель Tensorflow Sequence2Sequence для реализации двунаправленного LSTM, а не однонаправленного?

Обратитесь к этому сообщению, чтобы узнать предысторию проблемы: Реализует ли метод TensorFlow embedding_attention_seq2seq двунаправленный кодировщик RNN по умолчанию?

Я работаю над той же моделью и хочу заменить однонаправленный слой LSTM двунаправленным слоем. Я понимаю, что мне нужно использовать static_bidirectional_rnn вместо static_rnn, но я получаю сообщение об ошибке из-за некоторого несоответствия в форме тензора.

Я заменил следующую строку:

encoder_outputs, encoder_state = core_rnn.static_rnn(encoder_cell, encoder_inputs, dtype=dtype)

со строкой ниже:

encoder_outputs, encoder_state_fw, encoder_state_bw = core_rnn.static_bidirectional_rnn(encoder_cell, encoder_cell, encoder_inputs, dtype=dtype)

Это дает мне следующую ошибку:

InvalidArgumentError (см. Выше для трассировки): Несовместимые формы: [32,5,1,256] vs. [16,1,1,256] [[Узел: gradient / model_with_buckets / embedding_attention_seq2seq / embedding_attention_decoder / Внимание_decoder / Attention_0 / add_radientAradientArt = = DT_INT32, _device = "/ job: localhost / replica: 0 / task: 0 / cpu: 0"] (градиенты / model_with_buckets / embedding_attention_seq2seq / embedding_attention_decoder / Внимание_decoder / Attention_0 / add_grad / Shape, gradient_decoder_decoder / embder_battention_decoder / embder_battention_buckets / embder_buckets / Attention_0 / add_grad / Shape_1)]]

Я понимаю, что результаты обоих методов различаются, но я не знаю, как изменить код внимания, чтобы включить это. Как отправить в модуль внимания и прямое, и обратное состояние - объединить ли скрытые состояния?


person Leena Shekhar    schedule 14.07.2017    source источник


Ответы (1)


Из сообщения об ошибке я обнаружил, что размер пакета двух тензоров где-то не совпадает, один равен 32, а другой - 16. Я полагаю, это потому, что выходной список двунаправленного rnn вдвое больше, чем у однонаправленного. И вы просто не можете приспособиться к этому в следующем коде соответственно.

Как отправить в модуль внимания и прямое, и обратное состояние - объединить ли скрытые состояния?

Вы можете сослаться на этот код:

  def _reduce_states(self, fw_st, bw_st):
    """Add to the graph a linear layer to reduce the encoder's final FW and BW state into a single initial state for the decoder. This is needed because the encoder is bidirectional but the decoder is not.
    Args:
      fw_st: LSTMStateTuple with hidden_dim units.
      bw_st: LSTMStateTuple with hidden_dim units.
    Returns:
      state: LSTMStateTuple with hidden_dim units.
    """
    hidden_dim = self._hps.hidden_dim
    with tf.variable_scope('reduce_final_st'):

      # Define weights and biases to reduce the cell and reduce the state
      w_reduce_c = tf.get_variable('w_reduce_c', [hidden_dim * 2, hidden_dim], dtype=tf.float32, initializer=self.trunc_norm_init)
      w_reduce_h = tf.get_variable('w_reduce_h', [hidden_dim * 2, hidden_dim], dtype=tf.float32, initializer=self.trunc_norm_init)
      bias_reduce_c = tf.get_variable('bias_reduce_c', [hidden_dim], dtype=tf.float32, initializer=self.trunc_norm_init)
      bias_reduce_h = tf.get_variable('bias_reduce_h', [hidden_dim], dtype=tf.float32, initializer=self.trunc_norm_init)

      # Apply linear layer
      old_c = tf.concat(axis=1, values=[fw_st.c, bw_st.c]) # Concatenation of fw and bw cell
      old_h = tf.concat(axis=1, values=[fw_st.h, bw_st.h]) # Concatenation of fw and bw state
      new_c = tf.nn.relu(tf.matmul(old_c, w_reduce_c) + bias_reduce_c) # Get new cell from old cell
      new_h = tf.nn.relu(tf.matmul(old_h, w_reduce_h) + bias_reduce_h) # Get new state from old state
return tf.contrib.rnn.LSTMStateTuple(new_c, new_h) # Return new cell and state
person Lerner Zhang    schedule 15.07.2017
comment
Похоже, это то, что я искал. Позвольте мне попробовать и обновить, если это сработает. Спасибо. - person Leena Shekhar; 16.07.2017
comment
Кажется, это работает, но у меня есть вопрос: почему я не могу просто удвоить размер ячейки декодирования вместо того, чтобы проецировать состояния ячейки кодирования на половину размера? Я вижу, что это уменьшит количество параметров в модели, но не потеряю ли я информацию из-за проекции, которую я делаю? - person Leena Shekhar; 18.07.2017
comment
@LeenaShekhar Практично также удвоение размера ячейки декодирования. Здесь вам лучше объединить два состояния двунаправленного кодировщика в одно (чтобы кодировщик и декодер имели одинаковый размер ячеек, чтобы избежать ошибок), что достигается путем выполнения проекции, подобной приведенной выше, отдельно для c и час - person Lerner Zhang; 02.11.2017