|
1 | 1 | import copy |
2 | 2 | import os |
3 | 3 | import random |
4 | | -from typing import Iterable, Union |
| 4 | +from typing import Any, Dict, Iterable, Optional, Union |
5 | 5 |
|
6 | 6 | import numpy as np |
7 | 7 | import torch |
@@ -57,6 +57,8 @@ def __init__( |
57 | 57 | use_ema_warmup: bool = False, |
58 | 58 | inv_gamma: Union[float, int] = 1.0, |
59 | 59 | power: Union[float, int] = 2 / 3, |
| 60 | + model_cls: Optional[Any] = None, |
| 61 | + model_config: Dict[str, Any] = None, |
60 | 62 | **kwargs, |
61 | 63 | ): |
62 | 64 | """ |
@@ -123,6 +125,35 @@ def __init__( |
123 | 125 | self.power = power |
124 | 126 | self.optimization_step = 0 |
125 | 127 |
|
| 128 | + self.model_cls = model_cls |
| 129 | + self.model_config = model_config |
| 130 | + |
| 131 | + @classmethod |
| 132 | + def from_pretrained(cls, path, model_cls) -> "EMAModel": |
| 133 | + _, ema_kwargs = model_cls.load_config(path, return_unused_kwargs=True) |
| 134 | + model = model_cls.from_pretrained(path) |
| 135 | + |
| 136 | + ema_model = cls(model.parameters(), model_cls=model_cls, model_config=model.config) |
| 137 | + |
| 138 | + ema_model.load_state_dict(ema_kwargs) |
| 139 | + return ema_model |
| 140 | + |
| 141 | + def save_pretrained(self, path): |
| 142 | + if self.model_cls is None: |
| 143 | + raise ValueError("`save_pretrained` can only be used if `model_cls` was defined at __init__.") |
| 144 | + |
| 145 | + if self.model_config is None: |
| 146 | + raise ValueError("`save_pretrained` can only be used if `model_config` was defined at __init__.") |
| 147 | + |
| 148 | + model = self.model_cls.from_config(self.model_config) |
| 149 | + state_dict = self.state_dict() |
| 150 | + state_dict.pop("shadow_params", None) |
| 151 | + state_dict.pop("collected_params", None) |
| 152 | + |
| 153 | + model.register_to_config(**state_dict) |
| 154 | + self.copy_to(model.parameters()) |
| 155 | + model.save_pretrained(path) |
| 156 | + |
126 | 157 | def get_decay(self, optimization_step: int) -> float: |
127 | 158 | """ |
128 | 159 | Compute the decay factor for the exponential moving average. |
@@ -184,7 +215,7 @@ def copy_to(self, parameters: Iterable[torch.nn.Parameter]) -> None: |
184 | 215 | """ |
185 | 216 | parameters = list(parameters) |
186 | 217 | for s_param, param in zip(self.shadow_params, parameters): |
187 | | - param.data.copy_(s_param.data) |
| 218 | + param.data.copy_(s_param.to(param.device).data) |
188 | 219 |
|
189 | 220 | def to(self, device=None, dtype=None) -> None: |
190 | 221 | r"""Move internal buffers of the ExponentialMovingAverage to `device`. |
@@ -257,13 +288,15 @@ def load_state_dict(self, state_dict: dict) -> None: |
257 | 288 | if not isinstance(self.power, (float, int)): |
258 | 289 | raise ValueError("Invalid power") |
259 | 290 |
|
260 | | - self.shadow_params = state_dict["shadow_params"] |
261 | | - if not isinstance(self.shadow_params, list): |
262 | | - raise ValueError("shadow_params must be a list") |
263 | | - if not all(isinstance(p, torch.Tensor) for p in self.shadow_params): |
264 | | - raise ValueError("shadow_params must all be Tensors") |
| 291 | + shadow_params = state_dict.get("shadow_params", None) |
| 292 | + if shadow_params is not None: |
| 293 | + self.shadow_params = shadow_params |
| 294 | + if not isinstance(self.shadow_params, list): |
| 295 | + raise ValueError("shadow_params must be a list") |
| 296 | + if not all(isinstance(p, torch.Tensor) for p in self.shadow_params): |
| 297 | + raise ValueError("shadow_params must all be Tensors") |
265 | 298 |
|
266 | | - self.collected_params = state_dict["collected_params"] |
| 299 | + self.collected_params = state_dict.get("collected_params", None) |
267 | 300 | if self.collected_params is not None: |
268 | 301 | if not isinstance(self.collected_params, list): |
269 | 302 | raise ValueError("collected_params must be a list") |
|
0 commit comments