3、 DiffusionPipeline原理 & 代码解析 [代码级手把手解析diffusers库]

DiffusionPipeline

有一种简便的方法用于推理是至关重要的。扩散系统通常由多个组件组成,如parameterized modeltokenizersschedulers等,它们以复杂的方式进行交互。这就是为什么我们设计了DiffusionPipeline,将整个扩散系统的复杂性包装成易于使用的API,同时保持足够的灵活性,以适应其他用例,例如将每个组件单独加载作为构建块来组装自己的扩散系统。

作为所有Diffusion模型Pipeline的基类,DiffusionPipeline主要负责完成模型的加载与注册等一系列前置工作。将下载的权重加载到正确的Pipeline类(从文件model_index.json中检索)中,并返回该类的实例,并自动将model移动到对应的device上(注意:DiffusionPipeline将devicedtype注册为property method,是在from_pretrained中初始化的)。

除了基类DiffusionPipeline,其他用于特定任务的Piepline叫做Community pipelines:如StableDiffusionControlNetPipeline 对应于使用 ControlNet 调节生成文本到图像的Pipeline。

1. from_pretrained

1.1 简单使用

DiffusionPipeline 类是从 Hub 加载最新趋势扩散模型的最简单、最通用的方法。DiffusionPipeline.from_pretrained() 方法自动从检查点检测正确的Pipeline类,下载并缓存所有必需的配置和权重文件,并返回准备进行推理的管道实例。而且当 from_pretrained() 方法检测到本地路径时,它不会从 Hub 下载任何文件,但这也意味着它不会下载和缓存检查点的最新更改。

from diffusers import DiffusionPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
pipe = DiffusionPipeline.from_pretrained(repo_id, use_safetensors=True)

还可以加载具有特定Community pipelines类的检查点。上面的示例加载了一个稳定扩散模型;若要获得相同的结果,请使用 StableDiffusionPipeline 类:

from diffusers import StableDiffusionPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionPipeline.from_pretrained(repo_id, use_safetensors=True)

也可以直接使用其相应的特定于任务的Community pipelines类加载它:

from diffusers import StableDiffusionImg2ImgPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(repo_id)

除了直接从diffusers导入对应的Community pipelines类,我们还可以直接使用DiffusionPipeline导入,只需要指定custom_pipeline参数即可:若要在 Hub 上加载任何社区管道,请将Community pipelines的存储库 ID 传递给custom_pipeline

如果Pipeline中包含 Diffusers库 尚不支持的自定义组件,则需要手动将其实现,然后导入。这些自定义组件可以是 VAE、UNet 、TextEncoder、调度器等。

例如,以下示例从 showlab/show-1-base 加载Community Pipeline,手动加载加载pipeline权重和组件传入Pipeline:

pipe_id = "showlab/show-1-base"

# 1. 从 Transformer 导入并加载文本编码器:
from transformers import T5Tokenizer, T5EncoderModel
tokenizer = T5Tokenizer.from_pretrained(pipe_id, subfolder="tokenizer")
text_encoder = T5EncoderModel.from_pretrained(pipe_id, subfolder="text_encoder")

# 2. 加载调度程序:
from diffusers import DPMSolverMultistepScheduler
scheduler = DPMSolverMultistepScheduler.from_pretrained(pipe_id, subfolder="scheduler")

# 3. 加载图像处理器:
from transformers import CLIPFeatureExtractor
feature_extractor = CLIPFeatureExtractor.from_pretrained(pipe_id, subfolder="feature_extractor")

# 4. 加载一个自定义 UNet(为方便起见,假设该  UNet3DConditionModel  已在showone_unet_3d_condition.py脚本中实现)
from showone_unet_3d_condition import ShowOneUNet3DConditionModel
unet = ShowOneUNet3DConditionModel.from_pretrained(pipe_id, subfolder="unet")

# 5. 加载自定义管道 Pipeline同样假设已经在pipeline_t2v_base_pixel.py脚本中实现)
from pipeline_t2v_base_pixel import TextToVideoIFPipeline
import torch
pipeline = TextToVideoIFPipeline(
    unet=unet,
    text_encoder=text_encoder,
    tokenizer=tokenizer,
    scheduler=scheduler,
    feature_extractor=feature_extractor
)
pipeline = pipeline.to(device="cuda")
pipeline.torch_dtype = torch.float16
  • 推送 自定义组件/pipeline 到 Hub:

对于自定义的一个Pipeline,我们可以将其推送到Huggingace社区,方便以后直接用DiffusionPipeline进行加载push_to_hub()将每个组件保存到存储库中的子文件夹中,权重默认保存为.safetensors,配置参数默认保存为config.json

pipeline.push_to_hub("custom-t2v-pipeline")  # 设置pipeline的id_name

