Skip to content

Commit d641fb3

Browse files
authored
Updated 'Up and Running with Composer' (#619)
1 parent 776eedf commit d641fb3

2 files changed

Lines changed: 63 additions & 108 deletions

File tree

notebooks/custom_method_tutorial.ipynb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"metadata": {},
3434
"outputs": [],
3535
"source": [
36-
"# Installing from a branch until main is updated\n",
3736
"!pip install mosaicml \n",
3837
"!pip install matplotlib"
3938
]

notebooks/up_and_running_with_composer.ipynb

100755100644
Lines changed: 63 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"metadata": {},
3030
"outputs": [],
3131
"source": [
32-
"!pip install git+https://github.com/mosaicml/composer.git@dev"
32+
"!pip install mosaicml "
3333
]
3434
},
3535
{
@@ -43,6 +43,8 @@
4343
"cell_type": "markdown",
4444
"metadata": {},
4545
"source": [
46+
"## Imports\n",
47+
"\n",
4648
"In this section we'll set up our workspace. We'll import the necessary packages, and setup our dataset and trainer. First, the imports:"
4749
]
4850
},
@@ -66,6 +68,8 @@
6668
"cell_type": "markdown",
6769
"metadata": {},
6870
"source": [
71+
"## Dataset & Dataloader\n",
72+
"\n",
6973
"Next, we instantiate our CIFAR10 dataset and dataloader. Composer has it's own CIFAR10 dataset and dataloaders, but this walkthrough focuses on how to use Composer's algorithms, so we'll stick with the Torchvision CIFAR10 and PyTorch dataloader for the sake of familiarity."
7074
]
7175
},
@@ -96,6 +100,8 @@
96100
"cell_type": "markdown",
97101
"metadata": {},
98102
"source": [
103+
"## Model\n",
104+
"\n",
99105
"Next, we create our model. We're using composer's built-in ResNet56. To use your own custom model, please see the [custom models tutorial](https://docs.mosaicml.com/en/v0.3.1/tutorials/adding_models_datasets.html#models)."
100106
]
101107
},
@@ -113,6 +119,8 @@
113119
"cell_type": "markdown",
114120
"metadata": {},
115121
"source": [
122+
"## Optimizer and Scheduler\n",
123+
"\n",
116124
"The trainer will handle instantiating the optimizer, but first we need to create the optimizer and LR scheduler. We're using [MosaicML's SGD with decoupled weight decay](https://arxiv.org/abs/1711.05101):"
117125
]
118126
},
@@ -134,52 +142,7 @@
134142
"cell_type": "markdown",
135143
"metadata": {},
136144
"source": [
137-
"We'll assume this is being run on Colab, which means training for hundreds of epochs would take a very long time. Instead we'll train our baseline model for three epochs. The first epoch will be linear warmup. We achieve this by instantiating a `WarmUpLRHparams` class."
138-
]
139-
},
140-
{
141-
"cell_type": "code",
142-
"execution_count": null,
143-
"metadata": {},
144-
"outputs": [],
145-
"source": [
146-
"## Having to manually compute the number of iterations is ungainly\n",
147-
"\n",
148-
"warmup = composer.optim.WarmUpLR(\n",
149-
" optimizer, # Optimizer\n",
150-
" warmup_iters=25, # Number of iterations to warmup over. 50k samples * 1 batch/2048 samples\n",
151-
" warmup_method=\"linear\", # Linear warmup\n",
152-
" warmup_factor=1e-4, # Initial LR = LR * warmup_factor\n",
153-
" interval=\"step\", # Update LR with stepwise granularity for superior results\n",
154-
")"
155-
]
156-
},
157-
{
158-
"cell_type": "markdown",
159-
"metadata": {},
160-
"source": [
161-
"We'll also use cosine decay for the next two epochs:"
162-
]
163-
},
164-
{
165-
"cell_type": "code",
166-
"execution_count": null,
167-
"metadata": {},
168-
"outputs": [],
169-
"source": [
170-
"## Seems like there's no way to have stepwise resolution for cosine decay without using CosineAnnealingLRHparams :(\n",
171-
"\n",
172-
"# decay = torch.optim.lr_scheduler.CosineAnnealingLR(\n",
173-
"# optimizer,\n",
174-
"# T_max=50 # 2 epochs == 50 steps\n",
175-
"# )"
176-
]
177-
},
178-
{
179-
"cell_type": "markdown",
180-
"metadata": {},
181-
"source": [
182-
"An LR schedule is provided to the trainer as a list of SchedulerHparams objects. In this case we just have one, but creating a more complex LR schedule is as simple as collecting the SchedulerHparams objects in a list."
145+
"We'll assume this is being run on Colab, which means training for hundreds of epochs would take a very long time. Instead we'll train our baseline model for three epochs. The first epoch will be linear warmup, followed by two epochs of constant LR. We achieve this by instantiating a `LinearWithWarmupLRHparams` class and calling its `initialize_object()` method."
183146
]
184147
},
185148
{
@@ -188,7 +151,12 @@
188151
"metadata": {},
189152
"outputs": [],
190153
"source": [
191-
"lr_schedule = [warmup] # Complex LR schedules achieved by [warmup_scheduler_object, decay_scheduler_object, ...]"
154+
"lr_scheduler_hparams = composer.optim.LinearWithWarmupLRHparams(\n",
155+
" warmup_time=\"1ep\", # Warm up over 1 epoch\n",
156+
" start_factor=1.0, # Flat LR schedule achieved by having start_factor == end_factor\n",
157+
" end_factor=1.0\n",
158+
")\n",
159+
"lr_scheduler = lr_scheduler_hparams.initialize_object() # This gets us the actual LR scheduler"
192160
]
193161
},
194162
{
@@ -211,8 +179,6 @@
211179
"metadata": {},
212180
"outputs": [],
213181
"source": [
214-
"## Need in-memory logging to store and plot results\n",
215-
"\n",
216182
"train_epochs = \"3ep\" # Train for 3 epochs because we're assuming Colab environment and hardware\n",
217183
"device = \"gpu\" # Train on the GPU\n",
218184
"\n",
@@ -222,13 +188,9 @@
222188
" eval_dataloader=test_dataloader,\n",
223189
" max_duration=train_epochs,\n",
224190
" optimizers=optimizer,\n",
225-
" schedulers=lr_schedule,\n",
191+
" schedulers=lr_scheduler,\n",
226192
" device=device\n",
227-
")\n",
228-
"\n",
229-
"\n",
230-
"\n",
231-
"# Would be nice to be able to plot something here"
193+
")"
232194
]
233195
},
234196
{
@@ -241,11 +203,7 @@
241203
{
242204
"cell_type": "code",
243205
"execution_count": null,
244-
"metadata": {
245-
"tags": [
246-
"trainer_fit"
247-
]
248-
},
206+
"metadata": {},
249207
"outputs": [],
250208
"source": [
251209
"start_time = time.perf_counter()\n",
@@ -321,7 +279,7 @@
321279
"source": [
322280
"prog_resize = composer.algorithms.ProgressiveResizing(\n",
323281
" initial_scale=.6, # Size of images at the beginning of training = .6 * default image size\n",
324-
" finetune_fraction=0.33 # Train on default size images for 0.5 of total training time.\n",
282+
" finetune_fraction=0.34 # Train on default size images for 0.34 of total training time.\n",
325283
")"
326284
]
327285
},
@@ -345,7 +303,7 @@
345303
"cell_type": "markdown",
346304
"metadata": {},
347305
"source": [
348-
"Now let's instantiate our model, optimizer, scheduler, and trainer again."
306+
"Now let's instantiate our model, optimizer, and trainer again. No need to instantiate our scheduler again because it's stateless!"
349307
]
350308
},
351309
{
@@ -363,23 +321,13 @@
363321
" weight_decay=2.0e-3\n",
364322
" )\n",
365323
"\n",
366-
"warmup = composer.optim.WarmUpLR(\n",
367-
" optimizer, # Optimizer\n",
368-
" warmup_iters=25, # Number of iterations to warmup over. 50k samples * 1 batch/2048 samples\n",
369-
" warmup_method=\"linear\", # Linear warmup\n",
370-
" warmup_factor=1e-4, # Initial LR = LR * warmup_factor\n",
371-
" interval=\"step\", # Update LR with stepwise granularity for superior results\n",
372-
")\n",
373-
"\n",
374-
"lr_schedule = [warmup]\n",
375-
"\n",
376324
"trainer = composer.trainer.Trainer(\n",
377325
" model=model,\n",
378326
" train_dataloader=train_dataloader,\n",
379327
" eval_dataloader=test_dataloader,\n",
380328
" max_duration=train_epochs,\n",
381329
" optimizers=optimizer,\n",
382-
" schedulers=lr_schedule,\n",
330+
" schedulers=lr_scheduler,\n",
383331
" device=device,\n",
384332
" algorithms=algorithms # Adding algorithms this time\n",
385333
")"
@@ -395,17 +343,14 @@
395343
{
396344
"cell_type": "code",
397345
"execution_count": null,
398-
"metadata": {
399-
"tags": [
400-
"trainer_fit"
401-
]
402-
},
346+
"metadata": {},
403347
"outputs": [],
404348
"source": [
405349
"start_time = time.perf_counter()\n",
406350
"trainer.fit()\n",
407351
"end_time = time.perf_counter()\n",
408-
"print(f\"It took {end_time - start_time:0.4f} seconds to train\")"
352+
"three_epochs_accelerated_time = end_time - start_time\n",
353+
"print(f\"It took {three_epochs_accelerated_time:0.4f} seconds to train\")"
409354
]
410355
},
411356
{
@@ -414,7 +359,7 @@
414359
"source": [
415360
"Again, the runtime will vary based on the instance, but we found that it took about a 0.43x-0.75x as long to train (a 1.3x-2.3x speedup, which corresponds to 90-400 seconds) relative to the baseline recipe without augmentations. We also found that validation accuracy was similar for the algorithm-enhanced and baseline recipes.\n",
416361
"\n",
417-
"Because ColOut and Progressive Resizing increase data throughput (i.e. more samples per sceond), we can train for more iterations in the same amount of wall clock time. Let's train for another epoch!"
362+
"Because ColOut and Progressive Resizing increase data throughput (i.e. more samples per sceond), we can train for more iterations in the same amount of wall clock time. Let's train our model for one additional epoch!"
418363
]
419364
},
420365
{
@@ -430,49 +375,60 @@
430375
"cell_type": "markdown",
431376
"metadata": {},
432377
"source": [
433-
"We'll need to set up our optimizer, scheduler, and trainer again:"
378+
"Resuming training means we'll need to use a flat LR schedule:"
434379
]
435380
},
436381
{
437382
"cell_type": "code",
438383
"execution_count": null,
439-
"metadata": {
440-
"tags": [
441-
"trainer_fit"
442-
]
443-
},
384+
"metadata": {},
385+
"outputs": [],
386+
"source": [
387+
"lr_scheduler_hparams = composer.optim.ConstantLRHparams()\n",
388+
"lr_scheduler = lr_scheduler_hparams.initialize_object() # This gets us the actual LR scheduler"
389+
]
390+
},
391+
{
392+
"cell_type": "markdown",
393+
"metadata": {},
394+
"source": [
395+
"And we can also get rid of progressive resizing (because we want to train on the full size images for this additional epoch), and the model already has blurpool enabled, so we don't need to pass that either:"
396+
]
397+
},
398+
{
399+
"cell_type": "code",
400+
"execution_count": null,
401+
"metadata": {},
402+
"outputs": [],
403+
"source": [
404+
"algorithms = [colout]"
405+
]
406+
},
407+
{
408+
"cell_type": "code",
409+
"execution_count": null,
410+
"metadata": {},
444411
"outputs": [],
445412
"source": [
446-
"optimizer = composer.optim.DecoupledSGDW(\n",
447-
" model.parameters(),\n",
448-
" lr=0.05,\n",
449-
" momentum=0.9,\n",
450-
" weight_decay=2.0e-3\n",
451-
" )\n",
452-
"\n",
453-
"# The Composer trainer defaults to cosine decay if no schedule is passed to it,\n",
454-
"# so let's creata constant LR schedule\n",
455-
"flat_schedule = composer.optim.ConstantLR(\n",
456-
" optimizer\n",
457-
")\n",
458-
"\n",
459-
"lr_schedule = [flat_schedule]\n",
460-
"\n",
461413
"trainer = composer.trainer.Trainer(\n",
462414
" model=model,\n",
463415
" train_dataloader=train_dataloader,\n",
464416
" eval_dataloader=test_dataloader,\n",
465-
" max_duration='5ba',\n",
417+
" max_duration=train_epochs,\n",
466418
" optimizers=optimizer,\n",
467-
" schedulers=lr_schedule,\n",
419+
" schedulers=lr_scheduler,\n",
468420
" device=device,\n",
469-
" algorithms=[colout, blurpool] # Adding algorithms this time\n",
421+
" algorithms=algorithms\n",
470422
")\n",
471423
"\n",
472424
"start_time = time.perf_counter()\n",
473425
"trainer.fit()\n",
426+
"\n",
474427
"end_time = time.perf_counter()\n",
475-
"print(f\"It took {end_time - start_time:0.4f} seconds to train\")"
428+
"final_epoch_accelerated_time = end_time - start_time\n",
429+
"# Time for four epochs = time for three epochs + time for fourth epoch\n",
430+
"four_epochs_accelerated_time = three_epochs_accelerated_time + final_epoch_accelerated_time\n",
431+
"print(f\"It took {four_epochs_accelerated_time:0.4f} seconds to train\")"
476432
]
477433
},
478434
{
@@ -508,7 +464,7 @@
508464
"accelerator": "GPU",
509465
"colab": {
510466
"collapsed_sections": [],
511-
"name": "Fast Training of ResNet56 on CIFAR10.ipynb",
467+
"name": "up_and_running_with_composer.ipynb",
512468
"provenance": [],
513469
"toc_visible": true
514470
},

0 commit comments

Comments
 (0)