Как правильно сгенерировать последовательность с помощью кодера-декодера lstm? - PullRequest
1 голос
/ 05 июля 2019

Я реализую некоторый код для генерации помеченных данных для понимания естественного языка (NLU) из статьи «Генерация помеченных данных с помощью кодировщика-декодера LSTM для заполнения семантических слотов» (https://pdfs.semanticscholar.org/7ffe/83d7dd3a474e15ccc2aef412009f100a5802.pdf). Моя архитектура представляет собой простой кодер.декодер LSTM, но поскольку мои сгенерированные предложения (для слов и меток) не верны, я пытаюсь сгенерировать точно такое же предложение (только слова), которое я даю в качестве входных данных. К сожалению, это не работает правильно.

Я использую vord2vec для встраивания слов, и размер вложений установлен на 64 (как предложено в статье). Кодер LSTM получает последовательность в обратном порядке и с коэффициентом отсева 0,5. Декодер LSTM также имеетчастота выпадения 0,5 и слой softmax для каждого выхода последовательности для отображения наиболее вероятного слова. Входные данные точно такие же, как у целей (одинаковые предложения), так как сначала я хочу создать точно такое же предложение.

Для обучения я использовал Adam оптимизатор и категорикуl_crossentropy для потери.Для вывода я использовал поиск луча (B = 3) при генерации последовательностей.

Мой обучающий код:

def pretrained_embedding_layer(emb):
    vocab_len = len(emb)
    emb_dim = len(emb[0])
    emb_layer = Embedding(vocab_len, emb_dim, trainable = False)
    emb_layer.build((None,))
    emb_layer.set_weights([emb])

    return emb_layer

LSTM_encoder = LSTM(1024, dropout=0.5, return_state=True, go_backwards=True, name='lstm_encoder')
LSTM_decoder = LSTM(1024, dropout=0.5, return_sequences=True, return_state=True, name='lstm_decoder')
dense_w = Dense(vocab_w_size, activation='softmax', name="word_output")

K.set_learning_phase(1)

def model1_enc_dec(input_shape, w_emb):
     words_indices = Input(shape=input_shape, dtype='int32')
     wemb_layer = pretrained_embedding_layer(w_emb)
     wemb = wemb_layer(words_indices)
     enc_out, enc_state_h, enc_state_c = LSTM_encoder(wemb)
     encoder_states = [enc_state_h, enc_state_c]
     dec_out, dec_state_h, dec_state_c = LSTM_decoder(wemb, 
     initial_state=encoder_states)
     dec_out = dense_w(dec_out)
     model1 = Model(inputs=[words_indices], outputs=[dec_out])

     return model1

model = model1_enc_dec((maxlen,), w_emb, s_emb)
model.summary()
model.compile(loss="categorical_crossentropy", optimizer='adam', metrics=['accuracy'])
    model.fit(train_w, train_lab_w, validation_data=(val_w, val_lab_w), epochs=epochs, verbose=1, shuffle=True)

Мой код вывода:

wemb_layer = Embedding(len(w_emb), len(w_emb[0]), trainable=False)
wemb_layer.build((None,))
LSTM_encoder = LSTM(1024, return_state=True, go_backwards=True, name='lstm_encoder')
LSTM_decoder = LSTM(1024, return_sequences=True, return_state=True, name='lstm_decoder')
dense_w = Dense(vocab_w_size, activation='softmax', name="word_output")

def target_model(input_shape):
    words_indices = Input(shape=input_shape, dtype='int32')
    wemb = wemb_layer(words_indices)
    enc_out, enc_state_h, enc_state_c = LSTM_encoder(wemb)
    encoder_states = [enc_state_h, enc_state_c]
    dec_out, dec_state_h, dec_state_c = LSTM_decoder(wemb, 
    initial_state=encoder_states)
    dec_out = dense_w(dec_out)
    model = Model(inputs=[words_indices], outputs=[dec_out])

    return model

target_model = target_model((maxlen,))
wemb_layer.set_weights(model1.layers[1].get_weights()) # layer 0: input
LSTM_encoder.set_weights(model1.layers[2].get_weights())
LSTM_decoder.set_weights(model1.layers[3].get_weights())
dense_w.set_weights(model1.layers[4].get_weights())

def model1_enco_infe(input_shape):
    words_indices = Input(shape=input_shape, dtype='int32')
    wemb = wemb_layer(words_indices)
    enc_out, enc_state_h, enc_state_c = LSTM_encoder(wemb)
    encoder_model = Model(inputs=[words_indices], outputs=[enc_state_h, 
    enc_state_c])

    return encoder_model

def model1_deco_infe(input_shape):
    dec_word_input = Input(shape=input_shape, dtype='int32')
    dec_state_input_h = Input(shape=(1024,))
    dec_state_input_c = Input(shape=(1024,))
    wemb = wemb_layer(dec_word_input)
    dec_states_input = [dec_state_input_h, dec_state_input_c]
    dec_out, dec_state_h, dec_state_c = LSTM_decoder(wemb, 
    initial_state=dec_states_input)
    dec_states_output = [dec_state_h, dec_state_c]
    deco_out = dense_w(dec_out)
    decoder_model = Model(inputs=[dec_word_input] + dec_states_input, outputs= 
    [deco_out] + dec_states_output)

    return decoder_model

encoder_model = model1_enco_infe((maxlen,))
decoder_model = model1_deco_infe((1,))

def beamsearch_B(deco_w_out, beam):
    words_index = []
    dw = deco_w_out.copy()
    for i in range(beam):
        word_index = np.argmax(dw, axis=-1)
        dw[0][0][word_index[0][0]] = 0
        words_index.append(word_index[0][0])

    return words_index

def generate_model1_add(word_seq, encoder_model, decoder_model, dec_word_input, id2word, beam):
    [enc_state_h, enc_state_c] = encoder_model.predict(word_seq)
    states = [enc_state_h, enc_state_c]
    word_sentence = ''
    probs_word = []
    word_sentences = []
    dec_word_inputs = []
    states_beam = []
    stop_condition = False

    [dec_w_out, dec_state_h, dec_state_c] = 
    decoder_model.predict([dec_word_input] + states)
    words_index, _ = beamsearch_B(dec_w_out, [], beam)

    for i in range(beam):
        probs_word.append(-log(dec_w_out[0][0][words_index[i]]))
        word_sentences.append(id2word[words_index[i]])
        dec_word_inputs.append([words_index[i]])
        states_beam.append([dec_state_h, dec_state_c])

        n_words = 1
        endgame = []

        while not stop_condition:
            words_indexes, words_sentences, probs_words, states_b = [], [], 
            [], []
            for k in range(beam):
                [dec_w_out, dec_state_h, dec_state_c] = 
                decoder_model.predict([dec_word_inputs[k]] + states_beam[k])
                words_index, _ = beamsearch_B(dec_w_out, [], beam)
                states = [dec_state_h, dec_state_c]

                for j in range(beam):
                    words_indexes.append(words_index[j])
                    probs_words.append(probs_word[k] * -log(dec_w_out[0][0] 
                    [words_index[j]]) + 1e-7)
                    words_sentences.append(word_sentences[k] + ' ' + 
                    id2word[words_index[j]])
                    states_b.append(states)

            probs = []
            for i in range(len(probs_words)):
                probs.append(1 / (probs_words[i]))
            indexes = []
            for i in range(beam):
                index = np.argmax(probs, axis=-1)
                probs[index] = 0
                indexes.append(index)

            for i in range(beam):
                probs_word[i] = probs_words[indexes[i]]
                word_sentences[i] = words_sentences[indexes[i]]
                dec_word_inputs[i] = [words_indexes[indexes[i]]]
                states_beam[i] = states_b[indexes[i]]
                if (id2word[words_indexes[indexes[i]]] == 'EOS'):
                    endgame.append(i)

            if len(endgame) == 1:
                word_sentence = word_sentences[endgame]
                stop_condition = True
            elif len(endgame) > 1:
                word_sentence = word_sentences[np.min(endgame)]
                stop_condition = True

            n_words += 1

            if n_words > 50:
                word_sentence = word_sentences[0]
                stop_condition = True

    return word_sentence

word_sentence = generate_model1_add(np.reshape(train_w[i], (1, maxlen)), 
                encoder_model, 0, decoder_model, [w2i['BOS']], i2w, 3)

Anпример моих сгенерированных последовательностей:

Входное предложение: BOS Я четвертый в полете из Бостона в Атланту. EOS PAD PAD PAD ... Сгенерированное предложение: BOS от от от от от от от от от от от отот от от от от ...

Кажется, что тренировочные веса не верны, но я потерял: 0,0032 - акк: 0.9990 - val_loss: 0.0794 - val_acc: 0.9888 во время тренировки.

То, что я хочу, это просто генерировать точно такое же предложение ввода.Надеюсь, вы можете помочь мне, ребята.Заранее спасибо!

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