CoolFace
Apppublic

tohid4n/PartCrafter

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
train_utils.py184 linesDownload Raw Back to utils
1from src.utils.typing_utils import *2 3import os4from omegaconf import OmegaConf5 6from torch import optim7from torch.optim import lr_scheduler8from diffusers.training_utils import *9from diffusers.optimization import get_scheduler10 11# https://github.com/huggingface/diffusers/pull/9812: fix `self.use_ema_warmup`12class MyEMAModel(EMAModel):13    """14    Exponential Moving Average of models weights15    """16 17    def __init__(18        self,19        parameters: Iterable[torch.nn.Parameter],20        decay: float = 0.9999,21        min_decay: float = 0.0,22        update_after_step: int = 0,23        use_ema_warmup: bool = False,24        inv_gamma: Union[float, int] = 1.0,25        power: Union[float, int] = 2 / 3,26        foreach: bool = False,27        model_cls: Optional[Any] = None,28        model_config: Dict[str, Any] = None,29        **kwargs,30    ):31        """32        Args:33            parameters (Iterable[torch.nn.Parameter]): The parameters to track.34            decay (float): The decay factor for the exponential moving average.35            min_decay (float): The minimum decay factor for the exponential moving average.36            update_after_step (int): The number of steps to wait before starting to update the EMA weights.37            use_ema_warmup (bool): Whether to use EMA warmup.38            inv_gamma (float):39                Inverse multiplicative factor of EMA warmup. Default: 1. Only used if `use_ema_warmup` is True.40            power (float): Exponential factor of EMA warmup. Default: 2/3. Only used if `use_ema_warmup` is True.41            foreach (bool): Use torch._foreach functions for updating shadow parameters. Should be faster.42            device (Optional[Union[str, torch.device]]): The device to store the EMA weights on. If None, the EMA43                        weights will be stored on CPU.44 45        @crowsonkb's notes on EMA Warmup:46            If gamma=1 and power=1, implements a simple average. gamma=1, power=2/3 are good values for models you plan47            to train for a million or more steps (reaches decay factor 0.999 at 31.6K steps, 0.9999 at 1M steps),48            gamma=1, power=3/4 for models you plan to train for less (reaches decay factor 0.999 at 10K steps, 0.999949            at 215.4k steps).50        """51 52        if isinstance(parameters, torch.nn.Module):53            deprecation_message = (54                "Passing a `torch.nn.Module` to `ExponentialMovingAverage` is deprecated. "55                "Please pass the parameters of the module instead."56            )57            deprecate(58                "passing a `torch.nn.Module` to `ExponentialMovingAverage`",59                "1.0.0",60                deprecation_message,61                standard_warn=False,62            )63            parameters = parameters.parameters()64 65            # # set use_ema_warmup to True if a torch.nn.Module is passed for backwards compatibility66            # use_ema_warmup = True67 68        if kwargs.get("max_value", None) is not None:69            deprecation_message = "The `max_value` argument is deprecated. Please use `decay` instead."70            deprecate("max_value", "1.0.0", deprecation_message, standard_warn=False)71            decay = kwargs["max_value"]72 73        if kwargs.get("min_value", None) is not None:74            deprecation_message = "The `min_value` argument is deprecated. Please use `min_decay` instead."75            deprecate("min_value", "1.0.0", deprecation_message, standard_warn=False)76            min_decay = kwargs["min_value"]77 78        parameters = list(parameters)79        self.shadow_params = [p.clone().detach() for p in parameters]80 81        if kwargs.get("device", None) is not None:82            deprecation_message = "The `device` argument is deprecated. Please use `to` instead."83            deprecate("device", "1.0.0", deprecation_message, standard_warn=False)84            self.to(device=kwargs["device"])85 86        self.temp_stored_params = None87 88        self.decay = decay89        self.min_decay = min_decay90        self.update_after_step = update_after_step91        self.use_ema_warmup = use_ema_warmup92        self.inv_gamma = inv_gamma93        self.power = power94        self.optimization_step = 095        self.cur_decay_value = None  # set in `step()`96        self.foreach = foreach97 98        self.model_cls = model_cls99        self.model_config = model_config100 101    def get_decay(self, optimization_step: int) -> float:102        """103        Compute the decay factor for the exponential moving average.104        """105        step = max(0, optimization_step - self.update_after_step - 1)106 107        if step <= 0:108            return 0.0109 110        if self.use_ema_warmup:111            cur_decay_value = 1 - (1 + step / self.inv_gamma) ** -self.power112        else:113            # cur_decay_value = (1 + step) / (10 + step)114            cur_decay_value = self.decay115 116        cur_decay_value = min(cur_decay_value, self.decay)117        # make sure decay is not smaller than min_decay118        cur_decay_value = max(cur_decay_value, self.min_decay)119        return cur_decay_value120 121def get_configs(yaml_path: str, cli_configs: List[str]=[], **kwargs) -> DictConfig:122    yaml_configs = OmegaConf.load(yaml_path)123    cli_configs = OmegaConf.from_cli(cli_configs)124 125    configs = OmegaConf.merge(yaml_configs, cli_configs, kwargs)126    OmegaConf.resolve(configs)  # resolve ${...} placeholders127    return configs128 129def get_optimizer(name: str, params: Parameter, **kwargs) -> Optimizer:130    if name == "adamw":131        return optim.AdamW(params=params, **kwargs)132    else:133        raise NotImplementedError(f"Not implemented optimizer: {name}")134 135def get_lr_scheduler(name: str, optimizer: Optimizer, **kwargs) -> LRScheduler:136    if name == "one_cycle":137        return lr_scheduler.OneCycleLR(138            optimizer,139            max_lr=kwargs["max_lr"],140            total_steps=kwargs["total_steps"],141            pct_start=kwargs["pct_start"],142        )143    elif name == "cosine_warmup":144        return get_scheduler(145            "cosine", optimizer,146            num_warmup_steps=kwargs["num_warmup_steps"],147            num_training_steps=kwargs["total_steps"],148        )149    elif name == "constant_warmup":150        return get_scheduler(151            "constant_with_warmup", optimizer,152            num_warmup_steps=kwargs["num_warmup_steps"],153            num_training_steps=kwargs["total_steps"],154        )155    elif name == "constant":156        return lr_scheduler.LambdaLR(optimizer=optimizer, lr_lambda=lambda _: 1)157    elif name == "linear_decay":158        return lr_scheduler.LambdaLR(159            optimizer=optimizer,160            lr_lambda=lambda epoch: max(0., 1. - epoch / kwargs["total_epochs"]),161        )162    else:163        raise NotImplementedError(f"Not implemented lr scheduler: {name}")164 165def save_experiment_params(166    args: Namespace, 167    configs: DictConfig, 168    save_dir: str169) -> Dict[str, Any]:170    params = OmegaConf.merge(configs, {"args": {k: str(v) for k, v in vars(args).items()}})171    OmegaConf.save(params, os.path.join(save_dir, "params.yaml"))172    return dict(params)173 174 175def save_model_architecture(model: Module, save_dir: str) -> None:176    num_buffers = sum(b.numel() for b in model.buffers())177    num_params = sum(p.numel() for p in model.parameters())178    num_trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)179    message = f"Number of buffers: {num_buffers}\n" +\180        f"Number of trainable / all parameters: {num_trainable_params} / {num_params}\n\n" +\181        f"Model architecture:\n{model}"182 183    with open(os.path.join(save_dir, "model.txt"), "w") as f:184        f.write(message)