Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trainer cleanup #934

Merged
merged 8 commits into from
Feb 27, 2020
Merged

Trainer cleanup #934

merged 8 commits into from
Feb 27, 2020

Conversation

Borda
Copy link
Member

@Borda Borda commented Feb 25, 2020

What does this PR do?

minor cleaning Training inits in its parent classes... Partially solves #887

PR review

Anyone in the community is free to review the PR once the tests have passed.
If we didn't discuss your PR in Github issues there's a high chance it will not be merged.

Did you have fun?

Make sure you had fun coding 🙃

@Borda Borda added this to the 0.6.2 milestone Feb 25, 2020
@Borda Borda added the feature Is an improvement or enhancement label Feb 25, 2020
@Borda Borda mentioned this pull request Feb 25, 2020
@MattPainter01
Copy link
Contributor

MattPainter01 commented Feb 25, 2020

Looks good to me!

I was looking for guides on whether to use ellipsis instead of pass in abstract methods so we could use this everywhere, but as far as I can tell there is no consensus. Even pythons docs are inconsistent.

Never mind, it appears that pass is preferred.

@Borda Borda requested a review from a team February 25, 2020 16:44
@Borda Borda added the ready PRs ready to be merged label Feb 25, 2020
@williamFalcon
Copy link
Contributor

@Borda i think the ... is making the code unreadable to non engs... what's the advantage?
One of our core principles is to keep things simple so the code is readable.

@Borda
Copy link
Member Author

Borda commented Feb 25, 2020

The adventage of ... compare to none or pass is that it is just place holder, but let's keep it open for now, it is not a priority....
Moreover the motivation is not to depend on this package just because of single dataset lol

@luiscape
Copy link
Contributor

@Borda I agree with @williamFalcon here. I think the code is less readable with ellipsis rather than with regular None. I think that's the case because:

  • It is a very unusual notation for class attribute declaration
  • It's not what the official Ellipsis documentation suggests for the expected use-case
  • In my experience, I have only really used Ellipsis when declaring types using typing (see PEP484)

In the same spirit, maybe a potential enhancement would be to use type hinting to declare the expected type of such variables (see here)?

@Borda
Copy link
Member Author

Borda commented Feb 25, 2020

In the same spirit, maybe a potential enhancement would be to use type hinting to declare the expected type of such variables (see here)?

well we already started with type hinting, but not yet propagated everywhere lol so I would say that it fine aligned with your ref to class basic or here (maybe I missed something?)
and for class properties, I just found (feel like) it easier to understand that there is just place holder and it is not the true init value, I saw the discussion somewhere (let me see an I will update it here)

Anyway, happy to discuss it or drop my suggestion... :]

@hadim
Copy link
Contributor

hadim commented Feb 26, 2020

I don't find the code less readable with ellipsis but I guess this is a subjective opinion here.

I want to raise something kind of related: I use pyright to check my Python code while coding and the checker raise 431 errors on PL code.

Using ellipsis fixes some of them. For example, consider the following code in training_loop.py:

class TrainerTrainLoopMixin:

    def __init__(self):
        self.on_epoch_end = None

    def run_training_epoch(self):

        # (...)

        # Pyright error:
        # 'self.on_epoch_end()' has type 'None' and is not callable
        self.on_epoch_end()

Adding typing fixes the error in run_training_epoch() but raises a new one in __init__():

class TrainerTrainLoopMixin:

    def __init__(self):

        # Pyright error:
        # Cannot assign member 'on_epoch_end' for type 'TrainerTrainLoopMixin'
        #   Expression of type 'None' cannot be assigned to member 'on_epoch_end' of class 'TrainerTrainLoopMixin'
        #     'None' cannot be assigned to '(*args, **kwargs) -> Any'
        self.on_epoch_end: Callable = None

    def run_training_epoch(self):

        # (...)

        # Not Pyright error.
        self.on_epoch_end()

Adding ellipsis fixes it:

class TrainerTrainLoopMixin:

    def __init__(self):

        # Not Pyright error.
        self.on_epoch_end: Callable = ...

    def run_training_epoch(self):

        # (...)

        # Not Pyright error.
        self.on_epoch_end()

Now to be honest I don't really know whether it's a hack that appear to work or a good practice (I am not very familiar with ellipsis.

@Borda
Copy link
Member Author

Borda commented Feb 26, 2020

@hadim does pyright exist also fro Ubuntu? found it here
I have replaced the ... just with the docs, could you check it ow, pls

@MattPainter01
Copy link
Contributor

I had the same understanding of ... for initialising variables as @hadim. If there are type annotations, type checkers understand that ellipsis is a placeholder, whereas None is not and so it sometimes warns of this. There is some talk of this in PEP484 for .pyi stub files but I couldn't find anything on our exact case anywhere.

An example from PyCharm with some types put in,
Screenshot from 2020-02-26 11-29-02

I think this is mostly just useful if we decide to start specifying types in the future.

For abstract methods, I can't find a particular consensus on pass vs ... vs empty but personally I prefer pass since it's used in most examples of abstract classes I could find.

@ethanwharris
Copy link
Member

Why not just:

class TrainerTrainLoopMixin:

    on_epoch_end: Callable

Then you could remove the __init__ all together and avoid the weirdness of assigning ... or None. See further discussion here.

@luiscape
Copy link
Contributor

Totally agree with @ethanwharris. Instead if just replacing None with ... let's use type annotations instead such as on_epoch_end: Callable. That makes it much more readable and helps us find bugs with Pytright & friends.

@Borda maybe we should create an epic or issue for adding type annotations to the core modules (I'm not sure there's one)?

@hadim
Copy link
Contributor

hadim commented Feb 26, 2020

@Borda Pyright is written in JS and is integrated out of the box in VSCode as an extension. You can also use it in Vim or on a command line: https://github.com/microsoft/pyright#installation

@Borda
Copy link
Member Author

Borda commented Feb 26, 2020

@Borda maybe we should create an epic or issue for adding type annotations to the core modules (I'm not sure there's one)?

we already have it :] #887

Copy link
Member

@ethanwharris ethanwharris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! :)

@Borda
Copy link
Member Author

Borda commented Feb 26, 2020

@luiscape ^^ ?

@williamFalcon williamFalcon merged commit 7beed7c into Lightning-AI:master Feb 27, 2020
@Borda Borda deleted the clean-trainer branch February 27, 2020 21:48
@Borda Borda modified the milestones: 0.7.1, 0.7.0 Feb 27, 2020
tullie pushed a commit to tullie/pytorch-lightning that referenced this pull request Apr 3, 2020
* Trainer cleanup

* update abstract

* remove ...

* remove __init__

* update mixin types

* update callbacks

* fix

* lower test acc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Is an improvement or enhancement ready PRs ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants