Skip to content

Is there a way to deal with variable sized iterables? #64

Description

@mraggi

The problem is this line:
self.total = len(gen) if total is None else total

That is executed at the beginning. But len(gen) might change throughout the iteration, but progress_bar just assumes it keeps still.

What I really want is to use a timer (so "train for 1 hour" instead of "train for so and so epochs").

import time
class Timer:
    def __init__(self, num_seconds):
        self.num_seconds = num_seconds
        self.i = None
        
    def __len__(self):
        if self.i is None: return 1
        eps = 1e-7
        t = time.time() - self.start
        progress = t/num_seconds
        return int((num_seconds*self.i)/(progress+eps)) # estimated size. Changes constantly.
    
    def __iter__(self):
        self.start = time.time()
        self.i, t = 0, 0.0
        while t <= self.num_seconds:
            t = time.time() - self.start
            self.i += 1
            yield None

With this class, if you write

for t in Timer(3.0):
    # do stuff

it runs for 3 seconds. But it doesn't work with the progress_bar :(

Activity

  1. sgugger commented on May 27, 2020

    @sgugger
    Contributor

    This is not supported by the current design, no.

  2. mraggi commented on May 27, 2020

    @mraggi
    Author

    Solved it!

    class VariableSizeProgressBar(progress_bar):
        def on_update(self, val, text, interrupted=False):
            self.total = len(self.gen)
            super().on_update(val,text,interrupted)

    And my timer was calculating length wrong. Here is the correct timer. This way I can tell it "train for 60 seconds".

    class Timer:
        def __init__(self, num_seconds):
            self.num_seconds = num_seconds
            self.i = None
            
        def __len__(self):
            if self.i is None: return 1
            eps = 1e-7
            t = time.time() - self.start
    
            return int(self.i*self.num_seconds/t)
        
        def __iter__(self):
            self.start = time.time()
            self.i = 0
            t = 0.0
            while t <= self.num_seconds:
                t = time.time() - self.start
                self.i += 1
                yield None
  3. sgugger commented on May 27, 2020

    @sgugger
    Contributor

    Clever trick :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions