In the train(…):
encoder_optimizer.zero_grad()
decoder_optimizer.zero_grad()
for ei in range(input_length):
encoder_output, encoder_hidden = encoder(input_variable[ei], encoder_hidden)
encoder_outputs[ei] = encoder_output[0][0]
decoder_hidden = encoder_hidden # the last hidden in encoder is used as the initial hiddne in decoder
use_teacher_forcing = True if random.random() < teacher_forcing_ratio else False
if use_teacher_forcing:
for di in range(target_length):
decoder_output, decoder_hidden = decoder(decoder_input, decoder_hidden)
loss += criterion(decoder_output, target_variable[di])
decoder_input = target_variable[di]  # Teacher forcing
else:
for di in range(target_length):
decoder_output, decoder_hidden = decoder(decoder_input, decoder_hidden)
topv, topi = decoder_output.data.topk(1)
ni = topi[0][0]
		decoder_input = Variable(torch.LongTensor([[ni]]))
		decoder_input = decoder_input.cuda() if use_cuda else decoder_input

		loss += criterion(decoder_output, target_variable[di])

loss.backward()
encoder_optimizer.step()
decoder_optimizer.step()