Diffusers 中的 Stable Cascade 流水线实战:基于 42 倍压缩的级联扩散模型从文本生成图像
【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers
Stable Cascade 是 🤗 Diffusers 中基于 Würstchen 架构实现的三阶段级联扩散模型,它通过将 1024×1024 图像压缩到仅 24×24 的潜空间来完成文本到图像的生成,从而大幅降低推理与训练成本。本文以 Stable Cascade 官方文档 为主线,结合 prior 流水线源码、decoder 流水线源码 与 组合流水线源码,完整讲解其架构原理、数据类型约束、两阶段推理流程、Lite 轻量变体、单文件检查点加载以及源码级参数细节,读完即可在本地用 Diffusers 跑通 Stable Cascade 的完整文生图链路。
Stable Cascade 的设计动机:为什么要在极小的潜空间里工作
Stable Cascade 构建于 Würstchen 架构之上,与 Stable Diffusion 等模型最大的区别在于它工作在小得多的潜空间中。潜空间越小,推理速度越快,训练成本越低。这一差异可以从压缩因子直观看出:
| 模型 | 空间压缩因子 | 1024×1024 图像编码后的尺寸 |
|---|---|---|
| Stable Diffusion | 8 | 128×128 |
| Stable Cascade | 42 | 24×24 |
也就是说,Stable Cascade 能在保持清晰重建质量的前提下,把一张 1024×1024 的图像压缩到 24×24,然后文本条件模型直接在这样高度压缩的潜空间中训练。根据官方文档,该架构的先前版本相比 Stable Diffusion 1.5 实现了 16 倍的成本降低。
因此,这类模型非常适合对效率有要求的场景。同时,微调(finetuning)、LoRA、ControlNet、IP-Adapter、LCM 等已知扩展方法在 Stable Cascade 上同样适用。
三阶段级联:Stage A、Stage B 与 Stage C 的分工
Stable Cascade 由三个模型组成——Stage A、Stage B 和 Stage C,它们形成一条生成图像的"级联流水线",这正是 "Cascade" 名称的由来。
- Stage A 与 Stage B:负责图像压缩,作用类似于 Stable Diffusion 中的 VAE。两者协作实现了比单级 VAE 高得多的压缩比(压缩因子 42),将 1024×1024 图像编码为 24×24,同时仍能准确解码还原图像,带来训练与推理成本上的巨大收益。
- Stage C:负责根据文本提示生成小的 24×24 潜变量(latents),是级联流水线中最大的组件,配合
StableCascadePriorPipeline使用。 - Stage B 与 Stage A:配合
StableCascadeDecoderPipeline使用,负责基于 24×24 的潜变量生成最终图像。
从源码结构看,这种分工在 diffusers 中被封装为两条独立流水线:StableCascadePriorPipeline负责"文本 → 图像嵌入(24×24 潜变量)",StableCascadeDecoderPipeline负责"图像嵌入 → 最终图像"。二者的导出定义见 stable_cascade 流水线包,分别对应pipeline_stable_cascade_prior.py与pipeline_stable_cascade.py。
数据类型与 PyTorch 版本的重要约束
在使用 Stable Cascade 之前,必须先了解官方检查点对数据类型的限制,否则会遇到无法运行的问题:
[!WARNING]
- 官方
StableCascadePriorPipeline检查点不支持torch.float16,请改用torch.bfloat16。- 若要在
StableCascadeDecoderPipeline中使用torch.bfloat16,需要安装PyTorch 2.2.0 或更高版本。由于StableCascadeCombinedPipeline内部会调用StableCascadeDecoderPipeline,因此它使用torch.bfloat16时同样要求 PyTorch ≥ 2.2.0。- 如果环境无法安装 PyTorch 2.2.0 及以上版本,
StableCascadeDecoderPipeline可以单独使用torch.float16:下载全精度或bf16变体权重,然后将权重转换为torch.float16。
这一限制在源码中有硬性校验:StableCascadeDecoderPipeline.__call__会检查is_torch_version("<", "2.2.0") and dtype == torch.bfloat16并直接抛出ValueError(见 pipeline_stable_cascade.py 的调用入口),StableCascadeCombinedPipeline也有完全相同的校验逻辑(见 pipeline_stable_cascade_combined.py)。
标准用法:Prior + Decoder 两阶段文生图
官方文档给出的标准使用方式是分别加载StableCascadePriorPipeline与StableCascadeDecoderPipeline,先由 prior 生成图像嵌入,再交给 decoder 解码出图像:
import torch from diffusers import StableCascadeDecoderPipeline, StableCascadePriorPipeline prompt = "an image of a shiba inu, donning a spacesuit and helmet" negative_prompt = "" prior = StableCascadePriorPipeline.from_pretrained("stabilityai/stable-cascade-prior", variant="bf16", dtype=torch.bfloat16) decoder = StableCascadeDecoderPipeline.from_pretrained("stabilityai/stable-cascade", variant="bf16", dtype=torch.float16) prior.enable_model_cpu_offload() prior_output = prior( prompt=prompt, height=1024, width=1024, negative_prompt=negative_prompt, guidance_scale=4.0, num_images_per_prompt=1, num_inference_steps=20 ) decoder.enable_model_cpu_offload() decoder_output = decoder( image_embeddings=prior_output.image_embeddings.to(torch.float16), prompt=prompt, negative_prompt=negative_prompt, guidance_scale=0.0, output_type="pil", num_inference_steps=10 ).images[0] decoder_output.save("cascade.png")各关键参数的含义与推荐取值如下:
| 参数 | 取值 | 说明 |
|---|---|---|
variant="bf16" | prior / decoder | 加载 bf16 半精度权重变体,配合dtype指定运行时精度 |
height/width | 1024 | 生成图像的目标分辨率,会按resolution_multiple换算为 24×24 的 prior 潜变量 |
guidance_scale | prior 4.0 / decoder 0.0 | prior 阶段使用无分类器引导(>1 生效);decoder 阶段官方默认 0.0(不使用引导) |
num_inference_steps | prior 20 / decoder 10 | 各阶段去噪步数,步数越多质量越高但推理更慢 |
negative_prompt | 空字符串 | 无分类器引导下的负向提示 |
output_type | "pil"/"np"/"pt" | decoder 输出的图像格式 |
注意先验输出的image_embeddings是bfloat16,传给 decoder 前通过.to(torch.float16)显式转换,与 decoder 加载的torch.float16精度保持一致——这正好对应官方文档中"decoder 可用 float16 单独运行"的说明。
prior 阶段源码要点:分辨率如何变成 24×24
在 prior 流水线源码 的prepare_latents中,潜变量形状由resolution_multiple(默认42.67)换算:
latent_shape = ( num_images_per_prompt * batch_size, self.prior.config.in_channels, ceil(height / self.config.resolution_multiple), ceil(width / self.config.resolution_multiple), )即 1024 ÷ 42.67 ≈ 24,印证了文档中"24×24 潜空间"的说法。prior 的去噪循环中,StableCascadeUNet以clip_text_pooled、clip_text、clip_img为条件输入,在启用无分类器引导时会把文本/无条件嵌入拼接成同一批次做两次前向,再通过torch.lerp(uncond, text, guidance_scale)完成引导插值。源码中还有默认的 Stage C 时间步DEFAULT_STAGE_C_TIMESTEPS = list(np.linspace(1.0, 2 / 3, 20)) + list(np.linspace(2 / 3, 0.0, 11))[1:],定义了 Stage C 的默认去噪节奏。最终 prior 返回的StableCascadePriorPipelineOutput包含image_embeddings、prompt_embeds、prompt_embeds_pooled及对应的负向嵌入字段。
decoder 阶段源码要点:从 24×24 潜变量还原图像
在 decoder 流水线源码 中,prepare_latents通过latent_dim_scale(默认10.67)把 prior 的 24×24 图像嵌入放大到 VQ 潜空间:
latents_shape = ( batch_size * num_images_per_prompt, 4, int(height * self.config.latent_dim_scale), int(width * self.config.latent_dim_scale), )24 × 10.67 ≈ 256,即 decoder 的去噪在 256×256 的 4 通道潜变量上进行。去噪完成后,潜变量经self.vqgan.config.scale_factor * latents缩放,交给PaellaVQModel(vqgan.decode)解码并clamp(0, 1)得到最终像素图像,最后按output_type转换为 PIL、NumPy 或张量输出。
使用 Stage B / Stage C 的 Lite 轻量版本
官方为资源受限场景提供了 Stage B 与 Stage C 的 Lite 版本。加载方式是通过StableCascadeUNet分别加载prior_lite与decoder_lite子文件夹中的 UNet,再注入对应的流水线:
import torch from diffusers import ( StableCascadeDecoderPipeline, StableCascadePriorPipeline, StableCascadeUNet, ) prompt = "an image of a shiba inu, donning a spacesuit and helmet" negative_prompt = "" prior_unet = StableCascadeUNet.from_pretrained("stabilityai/stable-cascade-prior", subfolder="prior_lite") decoder_unet = StableCascadeUNet.from_pretrained("stabilityai/stable-cascade", subfolder="decoder_lite") prior = StableCascadePriorPipeline.from_pretrained("stabilityai/stable-cascade-prior", prior=prior_unet) decoder = StableCascadeDecoderPipeline.from_pretrained("stabilityai/stable-cascade", decoder=decoder_unet) prior.enable_model_cpu_offload() prior_output = prior( prompt=prompt, height=1024, width=1024, negative_prompt=negative_prompt, guidance_scale=4.0, num_images_per_prompt=1, num_inference_steps=20 ) decoder.enable_model_cpu_offload() decoder_output = decoder( image_embeddings=prior_output.image_embeddings, prompt=prompt, negative_prompt=negative_prompt, guidance_scale=0.0, output_type="pil", num_inference_steps=10 ).images[0] decoder_output.save("cascade.png")Lite 变体的权重结构在测试中有直接印证:tests/single_file/test_model_sd_cascade_unet_single_file.py同时验证了stage_b_bf16.safetensors与stage_b_lite_bf16.safetensors经from_single_file加载后,其配置与decoder/decoder_lite子文件夹的 diffusers 格式权重完全一致。
使用 from_single_file 加载原始检查点
如果你持有 Stability AI 原始格式的.safetensors检查点,可以直接通过StableCascadeUNet的from_single_file方法加载,无需预先转换格式。StableCascadeUNet继承自FromOriginalModelMixin(见 unet_stable_cascade.py),这正是单文件加载能力的来源。
import torch from diffusers import ( StableCascadeDecoderPipeline, StableCascadePriorPipeline, StableCascadeUNet, ) prompt = "an image of a shiba inu, donning a spacesuit and helmet" negative_prompt = "" prior_unet = StableCascadeUNet.from_single_file( "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_bf16.safetensors", dtype=torch.bfloat16 ) decoder_unet = StableCascadeUNet.from_single_file( "https://huggingface.co/stabilityai/stable-cascade/blob/main/stage_b_bf16.safetensors", dtype=torch.bfloat16 ) prior = StableCascadePriorPipeline.from_pretrained("stabilityai/stable-cascade-prior", prior=prior_unet, dtype=torch.bfloat16) decoder = StableCascadeDecoderPipeline.from_pretrained("stabilityai/stable-cascade", decoder=decoder_unet, dtype=torch.bfloat16) prior.enable_model_cpu_offload() prior_output = prior( prompt=prompt, height=1024, width=1024, negative_prompt=negative_prompt, guidance_scale=4.0, num_images_per_prompt=1, num_inference_steps=20 ) decoder.enable_model_cpu_offload() decoder_output = decoder( image_embeddings=prior_output.image_embeddings, prompt=prompt, negative_prompt=negative_prompt, guidance_scale=0.0, output_type="pil", num_inference_steps=10 ).images[0] decoder_output.save("cascade-single-file.png")代码中stage_c_bf16.safetensors(Stage C,即 prior 使用的 UNet)与stage_b_bf16.safetensors(Stage B,即 decoder 使用的 UNet)分别对应原始检查点中的两个组件;Lite 版本对应stage_b_lite_bf16.safetensors。这一加载路径已被 单文件测试 覆盖:测试将from_single_file加载的模型配置与from_pretrained(variant="bf16"、subfolder="decoder"/"decoder_lite")加载的模型配置逐项比对,确保两种加载方式得到的模型结构一致。
一键完成整条链路:StableCascadeCombinedPipeline
如果不想手动串联 prior 与 decoder,可以使用StableCascadeCombinedPipeline一步完成"文本 → 图像"。从 组合流水线源码 可以看出,它在__init__内部直接实例化了StableCascadePriorPipeline(self.prior_pipe)与StableCascadeDecoderPipeline(self.decoder_pipe),__call__时先调用prior_pipe得到image_embeddings,再将其传给decoder_pipe输出最终图像,并支持通过prior_num_inference_steps/prior_guidance_scale与num_inference_steps/decoder_guidance_scale分别控制两个阶段的参数:
import torch from diffusers import StableCascadeCombinedPipeline pipe = StableCascadeCombinedPipeline.from_pretrained( "stabilityai/stable-cascade", variant="bf16", torch_dtype=torch.bfloat16 ) pipe.enable_model_cpu_offload() prompt = "an image of a shiba inu, donning a spacesuit and helmet" images = pipe( prompt=prompt, height=1024, width=1024, prior_num_inference_steps=20, prior_guidance_scale=4.0, num_inference_steps=10, decoder_guidance_scale=0.0, )该组合流水线同样继承DeprecatedPipelineMixin,并在__call__入口对torch.bfloat16执行 PyTorch ≥ 2.2.0 的版本校验。此外它会把enable_model_cpu_offload、enable_sequential_cpu_offload等内存优化方法透传给内部的两条子流水线。
使用场景、边界与已知局限
直接用途(Direct Use)
根据官方文档,该模型当前主要面向研究目的,可能的研究方向与任务包括:
- 生成模型研究;
- 对有生成有害内容潜力的模型进行安全部署研究;
- 探测与理解生成模型的局限性与偏见;
- 艺术品生成以及在设计与其它艺术流程中的应用;
- 教育或创意工具中的应用程序。
超出范围的使用(Out-of-Scope Use)
该模型未经训练以生成人物或事件的真实表述,因此用它生成此类内容超出了模型的能力范围。模型不得以任何违反 Stability AI 可接受使用政策的方式使用。
局限性(Limitations)
- 人脸和人物整体可能无法正确生成;
- 模型的自动编码部分是有损的。
补充说明:pipeline 的弃用状态
从源码结构看,StableCascadePriorPipeline、StableCascadeDecoderPipeline与StableCascadeCombinedPipeline均继承自DeprecatedPipelineMixin,并声明了_last_supported_version = "0.35.2"(见 prior、decoder 与 combined 源码),可以推断这些流水线在当前版本中处于弃用过渡状态。此外三条流水线的导出被集中在 stable_cascade 包,需要通过from diffusers import StableCascadePriorPipeline, StableCascadeDecoderPipeline, StableCascadeCombinedPipeline导入;底层 UNet 模型StableCascadeUNet定义于 unet_stable_cascade.py,其核心模块包括SDCascadeResBlock(深度可分离卷积 + GlobalResponseNorm)、SDCascadeAttnBlock(带自注意力的交叉注意力块)与SDCascadeTimestepBlock(时间步比例条件映射),默认结构为两层 2048 通道、各 32 注意力头的对称 U-Net。建议实际使用时结合你所安装的 diffusers 版本来确认相关 API 的具体行为与替代方案。
【免费下载链接】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),仅供参考