-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
How to change optimizer and lr scheduler in the middle of training? #3095
Comments
Hi! thanks for your contribution!, great first issue! |
I would suggest doing class PreFineLightningModule(pl.LightningModule):
def __init__(self, mode='pre_train'):
super().__init__()
self.mode = mode
# define other params
def _configure_optim_backbone(self):
# return optimizers and schedulers for pre-training
optimizer = # pre-train optimizer
scheduler = # pre-train scheduler
return [optimizer], [optimizer]
def _configure_optim_finetune(self):
# return optimizers and scheduler for fine-tine
optimizer = # fine-tune optimizer
scheduler = # fine-tune scheduler
return [optimizer], [scheduler]
def configure_optimizers(self):
if self.mode == 'pre_train':
return self._configure_optim_backbone()
elif self.mode == 'fine_tune':
return self._configure_optim_finetune()
total_epochs=15 # can be anything
# Pre Train
model = PreFineLightningModule(mode='pre_train')
freeze_backbone(model)
trainer = Trainer(max_epochs=10)
trainer.fit(model)
# Fine Tune
model = PreFineLightningModule.load_from_checkpoint(saved_model_checkpoint, mode='fine_tune')
unfreeze_layers(model)
trainer = Trainer(max_epochs=total_epochs-10)
trainer.fit(model) |
Thanks so much for your response! I was hoping to avoid that since it would force me to write a lot more boilerplate code in my project to keep the whole training process automated, configurable, and model agnostic. Why doesn't PL provide an api to replace instances of optimizers and schedulers? Have you guys considered that? |
yeah, you can do that with a callback too using |
What would be ideal for me is to be able to replace optimizer and scheduler from within the |
you can try the
set: class SomeCallback(Callback):
def on_train_epoch_start(self, trainer. pl_module):
if trainer.current_epoch == 10:
trainer.optimizers = [new_optimizers]
trainer.lr_schedulers = trainer.configure_schedulers([new_schedulers])
trainer.optimizer_frequencies = [] # or optimizers frequencies if you have any
trainer = Trainer(callbacks=[SomeCallback()], ...) I think this should work. |
Thanks so much! This looks very promising, I couldn't tell from the docs that the I'll try this out and report back. |
fixed the link |
This solution worked great for me. It's important to note that the Thanks again @rohitgr7 for the help! |
Hi @rohitgr7, how to change optimizer and LR scheduler if I am using This is my sample def configure_optimizers(self):
optimizer = optim.Adam(
filter(
lambda p: p.requires_grad,
self.net.parameters()),
lr=self.lr,
weight_decay=self.weight_decay)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(
optimizer,
mode="min",
factor=0.1,
patience=self.scheduler_patience,
cooldown=3,
)
return {
"optimizer": optimizer,
"lr_scheduler": {
"scheduler": scheduler,
"monitor": "val/loss",
"interval": "epoch",
"frequency": 1,
},
} However, how to set this monitor, interval while using on_train_start in the middle of training? def on_train_start(self, trainer, pl_module) -> None:
if trainer.current_epoch == self._unfreeze_at_epoch:
print("unfreeze and add param group...")
pl_module.net.freeze_backbone(False)
new_optimizer = optim.Adam(
filter(
lambda p: p.requires_grad,
pl_module.net.parameters()),
lr=pl_module.lr,
weight_decay=pl_module.weight_decay)
new_schedulers = optim.lr_scheduler.ReduceLROnPlateau(
new_optimizer,
mode="min",
factor=0.1,
patience=pl_module.scheduler_patience,
cooldown=3,
)
trainer.optimizers = [new_optimizer]
trainer.lr_schedulers = [new_schedulers]
trainer.optimizer_frequencies =1 Thanks in advance |
I just tried the callback solution and found that you cannot set
but need to do this
to properly set the schedulers with monitor and add other default configurations |
What should I do in 2.0.2 ? Why we can't have a function like configure_optimizers()? |
def setup_optimizers(self, trainer: "pl.Trainer") -> None:
"""Creates optimizers and schedulers.
Args:
trainer: the Trainer, these optimizers should be connected to
"""
if trainer.state.fn != TrainerFn.FITTING:
return
assert self.lightning_module is not None
self.optimizers, self.lr_scheduler_configs = _init_optimizers_and_lr_schedulers(self.lightning_module)
def setup(self, trainer: "pl.Trainer") -> None:
"""Setup plugins for the trainer fit and creates optimizers.
Args:
trainer: the trainer instance
"""
assert self.accelerator is not None
self.accelerator.setup(trainer)
self.setup_optimizers(trainer)
self.setup_precision_plugin()
_optimizers_to_device(self.optimizers, self.root_device) So, just self.trainer.strategy.setup(self.trainer)? |
You could use only the |
What is your question?
I need to train a model with a pre-trained backbone. For the first 10 epochs, I want to have the backbone completely frozen (ie. not touched by the optimizer). After epoch 10, I want to start training certain layers of the backbone. In regular pytorch, I would instantiate a new optimizer adding the backbone params that I want to train. Then I'd swap both optimizer and lr_scheduler.
What's the recommended way to do something like this in PL?
The text was updated successfully, but these errors were encountered: