Я реализую модель Seq2Seq с многоуровневым двунаправленным механизмом взаимодействия и внимания, и, следуя этому уроку https://github.com/tensorflow/nmt, я запутался в том, как правильно манипулировать encoder_state после двунаправленного слоя.
Ссылаясь на учебное пособие «Для нескольких двунаправленных слоев нам нужно немного манипулировать encoder_state, см. Model.py, метод _build_bidirectional_rnn () для более подробной информации». и это соответствующая часть кода (https://github.com/tensorflow/nmt/blob/master/nmt/model.py строка 770):
encoder_outputs, bi_encoder_state = (
self._build_bidirectional_rnn(
inputs=self.encoder_emb_inp,
sequence_length=sequence_length,
dtype=dtype,
hparams=hparams,
num_bi_layers=num_bi_layers,
num_bi_residual_layers=num_bi_residual_layers))
if num_bi_layers == 1:
encoder_state = bi_encoder_state
else:
# alternatively concat forward and backward states
encoder_state = []
for layer_id in range(num_bi_layers):
encoder_state.append(bi_encoder_state[0][layer_id]) # forward
encoder_state.append(bi_encoder_state[1][layer_id]) # backward
encoder_state = tuple(encoder_state)
Итак, вот что у меня сейчас:
def get_a_cell(lstm_size):
lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_size)
#drop = tf.nn.rnn_cell.DropoutWrapper(lstm,
output_keep_prob=keep_prob)
return lstm
encoder_FW = tf.nn.rnn_cell.MultiRNNCell(
[get_a_cell(num_units) for _ in range(num_layers)])
encoder_BW = tf.nn.rnn_cell.MultiRNNCell(
[get_a_cell(num_units) for _ in range(num_layers)])
bi_outputs, bi_encoder_state = tf.nn.bidirectional_dynamic_rnn(
encoder_FW, encoder_BW, encoderInput,
sequence_length=x_lengths, dtype=tf.float32)
encoder_output = tf.concat(bi_outputs, -1)
encoder_state = []
for layer_id in range(num_layers):
encoder_state.append(bi_encoder_state[0][layer_id]) # forward
encoder_state.append(bi_encoder_state[1][layer_id]) # backward
encoder_state = tuple(encoder_state)
#DECODER -------------------
decoder_cell = tf.nn.rnn_cell.MultiRNNCell([get_a_cell(num_units) for _ in range(num_layers)])
# Create an attention mechanism
attention_mechanism = tf.contrib.seq2seq.LuongAttention(num_units_attention, encoder_output ,memory_sequence_length=x_lengths)
decoder_cell = tf.contrib.seq2seq.AttentionWrapper(
decoder_cell,attention_mechanism,
attention_layer_size=num_units_attention)
decoder_initial_state = decoder_cell.zero_state(batch_size,tf.float32)
.clone(cell_state=encoder_state)
Проблема в том, что я получаю ошибку
The two structures don't have the same nested structure.
First structure: type=AttentionWrapperState
str=AttentionWrapperState(cell_state=(LSTMStateTuple(c=, h=),
LSTMStateTuple(c=, h=)), attention=, time=, alignments=, alignment_history=
(), attention_state=)
Second structure: type=AttentionWrapperState
str=AttentionWrapperState(cell_state=(LSTMStateTuple(c=, h=),
LSTMStateTuple(c=, h=), LSTMStateTuple(c=, h=), LSTMStateTuple(c=, h=)),
attention=, time=, alignments=, alignment_history=(), attention_state=)
И это имеет для меня некоторый смысл, потому что мы включаем не все выходные слои, а (я думаю) только последний слой. Хотя для государства мы фактически объединяем все слои.
Так, как я и ожидал, при конкатенации только последнего состояния слоя, как показано ниже:
encoder_state = []
encoder_state.append(bi_encoder_state[0][num_layers-1]) # forward
encoder_state.append(bi_encoder_state[1][num_layers-1]) # backward
encoder_state = tuple(encoder_state)
Работает без ошибок.
Насколько мне известно, нет части кода, в которой они снова преобразуют кодировщик_код перед передачей его на уровень внимания. Так как же может работать их код? И что еще более важно, мое исправление нарушает правильное поведение механизма внимания?