A custom callback for weight averaging over the top-K checkpoints. This can be useful to smooth out fluctuations in weights across the best-performing models and can lead to improved generalization performance at inference time. Behavior: - Loads the state_dict from each of the
| 22 | |
| 23 | @typechecked |
| 24 | class AverageCheckpointsCallback(Callback): |
| 25 | """A custom callback for weight averaging over the top-K checkpoints. |
| 26 | |
| 27 | This can be useful to smooth out fluctuations in weights across the best-performing |
| 28 | models and can lead to improved generalization performance at inference time. |
| 29 | |
| 30 | Behavior: |
| 31 | - Loads the state_dict from each of the top-K checkpoints saved by given |
| 32 | ModelCheckpoint callbacks. |
| 33 | - Averages the model parameters (keys starting with `model.`). |
| 34 | - Ignores or simply accumulates integer-type parameters |
| 35 | (e.g., BatchNorm's `num_batches_tracked`). |
| 36 | - Saves the averaged model as a `.pth` file in `output_dir`. |
| 37 | |
| 38 | Args: |
| 39 | output_dir (str or Path): |
| 40 | The directory where the averaged model will be saved. |
| 41 | best_ckpt_callbacks (List[ModelCheckpoint]): |
| 42 | A list of ModelCheckpoint callbacks whose top-K checkpoints will be used |
| 43 | for averaging. Each callback must have `best_k_models` populated. |
| 44 | |
| 45 | Notes: |
| 46 | - Only keys that start with `model.` are included in the averaging. |
| 47 | - The final filename will be: |
| 48 | `{monitor_name}.ave_{K}best.pth` |
| 49 | - This callback only runs on the global rank 0 process |
| 50 | (for distributed training). |
| 51 | |
| 52 | Example: |
| 53 | >>> avg_ckpt_cb = AverageCheckpointsCallback( |
| 54 | ... output_dir="checkpoints/", |
| 55 | ... best_ckpt_callbacks=[val_loss_ckpt_cb, acc_ckpt_cb] |
| 56 | ... ) |
| 57 | >>> trainer = Trainer(callbacks=[avg_ckpt_cb]) |
| 58 | """ |
| 59 | |
| 60 | def __init__(self, output_dir, best_ckpt_callbacks): |
| 61 | """Initialize AverageCheckpointsCallback object.""" |
| 62 | self.output_dir = output_dir |
| 63 | self.best_ckpt_callbacks = best_ckpt_callbacks |
| 64 | |
| 65 | def on_validation_end(self, trainer, pl_module): |
| 66 | """At the end of validation, average the top-K checkpoints and save.""" |
| 67 | if trainer.is_global_zero: |
| 68 | for ckpt_callback in self.best_ckpt_callbacks: |
| 69 | checkpoints = list(ckpt_callback.best_k_models.keys()) |
| 70 | if not checkpoints: |
| 71 | continue |
| 72 | |
| 73 | avg_state_dict = None |
| 74 | reference_keys = None |
| 75 | for ckpt_path in checkpoints: |
| 76 | state_dict = torch.load( |
| 77 | ckpt_path, map_location="cpu", weights_only=False |
| 78 | ) |
| 79 | |
| 80 | # for deepspeed checkpoints |
| 81 | if "module" in state_dict: |
no outgoing calls
searching dependent graphs…