当前位置:   article > 正文

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

diffusers from_pretrained

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)
  • 1
  • 2
  • 3
  • 4

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

from diffusers import StableDiffusionPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionPipeline.from_pretrained(repo_id, use_safetensors=True)
  • 1
  • 2
  • 3
  • 4

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

from diffusers import StableDiffusionImg2ImgPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(repo_id)
  • 1
  • 2
  • 3
  • 4

除了直接从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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 推送 自定义组件/pipeline 到 Hub:

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

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

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

  • 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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
1.2 from_pretrained加载原理
  • Pipeline根据model_index.json进行加载各个子文件夹的组件类;
  • 各个组件类根据子文件夹中的config.json加载对应类的实例;

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

  • “feature_extractor”:来自 Transformer 的
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/321844
推荐阅读