-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Remove argparse utils #16708
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
Merged
Merged
Remove argparse utils #16708
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
0088397
main removals
awaelchli fda5eeb
docs
awaelchli 63d64ee
update example
awaelchli 36f29b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] d437782
fix mypy
awaelchli 879722f
removal
awaelchli 2ea152f
remove
awaelchli 588f669
removal
awaelchli dde285f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 496c2b0
changelog
awaelchli 4e27b0e
Merge branch 'master' into removal/argparse
awaelchli 78c386b
merge
awaelchli 21b9d19
missing imports
awaelchli 4b9e66f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 3d11a05
blabla
awaelchli d63acac
Merge remote-tracking branch 'origin/removal/argparse' into removal/a…
awaelchli d2a526d
x
awaelchli 6c38857
Merge branch 'master' into removal/argparse
carmocca eea51a6
Update docs/source-pytorch/common/trainer.rst
awaelchli 151b18e
Update docs/source-pytorch/common/trainer.rst
awaelchli 2940480
collapse model-specific args
awaelchli 5d979c4
remove _ARGPARSE_CLS
awaelchli 0625c77
remove more parsing utils
awaelchli 4a7c34a
simple argparse docs
awaelchli 4956e62
restore
awaelchli 170c9de
Merge branch 'master' into removal/argparse
Borda 3c5e4d8
Merge branch 'master' into removal/argparse
Borda 6a9c61d
no need for doctest
awaelchli 8caa93b
fix reference
awaelchli 93d2aa2
Merge branch 'master' into removal/argparse
awaelchli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -250,7 +250,6 @@ utilities | |
:toctree: api | ||
:nosignatures: | ||
|
||
argparse | ||
data | ||
deepspeed | ||
distributed | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,209 +1,52 @@ | ||
:orphan: | ||
|
||
.. testsetup:: * | ||
Configure hyperparameters from the CLI | ||
-------------------------------------- | ||
|
||
from argparse import ArgumentParser, Namespace | ||
You can use any CLI tool you want with Lightning. | ||
For beginners, we recommand using Python's built-in argument parser. | ||
|
||
sys.argv = ["foo"] | ||
|
||
Configure hyperparameters from the CLI (legacy) | ||
----------------------------------------------- | ||
---- | ||
|
||
.. warning:: | ||
|
||
This is the documentation for the use of Python's ``argparse`` to implement a CLI. This approach is no longer | ||
recommended, and people are encouraged to use the new `LightningCLI <../cli/lightning_cli.html>`_ class instead. | ||
|
||
|
||
Lightning has utilities to interact seamlessly with the command line ``ArgumentParser`` | ||
and plays well with the hyperparameter optimization framework of your choice. | ||
|
||
---------- | ||
|
||
ArgumentParser | ||
^^^^^^^^^^^^^^ | ||
Lightning is designed to augment a lot of the functionality of the built-in Python ArgumentParser | ||
|
||
.. testcode:: | ||
|
||
from argparse import ArgumentParser | ||
|
||
parser = ArgumentParser() | ||
parser.add_argument("--layer_1_dim", type=int, default=128) | ||
args = parser.parse_args() | ||
|
||
This allows you to call your program like so: | ||
|
||
.. code-block:: bash | ||
|
||
python trainer.py --layer_1_dim 64 | ||
|
||
---------- | ||
|
||
Argparser Best Practices | ||
^^^^^^^^^^^^^^^^^^^^^^^^ | ||
It is best practice to layer your arguments in three sections. | ||
The :class:`~argparse.ArgumentParser` is a built-in feature in Python that let's you build CLI programs. | ||
You can use it to make hyperparameters and other training settings available from the command line: | ||
|
||
1. Trainer args (``accelerator``, ``devices``, ``num_nodes``, etc...) | ||
2. Model specific arguments (``layer_dim``, ``num_layers``, ``learning_rate``, etc...) | ||
3. Program arguments (``data_path``, ``cluster_email``, etc...) | ||
|
||
| | ||
|
||
We can do this as follows. First, in your ``LightningModule``, define the arguments | ||
specific to that module. Remember that data splits or data paths may also be specific to | ||
a module (i.e.: if your project has a model that trains on Imagenet and another on CIFAR-10). | ||
|
||
.. testcode:: | ||
|
||
class LitModel(LightningModule): | ||
@staticmethod | ||
def add_model_specific_args(parent_parser): | ||
parser = parent_parser.add_argument_group("LitModel") | ||
parser.add_argument("--encoder_layers", type=int, default=12) | ||
parser.add_argument("--data_path", type=str, default="/some/path") | ||
return parent_parser | ||
|
||
Now in your main trainer file, add the ``Trainer`` args, the program args, and add the model args | ||
|
||
.. testcode:: | ||
.. code-block:: python | ||
|
||
# ---------------- | ||
# trainer_main.py | ||
# ---------------- | ||
from argparse import ArgumentParser | ||
|
||
parser = ArgumentParser() | ||
|
||
# add PROGRAM level args | ||
parser.add_argument("--conda_env", type=str, default="some_name") | ||
parser.add_argument("--notification_email", type=str, default="[email protected]") | ||
|
||
# add model specific args | ||
parser = LitModel.add_model_specific_args(parser) | ||
# Trainer arguments | ||
parser.add_argument("--devices", type=int, default=2) | ||
|
||
# add all the available trainer options to argparse | ||
# ie: now --accelerator --devices --num_nodes ... --fast_dev_run all work in the cli | ||
parser = Trainer.add_argparse_args(parser) | ||
# Hyperparameters for the model | ||
parser.add_argument("--layer_1_dim", type=int, default=128) | ||
|
||
# Parse the user inputs and defaults (returns a argparse.Namespace) | ||
args = parser.parse_args() | ||
|
||
Now you can call run your program like so: | ||
|
||
.. code-block:: bash | ||
|
||
python trainer_main.py --accelerator 'gpu' --devices 2 --num_nodes 2 --conda_env 'my_env' --encoder_layers 12 | ||
# Use the parsed arguments in your program | ||
trainer = Trainer(devices=args.devices) | ||
model = MyModel(layer_1_dim=args.layer_1_dim) | ||
|
||
Finally, make sure to start the training like so: | ||
|
||
.. code-block:: python | ||
|
||
# init the trainer like this | ||
trainer = Trainer.from_argparse_args(args, early_stopping_callback=...) | ||
This allows you to call your program like so: | ||
|
||
# NOT like this | ||
trainer = Trainer(accelerator=hparams.accelerator, devices=hparams.devices, ...) | ||
.. code-block:: bash | ||
|
||
# init the model with Namespace directly | ||
model = LitModel(args) | ||
python trainer.py --layer_1_dim 64 --devices 1 | ||
|
||
# or init the model with all the key-value pairs | ||
dict_args = vars(args) | ||
model = LitModel(**dict_args) | ||
---- | ||
|
||
---------- | ||
|
||
Trainer args | ||
LightningCLI | ||
^^^^^^^^^^^^ | ||
To recap, add ALL possible trainer flags to the argparser and init the ``Trainer`` this way | ||
|
||
.. code-block:: python | ||
|
||
parser = ArgumentParser() | ||
parser = Trainer.add_argparse_args(parser) | ||
hparams = parser.parse_args() | ||
|
||
trainer = Trainer.from_argparse_args(hparams) | ||
|
||
# or if you need to pass in callbacks | ||
trainer = Trainer.from_argparse_args(hparams, enable_checkpointing=..., callbacks=[...]) | ||
|
||
---------- | ||
|
||
Multiple Lightning Modules | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
We often have multiple Lightning Modules where each one has different arguments. Instead of | ||
polluting the ``main.py`` file, the ``LightningModule`` lets you define arguments for each one. | ||
|
||
.. testcode:: | ||
|
||
class LitMNIST(LightningModule): | ||
def __init__(self, layer_1_dim, **kwargs): | ||
super().__init__() | ||
self.layer_1 = nn.Linear(28 * 28, layer_1_dim) | ||
|
||
@staticmethod | ||
def add_model_specific_args(parent_parser): | ||
parser = parent_parser.add_argument_group("LitMNIST") | ||
parser.add_argument("--layer_1_dim", type=int, default=128) | ||
return parent_parser | ||
|
||
.. testcode:: | ||
|
||
class GoodGAN(LightningModule): | ||
def __init__(self, encoder_layers, **kwargs): | ||
super().__init__() | ||
self.encoder = Encoder(layers=encoder_layers) | ||
|
||
@staticmethod | ||
def add_model_specific_args(parent_parser): | ||
parser = parent_parser.add_argument_group("GoodGAN") | ||
parser.add_argument("--encoder_layers", type=int, default=12) | ||
return parent_parser | ||
|
||
|
||
Now we can allow each model to inject the arguments it needs in the ``main.py`` | ||
|
||
.. code-block:: python | ||
|
||
def main(args): | ||
dict_args = vars(args) | ||
|
||
# pick model | ||
if args.model_name == "gan": | ||
model = GoodGAN(**dict_args) | ||
elif args.model_name == "mnist": | ||
model = LitMNIST(**dict_args) | ||
|
||
trainer = Trainer.from_argparse_args(args) | ||
trainer.fit(model) | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = ArgumentParser() | ||
parser = Trainer.add_argparse_args(parser) | ||
|
||
# figure out which model to use | ||
parser.add_argument("--model_name", type=str, default="gan", help="gan or mnist") | ||
|
||
# THIS LINE IS KEY TO PULL THE MODEL NAME | ||
temp_args, _ = parser.parse_known_args() | ||
|
||
# let the model add what it wants | ||
if temp_args.model_name == "gan": | ||
parser = GoodGAN.add_model_specific_args(parser) | ||
elif temp_args.model_name == "mnist": | ||
parser = LitMNIST.add_model_specific_args(parser) | ||
|
||
args = parser.parse_args() | ||
|
||
# train | ||
main(args) | ||
|
||
and now we can train MNIST or the GAN using the command line interface! | ||
|
||
.. code-block:: bash | ||
|
||
$ python main.py --model_name gan --encoder_layers 24 | ||
$ python main.py --model_name mnist --layer_1_dim 128 | ||
Python's argument parser works well for simple use cases, but it can become cumbersome to maintain for larger projects. | ||
For example, every time you add, change, or delete an argument from your model, you will have to add, edit, or remove the corresponding ``parser.add_argument`` code. | ||
The :doc:`Lightning CLI <../cli/lightning_cli>` provides a seamless integration with the Trainer and LightningModule for which the CLI arguments get generated automatically for you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.