Последовательность начала декодера Tensorflow Seq2Seq не работает должным образом
Я реализую базовую модель seq2seq для нейронного машинного перевода. У меня есть вложение слов для кодера и декодера. Мой кодировщик использует функцию TrainingHelper, а мой декодер - GreedyEmbeddingHelper. Я пытался обучить свою сеть, используя две разные предварительные обработки, которые кажутся мне похожими, но одна не работает, и я не очень понимаю, почему.
1) Предварительная обработка предложения: добавление "EOS" для всех предложений.
target_ids = []
for sentence in text:
temp = []
# add <GO> indicator of the target sentence
#temp.append(self.word2idx['<GO>'])
# convert word of each sentence in ids
temp = temp + self.ConvertSentenceToIndex(sentence)
# add <EOS> indicator of the target sentence
temp.append(self.word2idx['<EOS>'])
target_ids.append(temp)
Затем, во время обучения, мы добавляем "GO" к целевым входным данным, прежде чем подавать кодирование встраивания следующим образом:
def build_decoder(target_data, encoder_state,
target_sequence_length, max_target_sequence_length,
rnn_size, num_layers, target_vocab_to_int, target_vocab_size,
batch_size, keep_prob, decoding_embedding_size):
"""
Create decoding layer
:input:
@target_data : target data
@encoder_state : feature map of the encoder
@target_sequence_length : tf.placeholder
@max_target_sequence_length : max value of target_sequence_length
@rnn_size : number of neurons for each rnn in the decoder
@num_layers : number of layers of RNN
@target_vocab_to_int : dic of the vocabulary to int
@target_vocab_size : size of the vocabulary target
@batch_size : size of the batch
@keep_prob : probability of the dropout
@decoding_embedding_size : size of the embedding target
:return: Tuple of (Training BasicDecoderOutput, Inference BasicDecoderOutput)
"""
# --- add <GO> to target data --- #
go_id = target_vocab_to_int['<GO>']
after_slice = tf.strided_slice(target_data, [0, 0], [batch_size, -1], [1, 1])
after_concat = tf.concat( [tf.fill([batch_size, 1], go_id), after_slice], 1)
# --- Embedding Decoder --- #
target_vocab_size = len(target_vocab_to_int)
dec_embeddings = tf.Variable(tf.random_uniform([target_vocab_size, decoding_embedding_size]))
dec_embed_input = tf.nn.embedding_lookup(dec_embeddings, after_concat)
cells = tf.contrib.rnn.MultiRNNCell([tf.contrib.rnn.LSTMCell(rnn_size) for _ in range(num_layers)])
output_layer = tf.layers.Dense(target_vocab_size)
with tf.variable_scope("decode"):
# --- Training decoding --- #
train_cell = tf.contrib.rnn.DropoutWrapper(cells,
output_keep_prob=keep_prob)
# for only input layer
train_helper = tf.contrib.seq2seq.TrainingHelper(dec_embed_input,
target_sequence_length)
train_decoder = tf.contrib.seq2seq.BasicDecoder(train_cell,
train_helper,
encoder_state,
output_layer)
# unrolling the decoder layer
train_output, _, _ = tf.contrib.seq2seq.dynamic_decode(train_decoder,
impute_finished=True,
maximum_iterations=max_target_sequence_length)
# --- Inference decoding --- #
infer_cell = tf.contrib.rnn.DropoutWrapper(cells,
output_keep_prob=keep_prob)
start_of_sequence_id = target_vocab_to_int['<GO>']
end_of_sequence_id = target_vocab_to_int['<EOS>']
infer_helper = tf.contrib.seq2seq.GreedyEmbeddingHelper(dec_embeddings,
#start_of_sequence_id,
tf.fill([batch_size], start_of_sequence_id),
end_of_sequence_id)
infer_decoder = tf.contrib.seq2seq.BasicDecoder(infer_cell,
infer_helper,
encoder_state,
output_layer)
infer_output, _, _ = tf.contrib.seq2seq.dynamic_decode(infer_decoder,
impute_finished=True,
maximum_iterations=max_target_sequence_length)
return (train_output, infer_output)
Это работает, точность при выводе хорошая.
2) Предварительная обработка предложения: добавление "GO" и "EOS" для всего предложения. Итак, я удаляю в функции buil_decoder 3 первые строки и изменяю:
dec_embed_input = tf.nn.embedding_lookup(dec_embeddings, after_concat)
от:
dec_embed_input = tf.nn.embedding_lookup(dec_embeddings, target_data)
Но это не работает во время обучения. Снижение потерь (так следует учиться), но и снижение точности, что ненормально. Более того, когда я смотрю на прогноз во время логического вывода, модель предсказывает большую часть времени повторяющихся слов. Я не понимаю, почему добавление "GO" в функцию "build_decoder" работает правильно, а делать это снаружи нет.
У кого-нибудь есть идеи по этому поводу? Это проблема, связанная с trainingHelper или чем-то еще?
Вот весь мой код на ноутбуке Jupyter: https://github.com/Shiro-LK/TF_exemple/blob/master/NTM_Seq2Seq.ipynb