Как преобразовать decoder_target_data в правильную форму для выходов модели - PullRequest
0 голосов
/ 15 мая 2019

Я пытаюсь закодировать машинный перевод на уровне слов, используя керасы, с помощью архитектурного кодера-декодера, используя метод word_embedding и метод принудительного обучения. Я прочитал, что target_answer должен быть таким же, как decoder_inputs, но со сдвигом одного слова. Проблема в том, что когда я создаю свою модель, это последняя часть model.summary()

lstm (LSTM)       [(None, 128), (None, 91648     embedding[0][0]                  
___________________________________________________________________________
lstm_2 (LSTM)     [(None, 100, 128), ( 91648   embedding_2[0][0]                
                                                                 lstm[0][1]                       
                                                                 lstm[0][2]                       
___________________________________________________________________________
dense_1 (Dense)   (None, 100, 10001)   1290129     lstm_2[0][0]    

decoder_outputs имеет 3 измерения, поэтому target_answer должен быть преобразован в 3 измерения. Как я могу это сделать?? target_answer - это массив с index_word словаря [4 52 69 5 6 ....]

Я следую этому примеру кераса https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq.py, но этот - на уровне персонажа.

Я пытался использовать это

target_answer = tokenizer.texts_to_matrix(answers, mode='binary')

но он просто дает мне двумерный массив и не имеет такой же формы, как decoder_ouputs

Это моя модель

latent_dim = 128
encoder_inputs = Input(shape=(max_amount_tokens,))
word_embedding = Embedding(input_dim=vocabulary_size+2, output_dim=embedding_dim,\
                           input_length=max_amount_tokens, weights = [embedding_matrix], trainable=False)(encoder_inputs)


x, state_h, state_c = LSTM(latent_dim, return_state=True)(word_embedding)
encoder_states = [state_h, state_c]

decoder_inputs = Input(shape=(max_amount_tokens,))
word_embedding = Embedding(input_dim=vocabulary_size+2, output_dim=embedding_dim, \
                           input_length=max_amount_tokens, weights = [embedding_matrix], trainable=False)(decoder_inputs)


decoder_lstm = LSTM(latent_dim,  return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(word_embedding, initial_state=encoder_states)
decoder_dense = Dense(vocabulary_size + 1, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)


model = Model([encoder_inputs, decoder_inputs], decoder_outputs)

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])

history = model.fit([input_questions_encoded, input_answers_encoded], target_answer, epochs=150, batch_size=64)

1 Ответ

0 голосов
/ 15 мая 2019

Encoder Decoder с Teacher Forcing

Давайте возьмем пример и посмотрим, что он подразумевает под Teacher Forcing.

Ввод: [1,2,3] и целевой декодированный вывод: [ 1, 3, 6].Поэтому мы хотим, чтобы модель научилась декодировать каждый вход, добавляя предыдущие все входы.В общем, это может быть POS-тегирование или NER-тегирование или языковой перевод.

Кодер: Цель использования кодера - узнать скрытое представление входного вектора.

Декодер: Декодер используется для декодированияцели из скрытого представления входов.Ванильный декодер принимает выходные данные предыдущего шага в качестве входных данных для прогнозирования текущего целевого состояния.то есть это обусловлено предыдущим выводом p(y_pred_i|y_pred_i-1)

Принудительное воздействие учителя: При принудительном обучении учителя вместо использования предыдущего вывода мы используем основную правду для прогнозирования текущего целевого состояния, т.е. p(y_pred_i|y_truth_i-1),После обучения модели для прогнозирования мы используем p(y_pred_i|y_pred_i-1)

. Таким образом, decoder_input - это действительные метки цели, сдвинутые вправо на один временной шаг, а первый временной шаг - это специальный ввод, называемый началом последовательности.

Графическое представление:

Фаза обучения

enter image description here

Фаза прогнозирования / тестирования

enter image description here

Пример кода:

X = np.random.randint(1,10,size=(10,sequence_length))
y = X.cumsum(axis=1)

encoder_input_data = X
decoder_input_data = np.column_stack([np.zeros(len(y)), y])[:,:-1]
target_data = y


latent_dim = 32
sequence_length = 5
input_vocabulary_size = 10
hidden_size = 128
output_vocabulary_size = 91

encoder_inputs = Input(shape=(sequence_length,))
word_embedding = Embedding(input_dim=input_vocabulary_size,
                           output_dim=hidden_size,
                           trainable=True)(encoder_inputs)
encoder_outputs, state_h, state_c = LSTM(latent_dim, return_state=True)(word_embedding)



decoder_inputs = Input(shape=(sequence_length,))
word_embedding = Embedding(input_dim=output_vocabulary_size, 
                           output_dim=hidden_size,
                           trainable=True)(decoder_inputs)

decoder_lstm,_,_ = LSTM(latent_dim, return_sequences=True, return_state=True)(
    word_embedding, initial_state=[state_h, state_c])
outputs = Dense(output_vocabulary_size, activation='softmax')(decoder_lstm)


model = Model([encoder_inputs,decoder_inputs], outputs)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])

model.fit([encoder_input_data,decoder_input_data], to_categorical(y, num_classes=91), epochs=500)

Как видно из кода, я использую 0 в качестве специального начального символа ($ вцифры).Строка, на которую следует обратить внимание:

decoder_input_data = np.column_stack([np.zeros(len(y)), y])[:,:-1], это смещение меток цели вправо на 1 и специальный начальный символ (0), добавленный в начале.

...