Diffusers 无条件图像生成实战指南:用 DiffusionPipeline 与 DDPM 从零生成图像
【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers
无条件图像生成(Unconditional Image Generation)是扩散模型最基础也最直观的应用场景:模型不依赖任何文本提示或参考图像,仅凭纯噪声出发,一步步去噪,最终还原出与训练数据分布相似的图像。本文以 🤗 Diffusers 官方文档(docs/source/ko/using-diffusers/unconditional_image_generation.md)为主线,结合仓库内DDPMPipeline源码与无条件训练脚本,系统讲解如何用DiffusionPipeline一行加载预训练 checkpoint、在 GPU 上完成推理、保存输出图像,并深入剖析去噪循环的底层原理与推理参数,最后介绍如何训练属于自己的无条件生成模型。
什么是无条件图像生成
无条件图像生成是相对"条件生成"(如文生图、图生图)而言的。它的特点在于:
- 无输入条件:不需要文本提示(prompt)、类别标签或参考图,模型只从随机高斯噪声出发;
- 目标是学习数据分布:训练阶段模型学习训练集的像素分布,推理阶段从中采样,生成"像训练数据但又不完全相同"的新图像;
- 典型的落地场景:生成与数据集同风格的新样本,例如蝴蝶图像、花朵图像、卡通头像、人脸等。
在 Diffusers 中,这类任务通常由DDPMPipeline、DDIMPipeline等"无提示词"的 pipeline 承担,配合UNet2DModel这类二维 U-Net 去噪骨干与DDPMScheduler调度器完成整个去噪采样流程。
一行代码加载预训练 pipeline
DiffusionPipeline是 Diffusers 提供的统一入口类,位于 src/diffusers/pipelines/pipeline_utils.py,官方文档称其为"为推理使用预训练扩散系统的最简单方式"。它最大的价值在于自动装配:只需要指定一个 checkpoint 标识,from_pretrained就会根据 checkpoint 内的配置文件,自动实例化对应的模型组件(如 U-Net)、调度器(如 DDPMScheduler),并把所有参数权重下载到本地缓存。
最基本的用法只需两行代码:
from diffusers import DiffusionPipeline generator = DiffusionPipeline.from_pretrained("anton-l/ddpm-butterflies-128")其中from_pretrained的第一个参数pretrained_model_name_or_path支持两种来源(见 pipeline_utils.py 中该方法的 docstring):
| 传入值 | 含义 |
|---|---|
| Hub 上的 repo id(字符串) | 例如anton-l/ddpm-butterflies-128,从 Hugging Face Hub 下载 |
| 本地目录路径 | 例如./my_pipeline_directory/,加载通过save_pretrained保存的 pipeline 目录 |
from_pretrained会一次性下载并缓存 pipeline 的全部组成部件——模型权重、tokenizer(如存在)、调度器配置等,因此用户无需关心内部的组件组装细节。该 checkpoint 的训练数据是蝴蝶图像,因此生成的图像内容以蝴蝶为主。
关于模型规模:原文档提到该模型包含约 14 亿参数并强烈建议在 GPU 上运行。需要注意,
anton-l/ddpm-butterflies-128是 128×128 分辨率的小型 DDPM 模型,实际参数量远小于 14 亿(14 亿规模通常指 Stable Diffusion 这类大型文生图模型),推理对显存的要求也相对宽松。准确的参数规模以你所加载 checkpoint 的模型卡与配置文件为准,不同 checkpoint 差异很大。文末我们也会看到,自己训练的无条件模型完全可以在单卡甚至 CPU 上跑通推理。
加载 pipeline 时的常用参数
from_pretrained还支持丰富的关键字参数(详见 源码 docstring),以下是实践中最常用的几个:
pipe = DiffusionPipeline.from_pretrained( "anton-l/ddpm-butterflies-128", torch_dtype=torch.float16, # 以半精度加载,节省显存并加速推理 cache_dir="./cache", # 自定义缓存目录 local_files_only=True, # 仅使用本地已缓存文件,不联网下载 revision="main", # 指定分支 / tag / commit force_download=False, # 强制重新下载,覆盖缓存 )torch_dtype:覆盖默认精度加载模型。以torch.float16加载可将显存占用与推理开销大幅降低;cache_dir:修改权重缓存位置,便于离线部署或多环境共享缓存;local_files_only:设为True时只从本地缓存读取,适合离线环境;revision:选择 checkpoint 的特定版本(分支名、tag 或 commit id);force_download:强制重新拉取,忽略已有缓存。
将 pipeline 迁移到 GPU 与 CPU 推理的注意事项
加载完成后,pipeline 默认位于 CPU。与 PyTorch 模块一致,通过.to(device)可将全部内部模块(U-Net、调度器等)迁移到指定设备:
generator.to("cuda")源码层面,to方法(见 pipeline_utils.py)会遍历 pipeline 注册的所有torch.nn.Module组件并逐个迁移。文档同样指出:
- 推荐在 GPU 上运行以获得可接受的推理速度;
- 若以
torch.float16精度加载,则不建议移回 CPU 运行——PyTorch 的float16运算在 CPU 上缺乏完整支持,可能导致推理失败(源码会在检测到float16+ CPU 组合时给出警告,见 pipeline_utils.py)。
此外,在 Apple Silicon 上也可以使用generator.to("mps")迁移到 MPS 设备(DDPMPipeline源码中专门处理了device.type == "mps"时随机张量生成的可复现性问题,见 pipeline_ddpm.py)。
生成并保存图像
设备迁移完成后,直接调用 pipeline 对象即可生成图像:
image = generator().images[0]几点说明:
- 默认
output_type="pil",因此images列表中的元素是PIL.Image 对象(内部通过numpy_to_pil转换,见 pipeline_ddpm.py),可直接用于展示或后续图像处理; - 返回对象是
ImagePipelineOutput(return_dict=True时),通过.images属性取得图像列表;若return_dict=False,则返回普通 tuple,第一个元素即图像列表; - 每个元素对应一个 batch 中的一张图,
batch_size默认 1。
保存图像同样简单:
image.save("generated_image.png")PIL.Image.save会根据文件扩展名自动选择编码格式,也支持jpg、webp等常见格式。
深入 DDPMPipeline:__call__参数与去噪循环原理
当加载anton-l/ddpm-butterflies-128这类 DDPM checkpoint 时,DiffusionPipeline.from_pretrained实际实例化的是DDPMPipeline(源码位于 src/diffusers/pipelines/ddpm/pipeline_ddpm.py),它由UNet2DModel与DDPMScheduler两个核心组件组成。理解它的__call__签名,就等于掌握了无条件生成的全部控制旋钮:
@torch.no_grad() def __call__( self, batch_size: int = 1, # 一次生成的图像数量 generator: torch.Generator | list[torch.Generator] | None = None, # 随机数生成器,用于可复现 num_inference_steps: int = 1000, # 去噪步数 output_type: str | None = "pil", # 输出格式:pil / np / pt return_dict: bool = True, # 返回 ImagePipelineOutput 还是 tuple ) -> ImagePipelineOutput | tuple:各参数详解
| 参数 | 默认值 | 作用与取值范围 |
|---|---|---|
batch_size | 1 | 生成的图像数量,设大于 1 可一次生成多张 |
generator | None | torch.Generator实例,传入后随机噪声可复现,便于调试与对照实验 |
num_inference_steps | 1000 | 去噪迭代步数。步数越多图像质量通常越高,但推理耗时线性增长;DDPM 默认 1000 步,实践中可结合 DDIM 等调度器大幅减少步数 |
output_type | "pil" | 输出格式:"pil"(PIL.Image)、"np"(numpy 数组)、"pt"(torch.Tensor) |
return_dict | True | True返回ImagePipelineOutput,False返回(images,)元组 |
底层去噪循环:从噪声到图像
DDPMPipeline.__call__的完整执行流程(见 pipeline_ddpm.py)清晰地展示了无条件生成的工作原理:
- 初始化纯噪声:根据
unet.config.sample_size与in_channels构造(batch_size, channels, height, width)形状,用randn_tensor采样高斯噪声作为起始图像x_T; - 设置时间步:调用
self.scheduler.set_timesteps(num_inference_steps),由调度器生成递减的时间步序列; - 迭代去噪:对每个时间步
t,- 先让 U-Net 预测噪声:
model_output = self.unet(image, t).sample; - 再由调度器根据预测噪声计算上一时刻图像:
image = self.scheduler.step(model_output, t, image, generator=generator).prev_sample,实现x_t -> x_{t-1}的逐步去噪;
- 先让 U-Net 预测噪声:
- 像素域还原:将潜空间图像映射回
[0, 1]:image = (image / 2 + 0.5).clamp(0, 1); - 格式转换与输出:根据
output_type转换为 PIL / numpy / tensor,并以ImagePipelineOutput返回。
整个过程被@torch.no_grad()包裹,推理阶段不计算梯度,节省显存。理解这五步后,若想进一步加速,只需把DDPMScheduler换成DDIMScheduler并减少num_inference_steps——这也是从 1000 步 DDPM 走向实用化采样的经典路径。
推理加速与显存优化技巧
针对无条件生成这类长时间推理任务,Diffusers 提供了若干开箱即用的优化开关,它们在DiffusionPipeline基类中均有实现:
enable_attention_slicing():将注意力计算切分为多个子块顺序执行,牺牲少量速度换取显存大幅下降(见 pipeline_utils.py),显存紧张时优先开启;enable_xformers_memory_efficient_attention():借助 xFormers 库使用内存高效的注意力算子,兼顾速度与显存(见 pipeline_utils.py),需要先pip install xformers;enable_model_cpu_offload():将 pipeline 各组件按序在 CPU 与 GPU 之间换入换出,用 PCIe 传输换取显存占用的大幅下降(见 pipeline_utils.py),适合超大模型在单卡上运行;- 半精度加载:
from_pretrained(..., torch_dtype=torch.float16)配合 GPU 使用,几乎可减半显存与计算量。
一个组合使用的示例:
pipe = DiffusionPipeline.from_pretrained( "anton-l/ddpm-butterflies-128", torch_dtype=torch.float16, ).to("cuda") pipe.enable_attention_slicing() # 如需更低显存:pipe.enable_model_cpu_offload() image = pipe(num_inference_steps=100).images[0]让结果可复现:torch.Generator 的用法
扩散采样依赖随机噪声,每次调用都会得到不同结果。若需要复现实验结果或做公平的对比,可显式传入torch.Generator:
import torch g = torch.Generator(device="cuda").manual_seed(0) image = pipe(generator=g).images[0]相同 seed 下,噪声初始化与调度器的每一步采样(scheduler.step(..., generator=generator))都可复现,从而得到完全一致的输出图像。
训练属于自己的无条件生成模型
除了直接使用预训练 checkpoint,你还可以在自定义数据集上训练无条件生成模型。仓库提供了开箱即用的训练脚本 examples/unconditional_image_generation/train_unconditional.py 与配套测试 test_unconditional.py,详细说明见 examples/unconditional_image_generation/README.md。
环境准备
在新建的虚拟环境中从源码安装 Diffusers,并安装示例依赖:
git clone https://github.com/huggingface/diffusers cd diffusers pip install .进入示例目录安装训练依赖,并初始化 Accelerate 分布式环境:
cd examples/unconditional_image_generation pip install -r requirements.txt accelerate config训练一个"花朵"无条件生成模型
以 Oxford Flowers 数据集为例,训练一个 DDPM UNet 模型:
accelerate launch train_unconditional.py \ --dataset_name="huggan/flowers-102-categories" \ --resolution=64 --center_crop --random_flip \ --output_dir="ddpm-ema-flowers-64" \ --train_batch_size=16 \ --num_epochs=100 \ --gradient_accumulation_steps=1 \ --use_ema \ --learning_rate=1e-4 \ --lr_warmup_steps=500 \ --mixed_precision=no \ --push_to_hub核心参数速查:
| 参数 | 作用 |
|---|---|
--dataset_name/--train_data_dir | 指定 Hub 数据集名,或本地图片文件夹路径(文件夹内任意层级放.png等图片即可,脚本自动用ImageFolder收集) |
--resolution | 训练分辨率(如 64/128),影响显存与训练耗时 |
--center_crop、--random_flip | 数据增强:中心裁剪与随机水平翻转 |
--use_ema | 启用指数移动平均,稳定输出质量 |
--gradient_accumulation_steps | 梯度累积步数,等效放大 batch size |
--mixed_precision | "no"/"fp16"等,控制混合精度训练 |
--push_to_hub | 训练完成后将模型推送到 Hub |
--output_dir | 模型与日志输出目录 |
使用自己的数据训练
两种方式任选:
- 本地文件夹:把图片放进任意目录(支持子目录),执行
accelerate launch train_unconditional.py --train_data_dir <路径> ...; - 上传到 Hub:用
datasets库的load_dataset("imagefolder", data_dir=...)构建数据集并push_to_hub后,以--dataset_name传入。
若数据包含 16/32 位通道(如医学 TIFF),可加
--preserve_input_precision保留原始精度。
多 GPU 分布式训练
借助 Accelerate 可无缝扩展到多卡:
accelerate launch --mixed_precision="fp16" --multi_gpu train_unconditional.py \ --dataset_name="huggan/pokemon" \ --resolution=64 --center_crop --random_flip \ --output_dir="ddpm-ema-pokemon-64" \ --train_batch_size=16 \ --num_epochs=100 \ --gradient_accumulation_steps=1 \ --use_ema \ --learning_rate=1e-4 \ --lr_warmup_steps=500 \ --mixed_precision="fp16" \ --logger="wandb"如需使用 Weights & Biases 记录训练曲线,先pip install wandb,再用--logger="wandb"开启。
训练完成后,同样用DiffusionPipeline.from_pretrained加载--output_dir指定目录即可推理:
from diffusers import DiffusionPipeline pipe = DiffusionPipeline.from_pretrained("ddpm-ema-flowers-64").to("cuda") image = pipe(num_inference_steps=200).images[0] image.save("my_flower.png")小结
本文围绕 Diffusers 无条件图像生成展开:从DiffusionPipeline.from_pretrained的一行加载,到 GPU 迁移与图像保存,再到DDPMPipeline.__call__的五个核心参数与底层"噪声初始化 → 迭代去噪 → 像素还原"的完整链路,最后给出了推理加速技巧、可复现生成方法以及基于train_unconditional.py从零训练自己模型的完整流程。无论你是想快速体验扩散模型生成效果,还是需要为特定数据集定制无条件生成器,这套"加载 → 推理 → 优化 → 训练"的路线图都可以直接复用。
【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考