主要看这几个
教程
1 Deconstruct a basic pipeline
读取scheduler 和模型
from diffusers import DDPMScheduler, UNet2DModel
scheduler = DDPMScheduler.from_pretrained("google/ddpm-cat-256")
model = UNet2DModel.from_pretrained("google/ddpm-cat-256", use_safetensors=True).to("cuda")
设置scheduler的去噪声步骤
scheduler.set_timesteps(50)
置调度器时间步创建一个张量,其中包含均匀间隔的元素,在本例中为50。每个元素对应于模型对图像去噪的时间步长。当你稍后创建去噪循环时,你将迭代这个张量来去噪图像:
可以看出DDPM会自动平均分布
scheduler.timesteps
tensor([980, 960, 940, 920, 900, 880, 860, 840, 820, 800, 780, 760, 740, 720,
700, 680, 660, 640, 620, 600, 580, 560, 540, 520, 500, 480, 460, 440,
420, 400, 380, 360, 340, 320, 300, 280, 260, 240, 220, 200, 180, 160,
140, 120, 100, 80, 60, 40, 20, 0])
创建一些与期望输出相同形状的随机噪声:
batch 是1 输入维度是3
因为是VAE
HW
import torch
sample_size = model.config.sample_size
noise = torch.randn((1, 3, sample_size, sample_size), device="cuda")
现在编写一个循环来遍历时间步长。
在每个时间步,模型执行UNet2DModel.forward()传递并返回带噪声的残差。
调度程序的step()方法接受噪声残差、时间步长和输入,并预测前一个时间步长的图像。
该输出成为去噪循环中模型的下一个输入,它将重复,直到到达时间步长数组的末尾。
input = noise
for t in scheduler.timesteps:
with torch.no_grad():
noisy_residual = model(input, t).sample
previous_noisy_sample = scheduler.step(noisy_residual, t, input).prev_sample
input = previous_noisy_sample
最后一步是将去噪后的输出转换成图像:
from PIL import Image
import numpy as np
image = (input / 2 + 0.5).clamp(0, 1).squeeze()
image = (image.permute(1, 2, 0) * 255).round().to(torch.uint8).cpu().numpy()
image = Image.fromarray(image)
image
2 Deconstruct the Stable Diffusion pipeline