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

Refactor model and metrics #100

Merged
merged 55 commits into from
May 18, 2023
Merged

Refactor model and metrics #100

merged 55 commits into from
May 18, 2023

Conversation

jasonjewik
Copy link
Collaborator

I'll come back to add examples later of how to use the code, and I'm really spotty on documentation, but I'm opening the PR so folks can take a look. Primary changes are such:

  • Much easier to load presets (which grabs the model, optimizer, and LR scheduler [if it exists])
  • Metrics are now their own subpackage
  • Transforms are separated from metrics because IMO the metrics should not have to know they are transforming their inputs

@jasonjewik jasonjewik linked an issue May 10, 2023 that may be closed by this pull request
@jasonjewik
Copy link
Collaborator Author

See Untitled.ipynb which can be run on MINT1 for some examples.

@jasonjewik
Copy link
Collaborator Author

TODO: Vision Transformer is broken. Up to you whether I should fix that in this PR or in a future one.

@prakhar6sharma
Copy link
Collaborator

TODO: Vision Transformer is broken. Up to you whether I should fix that in this PR or in a future one.

Let's leave this for a future PR.

@prakhar6sharma
Copy link
Collaborator

@jasonjewik thanks a lot for this crucial PR. I have done an initial review for the transforms, metrics and loaders.py and added some comments. Most of them include actionable suggestions whereas for a few I have raised the problem without going over the solution(because I couldn't think of a solution).

I am starting my review on the models/ but in the meantime, please address these comments at a time of your convenience.

@jasonjewik
Copy link
Collaborator Author

@prakhar6sharma I don't see your comments - perhaps you did not submit the review?

src/climate_learn/loaders.py Outdated Show resolved Hide resolved
src/climate_learn/loaders.py Show resolved Hide resolved
src/climate_learn/loaders.py Show resolved Hide resolved
src/climate_learn/loaders.py Show resolved Hide resolved
src/climate_learn/loaders.py Outdated Show resolved Hide resolved
src/climate_learn/metrics/metrics.py Show resolved Hide resolved
src/climate_learn/metrics/__init__.py Show resolved Hide resolved
src/climate_learn/metrics/utils.py Outdated Show resolved Hide resolved
src/climate_learn/trainer.py Show resolved Hide resolved
src/climate_learn/trainer.py Outdated Show resolved Hide resolved
@jasonjewik
Copy link
Collaborator Author

Other than these changes, I feel that each model under hub/ such as Climatology, Interpolation, LinearRegression, ResNet, etc should have an attribute named in_vars and out_vars other than in_channels and out_channels.

I believe that it would allow us to implement some crucial checks such as in the case of Persistence, we need the out_vars to be subset of in_vars. Using just in_channels and out_channels it's not possible to do so. Similarly, in the case of Interpolation we can ensure that in_vars are same as out_vars.

I disagree. For clean abstraction of code, the models should not be aware of the variable names. It is the loader functions' responsibility to ensure that the requested model is legal.

Copy link
Collaborator

@prakhar6sharma prakhar6sharma left a comment

Choose a reason for hiding this comment

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

Added some more comments.

tests/loaders/utils.py Outdated Show resolved Hide resolved
src/climate_learn/models/module.py Show resolved Hide resolved
src/climate_learn/metrics/functional.py Outdated Show resolved Hide resolved
@prakhar6sharma
Copy link
Collaborator

Other than these changes, I feel that each model under hub/ such as Climatology, Interpolation, LinearRegression, ResNet, etc should have an attribute named in_vars and out_vars other than in_channels and out_channels.
I believe that it would allow us to implement some crucial checks such as in the case of Persistence, we need the out_vars to be subset of in_vars. Using just in_channels and out_channels it's not possible to do so. Similarly, in the case of Interpolation we can ensure that in_vars are same as out_vars.

I disagree. For clean abstraction of code, the models should not be aware of the variable names. It is the loader functions' responsibility to ensure that the requested model is legal.

Do we assume that the user would create the models using the loader functions only?

  • If yes, then I completely agree with you.
  • If not, then we are allowing silent bugs to happen.
    -- Let me give an example of Persistence, let's say the len(in_vars) is same as len(out_vars) but out_vars is not a subset of in_vars. In this case, Persistence would work fine but logically the output would be incorrect.
    -- Moreover, we should support Persistence for cases where out_vars is a subset of in_vars. Unfortunately, the current attributes of the class doesn't allow it to know which channels of input are present in output also.
    -- Similarly, I can also build an example for Interpolation.

@jasonjewik
Copy link
Collaborator Author

Do we assume that the user would create the models using the loader functions only?

  • If yes, then I completely agree with you.
  • If not, then we are allowing silent bugs to happen.
    -- Let me give an example of Persistence, let's say the len(in_vars) is same as len(out_vars) but out_vars is not a subset of in_vars. In this case, Persistence would work fine but logically the output would be incorrect.
    -- Moreover, we should support Persistence for cases where out_vars is a subset of in_vars. Unfortunately, the current attributes of the class doesn't allow it to know which channels of input are present in output also.
    -- Similarly, I can also build an example for Interpolation.

Yes. I assume the user to create models with the loader function only. Side-by-side comparison of the number of lines of code required, assuming the data module dm has already been created, setup, etc. shows that it's the same.

# using the loaders
import climate_learn as cl
model, optimizer, lr_scheduler = cl.load_preset("forecasting", dm, "persistence")

# do it yourself
from climate_learn.models.hub import Persistence
model = Persistence()

Besides, as the user wishes to load more models, the first approach scales better since they don't have to add a new import for each model. If the user chooses to do the second route (load it manually) and something like what you describe happens, IMO it is the user's fault, not the code's fault. Happy to discuss further.

@prakhar6sharma
Copy link
Collaborator

Yes. I assume the user to create models with the loader function only. Side-by-side comparison of the number of lines of code required, assuming the data module dm has already been created, setup, etc. shows that it's the same.

# using the loaders
import climate_learn as cl
model, optimizer, lr_scheduler = cl.load_preset("forecasting", dm, "persistence")

# do it yourself
from climate_learn.models.hub import Persistence
model = Persistence()

Besides, as the user wishes to load more models, the first approach scales better since they don't have to add a new import for each model. If the user chooses to do the second route (load it manually) and something like what you describe happens, IMO it is the user's fault, not the code's fault. Happy to discuss further.

Looks good to me. It's just that the loaders.py would need to be changed every time you add a model.

Also, can you please add support for Persistence for cases where out_vars is a subset of in_vars.

@prakhar6sharma prakhar6sharma self-requested a review May 18, 2023 01:52
Copy link
Collaborator

@prakhar6sharma prakhar6sharma left a comment

Choose a reason for hiding this comment

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

Hopefully, this one should be the last request change.

src/climate_learn/models/module.py Show resolved Hide resolved
Copy link
Collaborator

@prakhar6sharma prakhar6sharma left a comment

Choose a reason for hiding this comment

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

Hopefully, this one should be the last request change.

Copy link
Collaborator

@prakhar6sharma prakhar6sharma left a comment

Choose a reason for hiding this comment

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

Looks good to me!!!

@jasonjewik jasonjewik merged commit 594ee7d into main May 18, 2023
6 checks passed
@jasonjewik jasonjewik deleted the model-refactor branch May 18, 2023 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Model Refactor
2 participants