DDIMScheduler controls diffusion timing and denoising progression. It manages step sizes and denoising sequences for deterministic inference, while also adding time-dependent noise to images. section 15.2.2
For forward diffusion, add_noise() combines clean images and noise using weights determined by timesteps. As t increases toward 1,000, clean-image influence falls and noise influence rises. section 15.2.2
Generating flower images
Generation starts with random noise and uses 50 equally spaced inference steps: 980, 960, through 0. At each step, the denoising U-Net predicts an update and the scheduler produces the next image. The generate() method returns generated images and intermediate states, allowing the gradual conversion from noise to clean flowers to be visualized. section 15.4.2
Listing 15.2 Visualizing the forward diffusion process
from utils.ch15util import DDIMScheduler
noise_scheduler=DDIMScheduler(num_train_timesteps=1000) #1
allimgs=clean_images
for step in range(200,1001,200): #2
timesteps=torch.tensor([step-1]*4).long()
noisy_images=noise_scheduler.add_noise(clean_images,
noise, timesteps) #3
allimgs=torch.cat((allimgs,noisy_images)) #4
import torchvision
imgs=torchvision.utils.make_grid(allimgs,4,6)
fig = plt.figure(dpi=300)
plt.imshow((imgs.permute(2,1,0)+1)/2) #5
plt.axis("off")
plt.show()
Visualize forward diffusion by applying add_noise() to four 64×64 RGB images at progressively later timesteps. section 15.2.2
Listing 15.7 Defining a generate() method in the DDIMScheduler() class
@torch.no_grad()
def generate(self,model,device,batch_size=1,generator=None,
eta=1.0,use_clipped_model_output=True,num_inference_steps=50):
imgs=[]
image=torch.randn((batch_size,model.in_channels,model.sample_size,
model.sample_size),
generator=generator).to(device) #1
self.set_timesteps(num_inference_steps)
for t in tqdm(self.timesteps): #2
model_output = model(image, t)["sample"] #3
image = self.step(model_output,t,image,eta,
use_clipped_model_output=\
use_clipped_model_output) #4
img = unnormalize_to_zero_to_one(image)
img = img.cpu().permute(0, 2, 3, 1).numpy()
imgs.append(img) #5
image = unnormalize_to_zero_to_one(image)
image = image.cpu().permute(0, 2, 3, 1).numpy()
return {"sample": image}, imgs
Inspect the generation loop: initialize random images, set inference timesteps, call the model, apply scheduler.step(), and store intermediate images. section 15.4.2
