Lesson 9 Discussion & Wiki (2019)

DRY -> Don’t Repeat Yourself

for cb in self.cbs: 
    res = res and cb.something(learn)
return res

res is updated to res and cb.something(learn) after every callback (the right hand side is calculated first, and then res is updated).

In other words, if any of the cb.something(learn) returns False, res becomes False, and stays False.

3 Likes

When will this be put in the fastai library in your estimation?

Not sure. Probably after the course since it breaks a lot of existing behavior and we are lacking time to fix it all :wink:

1 Like

fast.ai: Come for the cutting edge ML instruction, stay for the actually good software engineering :slight_smile:

19 Likes

Here is the link about Tensorboard integration: Tensorboard Integration

11 Likes

how do i access below stuff in Callbacks

  1. Last metrics
  2. Last loss
  3. modify LRs

Runner#__call__ exits early when the first callback returns true, doesn’t it? Is that intentional? (I don’t have the code up in front of me)

1 Like

You asked that question before and had an answer. Please don’t ask it again in the thread… Make a new thread if you feel you need it after the answer you got.

2 Likes

Do you think it would make sense to have the code in Runner just be part of Learner?

Some awesome design patterns here! Excellent refactoring.

4 Likes

Suggestion to add proper documentation / comment to

    def __call__(self, cb_name):
        for cb in sorted(self.cbs, key=lambda x: x._order):
            f = getattr(cb, cb_name, None)
            if f and f(): return True
        return False

It’s definitely part of a useful abstraction, but my guess is that beginners will look at it and think: what the hell is happening here? Maybe a link to this part of the video will do.

8 Likes

that’s a really high bar for the S4TF team to replicate in a few weeks. :sunglasses:

3 Likes

Agree, I’ve been digging through the fastai code and it’s hard to follow. There’s lots of magic that happens implicitly (and when you’re in a subclass it’s hard to trace it back up to where it is defined especially if there’s no function or attribute name to search for)

Edit: This video is helping though :slight_smile:

Thanks, here is a full example from the earlier version (still trying to wrap my head around this):

def begin_fit(self, learn):
        self.learn,self.in_train = learn,True
        learn.stop = False
        res = True
        for cb in self.cbs: res = res and cb.begin_fit(learn)
        return res

Why must the begin_fit method in the CallbackHandler class stop executing subsequent callbacks in the list if one of the prior ones returns False?

Also, I’m having trouble wrapping my mind around the concept of a Callback as a set of callback functions – I naturally think of “begin_fit”, “after_fit”, etc each as a separate callback. Why would you ever need to pass in two "begin_fit"s?

For now it’s only in the notebook that you’re seeing with the video :wink:
And guess what, it’s your homework to come up with a nice documentation for it :slight_smile:

9 Likes

hi sg,

I tried to ask on the top of that…
What i knew already was how u build the callback…
What i dint knew was what i asked…hope that if some one is already doing it in any notebook ,can post the link.

It’s definitely part of a useful abstraction, but my guess is that beginners will look at it and think: what the hell is happening here? Maybe a link to this part of the video will do.

I would go one further and guess that non-beginners would also think “What the hell is happening here?” It will take some major unravelling for anyone unfamiliar with the codebase to make sense of this approach.

It does eventually seem to lead to a nice API for fastai users though. That said the whole exercise just makes me miss C# Events. I’m unfamiliar with Swift but perhaps it can help solve problems like this without having to search through lists of methods based on the method’s string name.

2 Likes

Might just be my opinion Self(‘callback’) code looks very weird. Why not just have a simple function self.invoke_callback(callback_name) instead ? Might be easier to understand it that way.

1 Like

Hi mods. May I know what is Jeremy’s typical process in debugging the issues that he encounters during his experimentation? Would love to see the process step by step.

I have a recollection that he mentioned this sometime before - but can’t find the reference somehow.

Thanks in advance.

6 Likes