Последовательность начала декодера Tensorflow Seq2Seq не работает должным образом - PullRequest
0 голосов
/ 24 февраля 2019

Я реализую базовую модель 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...