成功推送管道后,只需要进行一些更改:

  • model_index.json 中的_class_name属性更改为"pipeline_t2v_base_pixel""TextToVideoIFPipeline"
  • 上传showone_unet_3d_condition.py脚本到unet目录
  • 上传pipeline_t2v_base_pixel.py脚本到pipeline基目录

要再次运行推理,只需在初始化管道时添加参数trust_remote_code,即可在幕后处理所有操作。

from diffusers import DiffusionPipeline
import torch

pipeline = DiffusionPipeline.from_pretrained(
    "your-namespace/custom-t2v-pipeline", trust_remote_code=True, torch_dtype=torch.float16
).to("cuda")

prompt = "hello"

# Text embeds
prompt_embeds, negative_embeds = pipeline.encode_prompt(prompt)

# Keyframes generation (8x64x40, 2fps)
video_frames = pipeline(
    prompt_embeds=prompt_embeds,
    negative_prompt_embeds=negative_embeds,
    num_frames=8,
    height=40,
    width=64,
    num_inference_steps=2,
    guidance_scale=9.0,
    output_type="pt"
).frames
1.2 from_pretrained加载原理
  • Pipeline根据model_index.json进行加载各个子文件夹的组件类;
  • 各个组件类根据子文件夹中的config.json加载对应类的实例;

当我们打印普通的StableDiffusionPipeline:将看到 pipeline 是 StableDiffusionPipeline 的一个实例,它由七个组件组成:

  • “feature_extractor”:来自 Transformer 的 🤗 - CLIPImageProcessor。
  • “safety_checker”:用于筛选有害内容的组件。
  • “scheduler”:PNDMScheduler 的实例。
  • “text_encoder”:来自 Transformer 的 🤗 CLIPTextModel。
  • “tokenizer”:来自变形金刚的 🤗 CLIPTokenizer。
  • “unet”:UNet2DConditionModel 的实例。
  • “vae”:AutoencoderKL的实例。
StableDiffusionPipeline {
   
  "feature_extractor": [
    "transformers",
    "CLIPImageProcessor"
  ],
  "safety_checker": [
    "stable_diffusion",
    "StableDiffusionSafetyChecker"
  ],
  "scheduler": [
    "diffusers",
    "PNDMScheduler"
  ],
  "text_encoder": [
    "transformers",
    "CLIPTextModel"
  ],
  "tokenizer": [
    "transformers",
    "CLIPTokenizer"
  ],
  "unet": [
    "diffusers",
    "UNet2DConditionModel"
  ],
  "vae": [
    "diffusers",
    "AutoencoderKL"
  ]
}

将管道实例的组件与 runwayml/stable-diffusion-v1-5 文件夹结构进行比较,您将看到存储库中的每个组件都有一个单独的文件夹:

.
├── feature_extractor
│   └── preprocessor_config.json
├── model_index.json
├── safety_checker
│   ├── config.json
|   ├── model.fp16.safetensors
│   ├── model.safetensors
│   ├── pytorch_model.bin
|   └── pytorch_model.fp16.bin
├── scheduler
│   └── scheduler_config.json
├── text_encoder
│   ├── config.json
|   ├── model.fp16.safetensors
│   ├── model.safetensors
│   |── pytorch_model.bin
|   └── pytorch_model.fp16.bin
├── tokenizer
│   ├── merges.txt
│   ├── special_tokens_map.json
│   ├── tokenizer_config.json
│   └── vocab.json
├── unet
│   ├── config.json
│   ├── diffusion_pytorch_model.bin
|   |── diffusion_pytorch_model.fp16.bin|── diffusion_pytorch_model.f16.safetensors
│   |── diffusion_pytorch_model.non_ema.bin|── diffusion_pytorch_model.non_ema.safetensors
│   └── diffusion_pytorch_model.safetensors
|── vae
.   ├── config.json
.   ├── diffusion_pytorch_model.bin
    ├── diffusion_pytorch_model.fp16.bin
    ├── diffusion_pytorch_model.fp16.safetensors
    └── diffusion_pytorch_model.safetensors

每个Pipeline都需要一个 model_index.json 文件,该文件告诉 DiffusionPipeline

  • 要从哪个Pipeline类,加载_class_name
  • 哪个版本的diffusers🧨,用于创建模型_diffusers_version
  • 子文件夹中存储了哪些库中的组件(对应于组件和子文件夹名称,对应于要从中加载类的库的名称,对应于类名称)name: [library, class]

如下是runwayml/stable-diffusion-v1-5model_index.json 文件:

{
   
  "_class_name": "StableDiffusionPipeline",
  "_diffusers_version": "0.6.0",
  "feature_extractor": [
    "transformers",
    "CLIPImageProcessor"
  ],
  "safety_checker": [
    "stable_diffusion",
    "StableDiffusionSafetyChecker"
  ],
  "scheduler": [
    "diffusers",
    "PNDMScheduler"
  ],
  "text_encoder": [
    "transformers",
    "CLIPTextModel"
  ],
  "tokenizer": [
    "transformers"
  • 27
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuezero_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值