DDPM
公式
✅ 公式 (15)
$$ x_0 \approx \hat{x}_0 = \frac{x_t - \sqrt{1-\bar{\alpha}_t}\,\epsilon_\theta(x_t)} {\sqrt{\bar{\alpha}_t}} \tag{15} $$✅ 公式 (6)
$$ q(x_{t-1} \mid x_t, x_0) = \mathcal{N}\bigl(x_{t-1};\; \mu_t(x_t, x_0),\; \tilde{\beta}_t I\bigr) \tag{6} $$✅ 公式 (7)
$$ \mu_t(x_t, x_0) := \frac{\sqrt{\bar{\alpha}_{t-1}}\,\beta_t}{1-\bar{\alpha}_t}\, x_0 + \frac{\sqrt{\bar{\alpha}_t}\,(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t}\, x_t, \quad \tilde{\beta}_t := \frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t}\,\beta_t \tag{7} $$Code
1.计算 $\bar{\alpha}_t, \bar{\alpha}_{t-1}, \alpha_t$
t = timestep
prev_t = self.previous_timestep(t)
# 1. compute alphas, betas
alpha_prod_t = self.alphas_cumprod[t]
alpha_prod_t_prev = self.alphas_cumprod[prev_t] if prev_t >= 0 else self.one
beta_prod_t = 1 - alpha_prod_t
beta_prod_t_prev = 1 - alpha_prod_t_prev
current_alpha_t = alpha_prod_t / alpha_prod_t_prev
current_beta_t = 1 - current_alpha_t
2.计算
$$ x_0 \approx \hat{x}_0 = \frac{x_t - \sqrt{1-\bar{\alpha}_t}\,\epsilon_\theta(x_t)} {\sqrt{\bar{\alpha}_t}} \tag{15} $$ # 2. compute predicted original sample from predicted noise also called
# "predicted x_0" of formula (15) from https://huggingface.co/papers/2006.11239
pred_original_sample = (sample - beta_prod_t ** (0.5) * model_output) / alpha_prod_t ** (0.5)
3.计算公式(7)里的$x_0和x_t前边的系数$ $\frac{\sqrt{\bar{\alpha}_{t-1}}\,\beta_t}{1-\bar{\alpha}_t}$ 和 $\frac{\sqrt{\bar{\alpha}_t}\,(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t}$
# 4. Compute coefficients for pred_original_sample x_0 and current sample x_t
# See formula (7) from https://huggingface.co/papers/2006.11239
pred_original_sample_coeff = (alpha_prod_t_prev ** (0.5) * current_beta_t) / beta_prod_t
current_sample_coeff = current_alpha_t ** (0.5) * beta_prod_t_prev / beta_prod_t
4.计算公式(7)的 $\mu_t(x_t, x_0)$
$$\mu_t(x_t, x_0) := \frac{\sqrt{\bar{\alpha}_{t-1}}\,\beta_t}{1-\bar{\alpha}_t}\, x_0 + \frac{\sqrt{\bar{\alpha}_t}\,(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t}\, x_t,$$# 5. Compute predicted previous sample µ_t
# See formula (7) from https://huggingface.co/papers/2006.11239
pred_prev_sample = pred_original_sample_coeff * pred_original_sample + current_sample_coeff * sample
4.计算公式(7)中的方差 $\tilde{\beta}_t$
prev_t = self.previous_timestep(t)
alpha_prod_t = self.alphas_cumprod[t]
alpha_prod_t_prev = self.alphas_cumprod[prev_t] if prev_t >= 0 else self.one
current_beta_t = 1 - alpha_prod_t / alpha_prod_t_prev
# For t > 0, compute predicted variance βt (see formula (6) and (7) from https://huggingface.co/papers/2006.11239)
# and sample from it to get previous sample
# x_{t-1} ~ N(pred_prev_sample, variance) == add variance to pred_sample
variance = (1 - alpha_prod_t_prev) / (1 - alpha_prod_t) * current_beta_t
7.采样$x_{t-1} = \mu_t(x_t, x_0) + \tilde{\beta}_t * I$
variance_noise = randn_tensor(
model_output.shape, generator=generator, device=device, dtype=model_output.dtype)
pred_prev_sample = pred_prev_sample + variance * variance_noise
DDIM
https://huggingface.co/docs/diffusers/v0.35.1/en/api/schedulers/ddim#diffusers.DDIMScheduler
https://arxiv.org/abs/2010.02502
https://huggingface.co/papers/2010.02502
DDIM 核心(无随机项)公式
$$ x_{t-1} = \sqrt{\bar{\alpha}_{t-1}}\,\hat{x}_0+\sqrt{1-\bar{\alpha}_{t-1}}\,\epsilon_\theta(x_t, t), $$其中
$$ \hat{x}_0 = \frac{x_t - \sqrt{1-\bar{\alpha}_t}\,\epsilon_\theta(x_t, t)} {\sqrt{\bar{\alpha}_t}}. $$DDIM 核心(含随机项)公式
$$ x_{t-1} = \sqrt{\alpha_{t-1}} \left( \frac{x_t - \sqrt{1-\alpha_t}\,\epsilon_\theta^{(t)}(x_t)} {\sqrt{\alpha_t}} \right)+\sqrt{1-\alpha_{t-1}-\sigma_t^{2}}\;\epsilon_\theta^{(t)}(x_t)+\sigma_t \epsilon_t $$DDIM Code
DDIM定义
# See formulas (12) and (16) of DDIM paper https://huggingface.co/papers/2010.02502
# Ideally, read DDIM paper in-detail understanding
# Notation (<variable name> -> <name in paper>
# - pred_noise_t -> e_theta(x_t, t)
# - pred_original_sample -> f_theta(x_t, t) or x_0
# - std_dev_t -> sigma_t
# - eta -> η
# - pred_sample_direction -> "direction pointing to x_t"
# - pred_prev_sample -> "x_t-1"
1.计算下一步时间步t-1
# 1. get previous step value (=t-1)
# 999, 979, 959, ...
prev_timestep = timestep - self.config.num_train_timesteps // self.num_inference_steps
2.计算$\alpha_t,\alpha_{t-1},\beta_t$
# 2. compute alphas, betas
# 计算\alpha_t
alpha_prod_t = self.alphas_cumprod[timestep]
# 计算\alpha_{t-1}
alpha_prod_t_prev = self.alphas_cumprod[prev_timestep] if prev_timestep >= 0 else self.final_alpha_cumprod
# 计算 \beta,即1-\alpha_t。
beta_prod_t = 1 - alpha_prod_t
3.计算 pred_original_sample=$\frac{x_t - \sqrt{1-\alpha_t}\,\epsilon_\theta^{(t)}(x_t)}{\sqrt{\alpha_t}}$
# 3. compute predicted original sample from predicted noise also called
# "predicted x_0" of formula (12) from https://huggingface.co/papers/2010.02502
# sample是x_t,
# 计算 \frac{x_t - \sqrt{1-\alpha_t}\,\epsilon_\theta^{(t)}(x_t)}{\sqrt{\alpha_t}}
pred_original_sample = (sample - beta_prod_t ** (0.5) * model_output) / alpha_prod_t ** (0.5)
pred_epsilon = model_output
4.计算std_dev_t = $\sigma_t$
# 5. compute variance: "sigma_t(η)" -> see formula (16)
# σ_t = sqrt((1 − α_t−1)/(1 − α_t)) * sqrt(1 − α_t/α_t−1)
variance = self._get_variance(timestep, prev_timestep)
std_dev_t = eta * variance ** (0.5)
5.计算pred_sample_direction = $\sqrt{1-\alpha_{t-1}-\sigma_t^{2}}\;\epsilon_\theta^{(t)}(x_t)$
# 6. compute "direction pointing to x_t" of formula (12) from https://huggingface.co/papers/2010.02502
pred_sample_direction = (1 - alpha_prod_t_prev - std_dev_t**2) ** (0.5) * pred_epsilon
6.计算
$$ x_{t-1} = \sqrt{\alpha_{t-1}} \left( \frac{x_t - \sqrt{1-\alpha_t}\,\epsilon_\theta^{(t)}(x_t)} {\sqrt{\alpha_t}} \right)+\sqrt{1-\alpha_{t-1}-\sigma_t^{2}}\;\epsilon_\theta^{(t)}(x_t) $$# 7. compute x_t without "random noise" of formula (12) from https://huggingface.co/papers/2010.02502
prev_sample = alpha_prod_t_prev ** (0.5) * pred_original_sample + pred_sample_direction
7.计算
$$ x_{t-1} = \sqrt{\alpha_{t-1}} \left( \frac{x_t - \sqrt{1-\alpha_t}\,\epsilon_\theta^{(t)}(x_t)} {\sqrt{\alpha_t}} \right)+\sqrt{1-\alpha_{t-1}-\sigma_t^{2}}\;\epsilon_\theta^{(t)}(x_t)+\sigma_t \epsilon_t $$# \sigma_t \epsilon_t
variance = std_dev_t * variance_noise
prev_sample = prev_sample + variance
DDIM的使用
# set step values
# 999, 979, 959, ...
timesteps = (
np.linspace(0, self.config.num_train_timesteps - 1, num_inference_steps)
.round()[::-1]
.copy()
.astype(np.int64)
)
# self.scheduler.timesteps就是timesteps
for t in self.progress_bar(self.scheduler.timesteps):
# 1. predict noise model_output
model_output = self.unet(image, t).sample
# 2. predict previous mean of image x_t-1 and add variance depending on eta
# eta corresponds to η in paper and should be between [0, 1]
# do x_t -> x_t-1
image = self.scheduler.step(
model_output, t, image, eta=eta, use_clipped_model_output=use_clipped_model_output, generator=generator
).prev_sample