def add_progress_bar(trainer, evaluator, validation_loader, epoch_length):
    """
    "I can't believe it's not Keras"
    Running average accuracy and loss metrics + TQDM progressbar
    """
    training_history = {'accuracy': [], 'loss': []}
    validation_history = {'accuracy': [], 'loss': []}
    last_epoch = []

    RunningAverage(output_transform=lambda x: x[0]).attach(trainer, 'loss')
    RunningAverage(Accuracy(output_transform=lambda x: (x[1], x[2]))).attach(
        trainer, 'accuracy')

    prog_bar = ProgressBar()
    prog_bar.attach(trainer, ['loss', 'accuracy'])
    prog_bar.pbar_cls = tqdm.tqdm

    prog_bar_vd = ProgressBar()
    prog_bar_vd.attach(evaluator)
    prog_bar_vd.pbar_cls = tqdm.tqdm

    from ignite.handlers import Timer

    timer = Timer(average=True)
    timer.attach(trainer,
                 start=Events.EPOCH_STARTED,
                 resume=Events.EPOCH_STARTED,
                 pause=Events.EPOCH_COMPLETED,
                 step=Events.EPOCH_COMPLETED)

    @trainer.on(Events.EPOCH_COMPLETED)
    def log_validation_results(trainer):
        metrics = trainer.state.metrics
        accuracy = metrics['accuracy'] * 100
        loss = metrics['nll']
        last_epoch.append(0)
        training_history['accuracy'].append(accuracy)
        training_history['loss'].append(loss)
        train_msg = "Train Epoch {}:  acc: {:.2f}% loss: {:.2f}, train time: {:.2f}s".format(
            trainer.state.epoch, accuracy, loss, timer.value())

        evaluator.run(validation_loader, epoch_length=epoch_length)
        metrics = evaluator.state.metrics
        accuracy = metrics['accuracy'] * 100
        loss = metrics['nll']
        validation_history['accuracy'].append(accuracy)
        validation_history['loss'].append(loss)
        val_msg = "Valid Epoch {}:  acc: {:.2f}% loss: {:.2f}".format(
            trainer.state.epoch, accuracy, loss)

        prog_bar_vd.log_message(train_msg + " --- " + val_msg)