improve
This commit is contained in:
+132
-74
@@ -1,99 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
from diffusers import UNetModel, GaussianDiffusion
|
||||
from diffusers import UNetModel, GaussianDDPMScheduler
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
import numpy as np
|
||||
import PIL.Image
|
||||
import tqdm
|
||||
|
||||
unet = UNetModel.from_pretrained("fusing/ddpm_dummy")
|
||||
diffusion = GaussianDiffusion.from_config("fusing/ddpm_dummy")
|
||||
|
||||
#torch_device = "cuda"
|
||||
#
|
||||
#unet = UNetModel.from_pretrained("/home/patrick/ddpm-lsun-church")
|
||||
#unet.to(torch_device)
|
||||
#
|
||||
#TIME_STEPS = 10
|
||||
#
|
||||
#scheduler = GaussianDDPMScheduler.from_config("/home/patrick/ddpm-lsun-church", timesteps=TIME_STEPS)
|
||||
#
|
||||
#diffusion_config = {
|
||||
# "beta_start": 0.0001,
|
||||
# "beta_end": 0.02,
|
||||
# "num_diffusion_timesteps": TIME_STEPS,
|
||||
#}
|
||||
#
|
||||
# 2. Do one denoising step with model
|
||||
batch_size, num_channels, height, width = 1, 3, 32, 32
|
||||
dummy_noise = torch.ones((batch_size, num_channels, height, width))
|
||||
|
||||
|
||||
TIME_STEPS = 10
|
||||
|
||||
|
||||
#batch_size, num_channels, height, width = 1, 3, 256, 256
|
||||
#
|
||||
#torch.manual_seed(0)
|
||||
#noise_image = torch.randn(batch_size, num_channels, height, width, device="cuda")
|
||||
#
|
||||
#
|
||||
# Helper
|
||||
def extract(a, t, x_shape):
|
||||
b, *_ = t.shape
|
||||
out = a.gather(-1, t)
|
||||
return out.reshape(b, *((1,) * (len(x_shape) - 1)))
|
||||
#def noise_like(shape, device, repeat=False):
|
||||
# def repeat_noise():
|
||||
# return torch.randn((1, *shape[1:]), device=device).repeat(shape[0], *((1,) * (len(shape) - 1)))
|
||||
#
|
||||
# def noise():
|
||||
# return torch.randn(shape, device=device)
|
||||
#
|
||||
# return repeat_noise() if repeat else noise()
|
||||
#
|
||||
#
|
||||
#betas = np.linspace(diffusion_config["beta_start"], diffusion_config["beta_end"], diffusion_config["num_diffusion_timesteps"], dtype=np.float64)
|
||||
#betas = torch.tensor(betas, device=torch_device)
|
||||
#alphas = 1.0 - betas
|
||||
#
|
||||
#alphas_cumprod = torch.cumprod(alphas, axis=0)
|
||||
#alphas_cumprod_prev = F.pad(alphas_cumprod[:-1], (1, 0), value=1.0)
|
||||
#
|
||||
#posterior_mean_coef1 = betas * torch.sqrt(alphas_cumprod_prev) / (1.0 - alphas_cumprod)
|
||||
#posterior_mean_coef2 = (1.0 - alphas_cumprod_prev) * torch.sqrt(alphas) / (1.0 - alphas_cumprod)
|
||||
#
|
||||
#posterior_variance = betas * (1.0 - alphas_cumprod_prev) / (1.0 - alphas_cumprod)
|
||||
#posterior_log_variance_clipped = torch.log(posterior_variance.clamp(min=1e-20))
|
||||
#
|
||||
#
|
||||
#sqrt_recip_alphas_cumprod = torch.sqrt(1.0 / alphas_cumprod)
|
||||
#sqrt_recipm1_alphas_cumprod = torch.sqrt(1.0 / alphas_cumprod - 1)
|
||||
#
|
||||
#
|
||||
#noise_coeff = (1 - alphas) / torch.sqrt(1 - alphas_cumprod)
|
||||
#coeff = 1 / torch.sqrt(alphas)
|
||||
|
||||
|
||||
def noise_like(shape, device, repeat=False):
|
||||
def repeat_noise():
|
||||
return torch.randn((1, *shape[1:]), device=device).repeat(shape[0], *((1,) * (len(shape) - 1)))
|
||||
def real_fn():
|
||||
# Compare the following to Algorithm 2 Sampling of paper: https://arxiv.org/pdf/2006.11239.pdf
|
||||
# 1: x_t ~ N(0,1)
|
||||
x_t = noise_image
|
||||
# 2: for t = T, ...., 1 do
|
||||
for i in reversed(range(TIME_STEPS)):
|
||||
t = torch.tensor([i]).to(torch_device)
|
||||
# 3: z ~ N(0, 1)
|
||||
noise = noise_like(x_t.shape, torch_device)
|
||||
|
||||
def noise():
|
||||
return torch.randn(shape, device=device)
|
||||
# 4: √1αtxt − √1−αt1−α¯tθ(xt, t) + σtz
|
||||
# ------------------------- MODEL ------------------------------------#
|
||||
with torch.no_grad():
|
||||
pred_noise = unet(x_t, t) # pred epsilon_theta
|
||||
|
||||
return repeat_noise() if repeat else noise()
|
||||
# pred_x = sqrt_recip_alphas_cumprod[t] * x_t - sqrt_recipm1_alphas_cumprod[t] * pred_noise
|
||||
# pred_x.clamp_(-1.0, 1.0)
|
||||
# pred mean
|
||||
# posterior_mean = posterior_mean_coef1[t] * pred_x + posterior_mean_coef2[t] * x_t
|
||||
# --------------------------------------------------------------------#
|
||||
|
||||
posterior_mean = coeff[t] * (x_t - noise_coeff[t] * pred_noise)
|
||||
|
||||
# ------------------------- Variance Scheduler -----------------------#
|
||||
# pred variance
|
||||
posterior_log_variance = posterior_log_variance_clipped[t]
|
||||
|
||||
b, *_, device = *x_t.shape, x_t.device
|
||||
nonzero_mask = (1 - (t == 0).float()).reshape(b, *((1,) * (len(x_t.shape) - 1)))
|
||||
posterior_variance = nonzero_mask * (0.5 * posterior_log_variance).exp()
|
||||
# --------------------------------------------------------------------#
|
||||
|
||||
x_t_1 = (posterior_mean + posterior_variance * noise).to(torch.float32)
|
||||
x_t = x_t_1
|
||||
|
||||
print(x_t.abs().sum())
|
||||
|
||||
|
||||
# Schedule
|
||||
def cosine_beta_schedule(timesteps, s=0.008):
|
||||
"""
|
||||
cosine schedule
|
||||
as proposed in https://openreview.net/forum?id=-NEXDKk8gZ
|
||||
"""
|
||||
steps = timesteps + 1
|
||||
x = torch.linspace(0, timesteps, steps, dtype=torch.float64)
|
||||
alphas_cumprod = torch.cos(((x / timesteps) + s) / (1 + s) * torch.pi * 0.5) ** 2
|
||||
alphas_cumprod = alphas_cumprod / alphas_cumprod[0]
|
||||
betas = 1 - (alphas_cumprod[1:] / alphas_cumprod[:-1])
|
||||
return torch.clip(betas, 0, 0.999)
|
||||
def post_process_to_image(x_t):
|
||||
image = x_t.cpu().permute(0, 2, 3, 1)
|
||||
image = (image + 1.0) * 127.5
|
||||
image = image.numpy().astype(np.uint8)
|
||||
|
||||
return PIL.Image.fromarray(image[0])
|
||||
|
||||
|
||||
betas = cosine_beta_schedule(TIME_STEPS)
|
||||
alphas = 1.0 - betas
|
||||
alphas_cumprod = torch.cumprod(alphas, axis=0)
|
||||
alphas_cumprod_prev = F.pad(alphas_cumprod[:-1], (1, 0), value=1.0)
|
||||
from pytorch_diffusion import Diffusion
|
||||
|
||||
posterior_mean_coef1 = betas * torch.sqrt(alphas_cumprod_prev) / (1.0 - alphas_cumprod)
|
||||
posterior_mean_coef2 = (1.0 - alphas_cumprod_prev) * torch.sqrt(alphas) / (1.0 - alphas_cumprod)
|
||||
|
||||
posterior_variance = betas * (1.0 - alphas_cumprod_prev) / (1.0 - alphas_cumprod)
|
||||
posterior_log_variance_clipped = torch.log(posterior_variance.clamp(min=1e-20))
|
||||
#diffusion = Diffusion.from_pretrained("lsun_church")
|
||||
#samples = diffusion.denoise(1)
|
||||
#
|
||||
#image = post_process_to_image(samples)
|
||||
#image.save("check.png")
|
||||
#import ipdb; ipdb.set_trace()
|
||||
|
||||
|
||||
sqrt_recip_alphas_cumprod = torch.sqrt(1.0 / alphas_cumprod)
|
||||
sqrt_recipm1_alphas_cumprod = torch.sqrt(1.0 / alphas_cumprod - 1)
|
||||
device = "cuda"
|
||||
scheduler = GaussianDDPMScheduler.from_config("/home/patrick/ddpm-lsun-church", timesteps=10)
|
||||
|
||||
import ipdb; ipdb.set_trace()
|
||||
|
||||
model = UNetModel.from_pretrained("/home/patrick/ddpm-lsun-church").to(device)
|
||||
|
||||
|
||||
torch.manual_seed(0)
|
||||
next_image = scheduler.sample_noise((1, model.in_channels, model.resolution, model.resolution), device=device)
|
||||
|
||||
# Compare the following to Algorithm 2 Sampling of paper: https://arxiv.org/pdf/2006.11239.pdf
|
||||
# 1: x_t ~ N(0,1)
|
||||
x_t = dummy_noise
|
||||
# 2: for t = T, ...., 1 do
|
||||
for i in reversed(range(TIME_STEPS)):
|
||||
t = torch.tensor([i])
|
||||
# 3: z ~ N(0, 1)
|
||||
noise = noise_like(x_t.shape, "cpu")
|
||||
for t in tqdm.tqdm(reversed(range(len(scheduler))), total=len(scheduler)):
|
||||
# define coefficients for time step t
|
||||
clip_image_coeff = 1 / torch.sqrt(scheduler.get_alpha_prod(t))
|
||||
clip_noise_coeff = torch.sqrt(1 / scheduler.get_alpha_prod(t) - 1)
|
||||
image_coeff = (1 - scheduler.get_alpha_prod(t - 1)) * torch.sqrt(scheduler.get_alpha(t)) / (1 - scheduler.get_alpha_prod(t))
|
||||
clip_coeff = torch.sqrt(scheduler.get_alpha_prod(t - 1)) * scheduler.get_beta(t) / (1 - scheduler.get_alpha_prod(t))
|
||||
|
||||
# 4: √1αtxt − √1−αt1−α¯tθ(xt, t) + σtz
|
||||
# ------------------------- MODEL ------------------------------------#
|
||||
pred_noise = unet(x_t, t) # pred epsilon_theta
|
||||
pred_x = extract(sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t - extract(sqrt_recipm1_alphas_cumprod, t, x_t.shape) * pred_noise
|
||||
pred_x.clamp_(-1.0, 1.0)
|
||||
# pred mean
|
||||
posterior_mean = extract(posterior_mean_coef1, t, x_t.shape) * pred_x + extract(posterior_mean_coef2, t, x_t.shape) * x_t
|
||||
# --------------------------------------------------------------------#
|
||||
# predict noise residual
|
||||
with torch.no_grad():
|
||||
noise_residual = model(next_image, t)
|
||||
|
||||
# ------------------------- Variance Scheduler -----------------------#
|
||||
# pred variance
|
||||
posterior_log_variance = extract(posterior_log_variance_clipped, t, x_t.shape)
|
||||
b, *_, device = *x_t.shape, x_t.device
|
||||
nonzero_mask = (1 - (t == 0).float()).reshape(b, *((1,) * (len(x_t.shape) - 1)))
|
||||
posterior_variance = nonzero_mask * (0.5 * posterior_log_variance).exp()
|
||||
# --------------------------------------------------------------------#
|
||||
# compute prev image from noise
|
||||
pred_mean = clip_image_coeff * next_image - clip_noise_coeff * noise_residual
|
||||
pred_mean = torch.clamp(pred_mean, -1, 1)
|
||||
image = clip_coeff * pred_mean + image_coeff * next_image
|
||||
|
||||
x_t_1 = (posterior_mean + posterior_variance * noise).to(torch.float32)
|
||||
# sample variance
|
||||
variance = scheduler.sample_variance(t, image.shape, device=device)
|
||||
|
||||
# FOR PATRICK TO VERIFY: make sure manual loop is equal to function
|
||||
# --------------------------------------------------------------------#
|
||||
x_t_12 = diffusion.p_sample(unet, x_t, t, noise=noise)
|
||||
assert (x_t_1 - x_t_12).abs().sum().item() < 1e-3
|
||||
# --------------------------------------------------------------------#
|
||||
# sample previous image
|
||||
sampled_image = image + variance
|
||||
|
||||
x_t = x_t_1
|
||||
next_image = sampled_image
|
||||
|
||||
|
||||
image = post_process_to_image(next_image)
|
||||
image.save("example_new.png")
|
||||
|
||||
Reference in New Issue
Block a user