Algorithm 1 — DDPM Training. Args: config_path: Path to YAML config file
(config_path: str = "configs/base.yaml")
| 41 | |
| 42 | |
| 43 | def train(config_path: str = "configs/base.yaml"): |
| 44 | """Algorithm 1 — DDPM Training. |
| 45 | |
| 46 | Args: |
| 47 | config_path: Path to YAML config file |
| 48 | """ |
| 49 | # --- Load config --- |
| 50 | config_path = Path(config_path) |
| 51 | if config_path.exists(): |
| 52 | with open(config_path) as f: |
| 53 | cfg = yaml.safe_load(f) |
| 54 | else: |
| 55 | raise FileNotFoundError(f"Config not found: {config_path}") |
| 56 | |
| 57 | diff_cfg = cfg["diffusion"] |
| 58 | model_cfg = cfg["model"] |
| 59 | train_cfg = cfg["training"] |
| 60 | data_cfg = cfg["data"] |
| 61 | |
| 62 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| 63 | logger.info(f"Using device: {device}") |
| 64 | |
| 65 | # --- Noise schedule --- |
| 66 | # §2, Eq. 4 — linear schedule β_1 = 0.0001, β_T = 0.02 |
| 67 | T = diff_cfg["T"] |
| 68 | betas = linear_noise_schedule(T, diff_cfg["beta_start"], diff_cfg["beta_end"]) |
| 69 | betas = betas.to(device) |
| 70 | |
| 71 | alphas = 1.0 - betas # α_t = 1 − β_t |
| 72 | alpha_bar = torch.cumprod(alphas, dim=0) # ᾱ_t = ∏_{s=1}^{t} α_s |
| 73 | sqrt_alpha_bar = torch.sqrt(alpha_bar) # √ᾱ_t |
| 74 | sqrt_one_minus_alpha_bar = torch.sqrt(1.0 - alpha_bar) # √(1−ᾱ_t) |
| 75 | |
| 76 | # --- Model --- |
| 77 | unet_config = UNetConfig( |
| 78 | image_channels=model_cfg.get("image_channels", 3), |
| 79 | base_channels=model_cfg.get("base_channels", 128), |
| 80 | channel_mults=tuple(model_cfg.get("channel_mults", [1, 2, 2, 2])), |
| 81 | num_res_blocks=model_cfg.get("num_res_blocks", 2), |
| 82 | attention_resolutions=tuple(model_cfg.get("attention_resolutions", [16])), |
| 83 | dropout=model_cfg.get("dropout", 0.0), |
| 84 | num_groups=model_cfg.get("num_groups", 32), |
| 85 | image_size=data_cfg.get("image_size", 32), |
| 86 | ) |
| 87 | model = UNet(unet_config).to(device) |
| 88 | logger.info(f"Model: {model}") |
| 89 | |
| 90 | # --- EMA --- |
| 91 | # §4 — "we also report results with an exponential moving average of |
| 92 | # model parameters with a decay factor of 0.9999" |
| 93 | ema = EMA(model, decay=train_cfg.get("ema_decay", 0.9999)) |
| 94 | |
| 95 | # --- Optimizer --- |
| 96 | # Appendix B — "Adam, lr = 2 × 10^-4" |
| 97 | optimizer = torch.optim.Adam( |
| 98 | model.parameters(), |
| 99 | lr=float(train_cfg.get("lr", 2e-4)), |
| 100 | ) |
no test coverage detected