def evaluate(input_seq, encoder, decoder, max_length=MAX_LENGTH):
    input_seqs = [indexes_from_sentence(input_lang, input_seq)]
    input_lengths = [len(x) for x in input_seqs]
    input_batches = Variable(torch.LongTensor(input_seqs), volatile=True).transpose(0, 1)
    if USE_CUDA:
        input_batches = input_batches.cuda()
    encoder.eval()
    decoder.eval()
    (encoder_outputs, encoder_hidden) = encoder(input_batches, input_lengths, None)
    decoder_input = Variable(torch.LongTensor([[SOS_token]]), volatile=True)
    decoder_hidden = encoder_hidden[:decoder.n_layers]
    if USE_CUDA:
        decoder_input = decoder_input.cuda()
    decoded_words = []
    decoder_attentions = torch.zeros((max_length + 1), (max_length + 1))
    for di in range(max_length):
        (decoder_output, decoder_hidden, decoder_attention) = decoder(decoder_input, decoder_hidden, encoder_outputs)
        decoder_attentions[di, :decoder_attention.size(2)] += decoder_attention[0][0].cpu().data
        (topv, topi) = decoder_output.data.topk(1)
        ni = topi[0][0]
        if (ni == EOS_token):
            decoded_words.append('<EOS>')
            break
        else:
            decoded_words.append(output_lang.index2word[ni])
        decoder_input = Variable(torch.LongTensor([[ni]]))
        if USE_CUDA:
            decoder_input = decoder_input.cuda()
    encoder.train()
    decoder.train()
    return (decoded_words, decoder_attentions[:(di + 1), :len(encoder_outputs)])
def evaluate(input_seq, encoder, decoder, max_length=MAX_LENGTH):
    input_seqs = [indexes_from_sentence(input_lang, input_seq)]
    input_lengths = [len(x) for x in input_seqs]
    input_batches = Variable(torch.LongTensor(input_seqs), volatile=True).transpose(0, 1)
    if USE_CUDA:
        input_batches = input_batches.cuda()
    encoder.eval()
    decoder.eval()
    (encoder_outputs, encoder_hidden) = encoder(input_batches, input_lengths, None)
    decoder_input = Variable(torch.LongTensor([[SOS_token]]), volatile=True)
    decoder_hidden = encoder_hidden[:decoder.n_layers]
    if USE_CUDA:
        decoder_input = decoder_input.cuda()
    decoded_words = []
    decoder_attentions = torch.zeros((max_length + 1), (max_length + 1))
    for di in range(max_length):
        (decoder_output, decoder_hidden, decoder_attention) = decoder(decoder_input, decoder_hidden, encoder_outputs)
        decoder_attentions[di, :decoder_attention.size(2)] += decoder_attention[0][0].cpu().data
        (topv, topi) = decoder_output.data.topk(1)
        ni = topi[0][0]
        if (ni == EOS_token):
            decoded_words.append('<EOS>')
            break
        else:
            decoded_words.append(output_lang.index2word[ni])
        decoder_input = Variable(torch.LongTensor([[ni]]))
        if USE_CUDA:
            decoder_input = decoder_input.cuda()
    encoder.train()
    decoder.train()
    return (decoded_words, decoder_attentions[:(di + 1), :len(encoder_outputs)])