@@ -3,36 +3,111 @@ Hyperparameters
3
3
Lightning has utilities to interact seamlessly with the command line ArgumentParser
4
4
and plays well with the hyperparameter optimization framework of your choice.
5
5
6
- LightiningModule hparams
6
+ ArgumentParser
7
+ ^^^^^^^^^^^^^^
8
+ Lightning is designed to augment a lot of the functionality of the built-in Python ArgumentParser
9
+
10
+ .. code-block :: python
11
+
12
+ from argparse import ArgumentParser
13
+
14
+ parser = ArgumentParser()
15
+ parser.add_argument(' --layer_1_dim' , type = int , default = 128 )
16
+
17
+ args = parser.parse_args()
18
+
19
+ This allows you to call your program like so:
20
+
21
+ .. code-block :: bash
22
+
23
+ python trainer.py --layer_1_dim 64
24
+
25
+
26
+ Argparser Best Practices
7
27
^^^^^^^^^^^^^^^^^^^^^^^^
28
+ It is best practice to layer your arguments in three sections.
8
29
9
- Normally, we don't hard-code the values to a model. We usually use the command line to
10
- modify the network. The `Trainer ` can add all the available options to an ArgumentParser.
30
+ 1. Trainer args (gpus, num_nodes, etc...)
31
+ 2. Model specific arguments (layer_dim, num_layers, learning_rate, etc...)
32
+ 3. Program arguments (data_path, cluster_email, etc...)
33
+
34
+ We can do this as follows. First, in your LightningModule, define the arguments
35
+ specific to that module. Remember that data splits or data paths may also be specific to
36
+ a module (ie: if your project has a model that trains on Imagenet and another on CIFAR-10).
11
37
12
38
.. code-block :: python
13
39
40
+ class LitModel (LightningModule ):
41
+
42
+ @ staticmethod
43
+ def add_model_specific_args (parent_parser ):
44
+ parser = ArgumentParser(parents = [parent_parser], add_help = False )
45
+ parser.add_argument(' --encoder_layers' , type = int , default = 12 )
46
+ parser.add_argument(' --data_path' , type = str , default = ' /some/path' )
47
+ return parser
48
+
49
+ Now in your main trainer file, add the Trainer args, the program args, and add the model args
50
+
51
+ .. code-block :: python
52
+
53
+ # ----------------
54
+ # trainer_main.py
55
+ # ----------------
14
56
from argparse import ArgumentParser
15
57
16
58
parser = ArgumentParser()
17
59
18
- # parametrize the network
19
- parser.add_argument(' --layer_1_dim' , type = int , default = 128 )
20
- parser.add_argument(' --layer_2_dim' , type = int , default = 256 )
21
- parser.add_argument(' --batch_size' , type = int , default = 64 )
60
+ # add PROGRAM level args
61
+ parser.add_argument(' --conda_env' , type = str , default = ' some_name' )
62
+ parser.add_argument(' --notification_email' , type = str , default = ' [email protected] ' )
63
+
64
+ # add model specific args
65
+ parser = LitModel.add_model_specific_args(parser)
22
66
23
- # add all the available options to the trainer
67
+ # add all the available trainer options to argparse
68
+ # ie: now --gpus --num_nodes ... --fast_dev_run all work in the cli
24
69
parser = pl.Trainer.add_argparse_args(parser)
25
70
26
- args = parser.parse_args()
71
+ hparams = parser.parse_args()
27
72
28
- Now we can parametrize the LightningModule.
73
+ Now you can call run your program like so
74
+
75
+ .. code-block :: bash
76
+
77
+ python trainer_main.py --gpus 2 --num_nodes 2 --conda_env ' my_env' --encoder_layers 12
78
+
79
+ Finally, make sure to start the training like so:
80
+
81
+ .. code-block :: bash
82
+
83
+ hparams = parser.parse_args ()
84
+
85
+ # YES
86
+ model = LitModel(hparams)
87
+
88
+ # NO
89
+ # model = LitModel(learning_rate=hparams.learning_rate, ...)
90
+
91
+ # YES
92
+ trainer = Trainer.from_argparse_args(hparams, early_stopping_callback=...)
93
+
94
+ # NO
95
+ trainer = Trainer(gpus=hparams.gpus, ...)
96
+
97
+
98
+ LightiningModule hparams
99
+ ^^^^^^^^^^^^^^^^^^^^^^^^
100
+
101
+ Normally, we don't hard-code the values to a model. We usually use the command line to
102
+ modify the network and read those values in the LightningModule
29
103
30
104
.. code-block :: python
31
- :emphasize- lines: 5 ,6 ,7 ,12 ,14
32
105
33
106
class LitMNIST (pl .LightningModule ):
34
107
def __init__ (self , hparams ):
35
108
super ().__init__ ()
109
+
110
+ # do this to save all arguments in any logger (tensorboard)
36
111
self .hparams = hparams
37
112
38
113
self .layer_1 = torch.nn.Linear(28 * 28 , hparams.layer_1_dim)
@@ -49,86 +124,44 @@ Now we can parametrize the LightningModule.
49
124
def configure_optimizers (self ):
50
125
return Adam(self .parameters(), lr = self .hparams.learning_rate)
51
126
52
- hparams = parse_args()
53
- model = LitMNIST(hparams)
127
+ @ staticmethod
128
+ def add_model_specific_args (parent_parser ):
129
+ parser = ArgumentParser(parents = [parent_parser], add_help = False )
54
130
55
- .. note :: Bonus! if (hparams) is in your module, Lightning will save it into the checkpoint and restore your
56
- model using those hparams exactly.
131
+ parser.add_argument(' --layer_1_dim' , type = int , default = 128 )
132
+ parser.add_argument(' --layer_2_dim' , type = int , default = 256 )
133
+ parser.add_argument(' --batch_size' , type = int , default = 64 )
134
+ parser.add_argument(' --learning_rate' , type = float , default = 0.002 )
135
+ return parser
57
136
58
- And we can also add all the flags available in the Trainer to the Argparser.
137
+ Now pass in the params when you init your model
59
138
60
139
.. code-block :: python
61
140
62
- # add all the available Trainer options to the ArgParser
63
- parser = pl.Trainer.add_argparse_args(parser)
64
- args = parser.parse_args()
65
-
66
- And now you can start your program with
141
+ hparams = parse_args()
142
+ model = LitMNIST(hparams)
67
143
68
- .. code-block :: bash
144
+ The line `self.hparams = hparams ` is very special. This line assigns your hparams to the LightningModule.
145
+ This does two things:
69
146
70
- # now you can use any trainer flag
71
- $ python main.py --num_nodes 2 --gpus 8
147
+ 1. It adds them automatically to tensorboard logs under the hparams tab.
148
+ 2. Lightning will save those hparams to the checkpoint and use them to restore the module correctly.
72
149
73
150
Trainer args
74
151
^^^^^^^^^^^^
75
-
76
- It also gets annoying to map each argument into the Argparser. Luckily we have
77
- a default parser
152
+ To recap, add ALL possible trainer flags to the argparser and init the Trainer this way
78
153
79
154
.. code-block :: python
80
155
81
156
parser = ArgumentParser()
82
-
83
- # add all options available in the trainer such as (max_epochs, etc...)
84
157
parser = Trainer.add_argparse_args(parser)
158
+ hparams = parser.parse_args()
85
159
86
- We set up the main training entry point file like this:
87
-
88
- .. code-block :: python
89
-
90
- def main (args ):
91
- model = LitMNIST(hparams = args)
92
- trainer = Trainer(max_epochs = args.max_epochs)
93
- trainer.fit(model)
160
+ trainer = Trainer.from_argparse_args(hparams)
94
161
95
- if __name__ == ' __main__ ' :
96
- parser = ArgumentParser( )
162
+ # or if you need to pass in callbacks
163
+ trainer = Trainer.from_argparse_args(hparams, checkpoint_callback = ... , callbacks = [ ... ] )
97
164
98
- # adds all the trainer options as default arguments (like max_epochs)
99
- parser = Trainer.add_argparse_args(parser)
100
-
101
- # parametrize the network
102
- parser.add_argument(' --layer_1_dim' , type = int , default = 128 )
103
- parser.add_argument(' --layer_1_dim' , type = int , default = 256 )
104
- parser.add_argument(' --batch_size' , type = int , default = 64 )
105
- args = parser.parse_args()
106
-
107
- # train
108
- main(args)
109
-
110
- And now we can train like this:
111
-
112
- .. code-block :: bash
113
-
114
- $ python main.py --layer_1_dim 128 --layer_2_dim 256 --batch_size 64 --max_epochs 64
115
-
116
- But it would also be nice to pass in any arbitrary argument to the trainer.
117
- We can do it by changing how we init the trainer.
118
-
119
- .. code-block :: python
120
-
121
- def main (args ):
122
- model = LitMNIST(hparams = args)
123
-
124
- # makes all trainer options available from the command line
125
- trainer = Trainer.from_argparse_args(args)
126
-
127
- and now we can do this:
128
-
129
- .. code-block :: bash
130
-
131
- $ python main.py --gpus 1 --min_epochs 12 --max_epochs 64 --arbitrary_trainer_arg some_value
132
165
133
166
Multiple Lightning Modules
134
167
^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -173,7 +206,7 @@ Now we can allow each model to inject the arguments it needs in the main.py
173
206
model = LitMNIST(hparams = args)
174
207
175
208
model = LitMNIST(hparams = args)
176
- trainer = Trainer( max_epochs = args.max_epochs )
209
+ trainer = Trainer.from_argparse_args( args)
177
210
trainer.fit(model)
178
211
179
212
if __name__ == ' __main__' :
@@ -182,6 +215,8 @@ Now we can allow each model to inject the arguments it needs in the main.py
182
215
183
216
# figure out which model to use
184
217
parser.add_argument(' --model_name' , type = str , default = ' gan' , help = ' gan or mnist' )
218
+
219
+ # THIS LINE IS KEY TO PULL THE MODEL NAME
185
220
temp_args = parser.parse_known_args()
186
221
187
222
# let the model add what it wants
0 commit comments