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
- это действительные метки цели, сдвинутые вправо на один временной шаг, а первый временной шаг - это специальный ввод, называемый началом последовательности.
Графическое представление:
Фаза обучения

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

Пример кода:
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), добавленный в начале.