In sequence-to-sequence (Seq2Seq) models, the output sequence is generated by predicting the next element in the sequence one at a time, based on the previously generated elements. This process is usually done using an RNN-based model, such as an LSTM or GRU. During training, the model is usually fed the true (ground truth) previous element as part of the input, and the true next element as the expected output. However, during inference (when generating new sequences), the model is not provided with the ground truth previous element and must generate it by itself.
Teacher forcing refers to the practice of training Seq2Seq models by feeding the model the true previous element as its input during training, even when generating the current sequence element that will become the input at the next step. This can be thought of as "forcing" the model to learn to predict the next element even when given imperfect previous elements, making it more robust to errors and variations.
In Keras, teacher forcing can be implemented by using the ‘training‘ parameter of the ‘tf.keras.layers.RNN()‘ layer. Setting ‘training=True‘ will use the true input sequence during training, while setting it to ‘False‘ will use the predicted output sequence as the input at the next step.
Here’s an example of how to implement teacher forcing in a Seq2Seq model in Keras:
encoder_inputs = tf.keras.Input(shape=(None, num_encoder_tokens))
encoder = tf.keras.layers.LSTM(latent_dim, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c]
decoder_inputs = tf.keras.Input(shape=(None, num_decoder_tokens))
decoder_lstm = tf.keras.layers.LSTM(latent_dim, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = tf.keras.layers.Dense(num_decoder_tokens, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)
model = tf.keras.Model([encoder_inputs, decoder_inputs], decoder_outputs)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Train model with true previous element as input (teacher forcing)
model.fit([encoder_input_data, decoder_input_data], decoder_target_data, batch_size=batch_size,
epochs=epochs, validation_split=0.2)
# Inference mode (with generator). Use predicted previous element as input
encoder_model = tf.keras.Model(encoder_inputs, encoder_states)
decoder_state_input_h = tf.keras.Input(shape=(latent_dim,))
decoder_state_input_c = tf.keras.Input(shape=(latent_dim,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_outputs, state_h, state_c = decoder_lstm(
decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = tf.keras.Model(
[decoder_inputs] + decoder_states_inputs,
[decoder_outputs] + decoder_states)
# Generate new sequences
def generate_seq(input_seq):
# Encode the input as state vectors.
states_value = encoder_model.predict(input_seq)
# Generate empty target sequence of length 1.
target_seq = np.zeros((1, 1, num_decoder_tokens))
# Populate the first element of target sequence with the start character.
target_seq[0, 0, target_token_index['t']] = 1.
# Sampling loop for a batch of sequences
# (to simplify, here we assume a batch of size 1).
stop_condition = False
generated_sequence = ''
while not stop_condition:
# Predict the next character using the decoder model
output_tokens, h, c = decoder_model.predict(
[target_seq] + states_value)
# Update the states
states_value = [h, c]
# Sample a token
sampled_token_index = np.argmax(output_tokens[0, -1, :])
sampled_char = reverse_target_char_index[sampled_token_index]
generated_sequence += sampled_char
# Exit condition
if (sampled_char == 'n' or
len(generated_sequence) > max_decoder_seq_length):
stop_condition = True
# Update the target sequence (using the predicted output as input)
target_seq = np.zeros((1, 1, num_decoder_tokens))
target_seq[0, 0, sampled_token_index] = 1.
return generated_sequence
In the code above, the model is trained with ground truth previous elements by passing the true input and target sequences into the ‘fit()‘ method. In inference mode, the ‘encoder_model‘ and ‘decoder_model‘ are used to generate new sequences, with the predicted output sequence being fed back into the ‘decoder_model‘ at each step. This is done until the end of the sequence is reached or a maximum sequence length is reached.