ignite icon indicating copy to clipboard operation
ignite copied to clipboard

More control over ProgressBar formatting

Open jmg049 opened this issue 2 years ago • 5 comments

🚀 Feature - Improved contrib.handlers.tqdm_logger.ProgressBar formatting and alignment

More configurable arguments/bar formatting of the available ProgressBar class. Specifically to allow for the alignment of multiple bars (train loop, test/validation loop).

The current functionality of the ProgressBar class modifies the bar format to include the current_epoch/total_epochs when max_epochs > 1. This mostly works well for the train loop. However, format/alignment issues arise when the train loop is used with a validation loop that runs at the end of each epoch (on EpochCompleted). The validation loop should only be run once. However, this causes the epoch information to be omitted, and consequently, any format options which attempt to align the bars are void (see the screenshot below; both progress bars are set to have the same formatting). The format given below may not format as intended, but I cannot test it since I cannot remove/add the epoch information.

Ideally, control would be given over the if/how the epoch information is displayed when creating the ProgressBar. Investigating the codebase, it seems that this stuff is handled internally in the _OutputHandler class. I would very much like to align the bars to start and finish in the same place as each other, purely for aesthetics.

BAR_FMT = "{desc:<15} [{n_fmt}/{total_fmt}]|{bar}| {rate_fmt}{postfix}"

image

In the above image, I would love control over aligning the actual bar sections of the progress bars.

jmg049 avatar Nov 01 '23 18:11 jmg049

@jmg049 thanks for the suggestions! Would you like to send a draft PR with implementing that?

vfdev-5 avatar Nov 02 '23 14:11 vfdev-5

Hey 👋, I've just created a thread for this issue on PyTorch-Ignite Discord where you can quickly talk to the community on the topic.

🤖 This comment was automatically posted by Discuss on Discord

github-actions[bot] avatar Nov 02 '23 14:11 github-actions[bot]

@jmg049 thanks for the suggestions! Would you like to send a draft PR with implementing that?

Hey, sure, it might take some time though unfortunately(if only contributing was my main work). I do already have a very hacky, massively imperfect prototype work-around for it.

But if I find some time I'll give it a shot. Definitely a niche, but fun and interesting problem.

jmg049 avatar Nov 02 '23 22:11 jmg049

@jmg049 I tried using the same way as you did with padding the description and seems like tqdm should strip whitespaces. Here is how I could get the alignment with another character. Basically, all mid-sized chars can work.

from ignite.engine import Engine, Events
from ignite.contrib.handlers import ProgressBar


train_data = range(10)
eval_data = range(4)
max_epochs = 5


def train_step(engine, batch):
    import time

    time.sleep(0.1)


trainer = Engine(train_step)


def eval_step(engine, batch):
    import time

    time.sleep(0.1)


evaluator = Engine(eval_step)


@trainer.on(Events.EPOCH_COMPLETED(every=2))
def run_validation():
    evaluator.run(eval_data)


bformat = "{desc:▫>20}[{n_fmt:0>3}/{total_fmt:0>3}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]"

ProgressBar(
    persist=True, desc="Training", bar_format=bformat,
).attach(trainer)
ProgressBar(
    persist=True, desc="Validation", bar_format=bformat,
).attach(evaluator)
  

trainer.run(train_data, max_epochs=max_epochs)
image

Does this look aesthetically better?

vfdev-5 avatar Nov 06 '23 14:11 vfdev-5

Yes it definitely looks better. No doubt about it. I'm still not a huge fan of always having the epoch info there and more specifically that it's tied to the specific Engine.

I have something working (I think) that is quite nice, unfortunately the amount of time I have to work on it is small. Basically, I've added a custom field to the tqdm bar format, epochs, which allows you to control the formatting of the epoch information.

Then I've also added a parameter to the ProgressBar class named progress_with to allow for tying of something like and Evaluator progress bar to the Trainer progress bar.

A (rough) example:

trainer_pb = ProgressBar(...)
evaluator_pb = ProgressBar(...,  progress_with=trainer_pb)

Then the evaluator progress bar displays the same epoch information as the trainer.

jmg049 avatar Nov 08 '23 20:11 jmg049