DDPMForImageGeneration
ImageGenerationModelDiffusionMixinDDPMForImageGeneration(config: DDPMConfig)DDPM with the noise-prediction training loss and Markov-chain sampler.
Wraps a _DDPMUNet denoiser, supplies the Ho 2020 §3.2
"simplified" training objective when target is provided, and inherits
DiffusionMixin.generate for ancestral sampling over the configured
noise schedule. This is the standard entry point for training and
inference on the DDPM family.
Training
* forward(sample, timestep) returns the raw network output.
* forward(sample, timestep, target=...) (target = ground-truth
noise for epsilon parameterisation) additionally fills the
loss field with the MSE loss of the paper's simple objective
(Ho 2020 Eq. 14).
* With config.learn_sigma=True the loss becomes Improved-DDPM's
hybrid , and
loss_simple / loss_vlb report the two terms separately.
Pass x_start= when you have the clean image — see
forward.
Sampling
* Use generate from DiffusionMixin — pass any
Scheduler (DDPMScheduler for ancestral sampling).
Parameters
configDDPMConfigconfig.learn_sigma=True switches on the learned
variance head and the hybrid objective; config.vlb_weight is the
that weights its variational term (default 1e-3,
the value in Nichol & Dhariwal §4).Attributes
unet_DDPMUNet_DDPMUNet).Notes
Reference: Ho, Jain, and Abbeel, "Denoising Diffusion Probabilistic Models", NeurIPS, 2020 (arXiv:2006.11239); Improved-DDPM additions from Nichol and Dhariwal, ICML 2021 (arXiv:2102.09672).
Training loss (when target is supplied):
where .
Examples
>>> import lucid
>>> from lucid.models.generative.ddpm import (
... DDPMConfig, DDPMForImageGeneration,
... )
>>> cfg = DDPMConfig(sample_size=32, base_channels=32,
... channel_mult=(1, 2), num_res_blocks=1,
... resnet_groups=16, num_train_timesteps=100)
>>> model = DDPMForImageGeneration(cfg).eval()
>>> x_t = lucid.randn((1, 3, 32, 32))
>>> t = lucid.tensor([42]).long()
>>> out = model(x_t, t)
>>> out.sample.shape # (1, 3, 32, 32)
(1, 3, 32, 32)Used by 2
Constructors
1Instance methods
2forward(sample: Tensor, timestep: Tensor, target: Tensor | None = None, x_start: Tensor | None = None)Predict noise (or [noise, σ²]) at the given timestep.
Parameters
sample(B, in_channels, H, W) noisy image x_t.timestep(B,) or () int timestep tensor. Scalar tensors
are broadcast.Returns
DDPMOutput(B, out_channels_effective, H, W) raw network output.
The ancestral sampler this model's own config describes.
DiffusionMixin.generate takes any scheduler, which leaves
the caller to retype the schedule:
scheduler = DDPMScheduler( config.num_train_timesteps, beta_schedule=config.beta_schedule, beta_start=config.beta_start, beta_end=config.beta_end, prediction_type=config.prediction_type, )
Every one of those is already on the config, and a scheduler
built with a different schedule from the one the weights were
trained under produces plausible-looking noise rather than an
error. config.clip_denoised was not reachable at all: the
field existed, the sampler honoured its own copy, and nothing
carried one to the other.
Returns
DDPMSchedulerConfigured from self.config.
Examples
>>> import lucid
>>> from lucid.models.generative.ddpm import (
... DDPMConfig, DDPMForImageGeneration,
... )
>>> cfg = DDPMConfig(sample_size=32, base_channels=32,
... channel_mult=(1, 2), num_res_blocks=1,
... resnet_groups=16, num_train_timesteps=100)
>>> model = DDPMForImageGeneration(cfg).eval()
>>> scheduler = model.make_scheduler()
>>> scheduler.num_train_timesteps, scheduler.clip_denoised
(100, True)