【Diffusers库】第五篇 加载pipeline、model、schedulers

写在前面的话

  这是我们研发的用于 消费决策的AI助理 ,我们会持续优化,欢迎体验与反馈。微信扫描二维码,添加即可。
  官方链接:https://ailab.smzdm.com/

************************************************************** 分割线 ****************************************************************

  官网的这一章节,我觉得有点繁琐,部分内容在前面的博客中有提到,所以这篇梳理总结一下,省些时间。

从不同的位置加载模型

from diffusers import DiffusionPipeline, StableDiffusionPipeline,StableDiffusionImg2ImgPipeline

repo_id = "runwayml/stable-diffusion-v1-5"

# 方法一, 第一次加载会自动下载,随后再次加载会从缓存中加载
pipe = DiffusionPipeline.from_pretrained(repo_id)

# 方法二, 第一次加载会自动下载,随后再次加载会从缓存中加载
pipe = StableDiffusionPipeline.from_pretrained(repo_id)

# 方法三, 第一次加载会自动下载,随后再次加载会从缓存中加载,用于图生图
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(repo_id)

# 方法四, 从指定路径加载
repo_id = "./stable-diffusion-v1-5"
stable_diffusion = DiffusionPipeline.from_pretrained(repo_id)

加载模型的不同部分

调度器

查看可用调度器

  在进行图像生成的时候,pipeline有好几个部分,不同的部分产生的作用不一样,因而我们可以替换一下不同的组件,来提升图像生成的质量和效率。

  • 改变调度器,并且权衡图像生成时的速度和质量非常重要。
  • 模型的不同组件通常是独立训练的,您可以将组件换成性能更好的组件。
  • 在微调过程中,通常只训练一些组件,如UNet或文本编码器。

  为了检查调度器与加载模型的兼容性,可以使用compatibles函数:

from diffusers import DiffusionPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
stable_diffusion = DiffusionPipeline.from_pretrained(repo_id)
stable_diffusion.scheduler.compatibles

返回

[<class 'diffusers.schedulers.scheduling_lms_discrete.LMSDiscreteScheduler'>,
 <class 'diffusers.schedulers.scheduling_unipc_multistep.UniPCMultistepScheduler'>, 
 <class 'diffusers.utils.dummy_torch_and_torchsde_objects.DPMSolverSDEScheduler'>, 
 <class 'diffusers.schedulers.scheduling_heun_discrete.HeunDiscreteScheduler'>, 
 <class 'diffusers.schedulers.scheduling_ddim.DDIMScheduler'>, 
 <class 'diffusers.schedulers.scheduling_dpmsolver_singlestep.DPMSolverSinglestepScheduler'>, 
 <class 'diffusers.schedulers.scheduling_deis_multistep.DEISMultistepScheduler'>, 
 <class 'diffusers.schedulers.scheduling_dpmsolver_multistep.DPMSolverMultistepScheduler'>, 
 <class 'diffusers.schedulers.scheduling_pndm.PNDMScheduler'>, 
 <class 'diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler'>, 
 <class 'diffusers.schedulers.scheduling_k_dpm_2_discrete.KDPM2DiscreteScheduler'>, 
 <class 'diffusers.schedulers.scheduling_ddpm.DDPMScheduler'>, 
 <class 'diffusers.schedulers.scheduling_k_dpm_2_ancestral_discrete.KDPM2AncestralDiscreteScheduler'>, 
 <class 'diffusers.schedulers.scheduling_euler_ancestral_discrete.EulerAncestralDiscreteScheduler'>]

这里可以看到这个pipeline可以使用的调度器

更换可用调度器

from diffusers import DiffusionPipeline, EulerDiscreteScheduler, DPMSolverMultistepScheduler
repo_id = "runwayml/stable-diffusion-v1-5"

# 使用EulerDiscreteScheduler中的调度器,替换默认的调度器,但是需要指定文件夹
scheduler = EulerDiscreteScheduler.from_pretrained(repo_id, subfolder="scheduler")
stable_diffusion = DiffusionPipeline.from_pretrained(repo_id, scheduler=scheduler)

安全模型

主要通过from_pretrained方法中的safety_checker参数来设定的。这个主要是 防止色情和暴力之类的。

from diffusers import DiffusionPipeline

repo_id = "runwayml/stable-diffusion-v1-5"
stable_diffusion = DiffusionPipeline.from_pretrained(repo_id, safety_checker=None)

重复使用组件

还可以在多个pipeline中,使用相同的组件,以避免重复加载:

from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline

model_id = "runwayml/stable-diffusion-v1-5"
stable_diffusion_txt2img = StableDiffusionPipeline.from_pretrained(model_id)
components = stable_diffusion_txt2img.components

for i in components:
     print(i)

输出了这个pipeline里的不同的组件,这些组件中记录了模型参数、网络结构等等:

vae
text_encoder
tokenizer
unet
scheduler
safety_checker
feature_extractor

然后,可以将组件传递到另一个pipeline,无需将模型重新加载到内存中:

stable_diffusion_img2img = StableDiffusionImg2ImgPipeline(**components)

当然,也可以分开加载:

from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline

model_id = "runwayml/stable-diffusion-v1-5"
stable_diffusion_txt2img = StableDiffusionPipeline.from_pretrained(model_id)
stable_diffusion_img2img = StableDiffusionImg2ImgPipeline(
    vae=stable_diffusion_txt2img.vae,
    text_encoder=stable_diffusion_txt2img.text_encoder,
    tokenizer=stable_diffusion_txt2img.tokenizer,
    unet=stable_diffusion_txt2img.unet,
    scheduler=stable_diffusion_txt2img.scheduler,
    safety_checker=None,
    feature_extractor=None,
    requires_safety_checker=False,
)

模型变种

这个概念可能比较陌生,我的理解就是在预训练模型的基础上,训练出来的模型,叫做模型变体(Checkpoint variants)

  • 模型中的参数的数据类型在进行存储的时候是有选择的,比如:torch.float16,可以获得较低的精度和较低的存储空间。但是,如果使用的是CPU,则不能使用此变体。
  • Non-exponential mean averaged (EMA) weights 不能进行图例,只能进行微调模型。

加载

另外,还有2个重要的参数,在加载模型的时候要使用,
一个是指定torch_dtype(数据格式),就是上文中提到的torch.float16,
一个是指定variant(模型变种),我感觉,这个参数会明确加载模型时的目的,是用于推理 or 训练。

from diffusers import DiffusionPipeline

# load fp16 variant
stable_diffusion = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", variant="fp16", torch_dtype=torch.float16
)
# load non_ema variant
stable_diffusion = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", variant="non_ema")

保存

保存的时候,使用 DiffusionPipeline.save_pretrained() 函数,并且要指明 variant 参数是:fp16 or non_ema,应该将模型保存到与原始检查点相同的文件夹中,这样您就可以从同一文件夹加载这两个模型了:

from diffusers import DiffusionPipeline

# save as fp16 variant
stable_diffusion.save_pretrained("runwayml/stable-diffusion-v1-5", variant="fp16")
# save as non-ema variant
stable_diffusion.save_pretrained("runwayml/stable-diffusion-v1-5", variant="non_ema")

如果不将模型保存到现有文件夹中,则必须指定模型参数,否则它将引发异常,找不到模型:

# 👎 this won't work
stable_diffusion = DiffusionPipeline.from_pretrained("./stable-diffusion-v1-5", torch_dtype=torch.float16)
# 👍 this works
stable_diffusion = DiffusionPipeline.from_pretrained(
    "./stable-diffusion-v1-5", variant="fp16", torch_dtype=torch.float16
)

模型和调度器

模型

ModelMixin.from_pretrained() 函数会下载和缓存最新版本的模型。假如本地已经存在,则不会重复下载。
可以使用subfolder参数从子文件夹加载模型。例如,“runwayml/stable-diffusion-v1-5”的模型权重存储在unet子文件夹中:

from diffusers import UNet2DConditionModel

repo_id = "runwayml/stable-diffusion-v1-5"
model = UNet2DConditionModel.from_pretrained(repo_id, subfolder="unet")

或者 直接从工程目录下面加载

from diffusers import UNet2DModel

repo_id = "google/ddpm-cifar10-32"
model = UNet2DModel.from_pretrained(repo_id)

也可以通过ModelMixin来加载和保存模型变量: ModelMixin.from_pretrained() 和 ModelMixin.save_pretrained():

from diffusers import UNet2DConditionModel

model = UNet2DConditionModel.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="unet", variant="non-ema")
model.save_pretrained("./local-unet", variant="non-ema")

调度器

调度器的加载可以使用 SchedulerMixin.from_pretrained() ,调度器不会被训练。调度器不会消耗大量的内存。下面的代码可以尝试加载不同的调度器。

from diffusers import StableDiffusionPipeline
from diffusers import (
    DDPMScheduler,
    DDIMScheduler,
    PNDMScheduler,
    LMSDiscreteScheduler,
    EulerDiscreteScheduler,
    EulerAncestralDiscreteScheduler,
    DPMSolverMultistepScheduler,
)

repo_id = "runwayml/stable-diffusion-v1-5"

ddpm = DDPMScheduler.from_pretrained(repo_id, subfolder="scheduler")
ddim = DDIMScheduler.from_pretrained(repo_id, subfolder="scheduler")
pndm = PNDMScheduler.from_pretrained(repo_id, subfolder="scheduler")
lms = LMSDiscreteScheduler.from_pretrained(repo_id, subfolder="scheduler")
euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(repo_id, subfolder="scheduler")
euler = EulerDiscreteScheduler.from_pretrained(repo_id, subfolder="scheduler")
dpm = DPMSolverMultistepScheduler.from_pretrained(repo_id, subfolder="scheduler")

# replace `dpm` with any of `ddpm`, `ddim`, `pndm`, `lms`, `euler_anc`, `euler`
pipeline = StableDiffusionPipeline.from_pretrained(repo_id, scheduler=dpm)

关于model_index.json

一般情况下,在hugging-face下的模型工程,都会存在一个model_index.json,用来说明该模型下的工程文件配置。比如:runwayml/stable-diffusion-v1-5。尤其在实例化之后,pipeline中的各个组件的默认使用情况,就和model_index.json中记载的一样。如下文件就是runwayml/stable-diffusion-v1-5的默认指定组件。

{
  "_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",
    "CLIPTokenizer"
  ],
  "unet": [
    "diffusers",
    "UNet2DConditionModel"
  ],
  "vae": [
    "diffusers",
    "AutoencoderKL"
  ]
}

### Hugging Face Diffusers 使用指南 #### 一、简介 Hugging Face Diffusers 是一个用于实现扩散模型的深度学习,能够帮助开发者轻松创建高质量的图像和音频内容。通过该可以快速上手并掌握如何构建基于扩散模型的应用程序[^1]。 #### 二、安装与配置 要开始使用Diffusers,需先完成其安装过程: 对于Python环境而言,推荐采用pip工具来进行包管理;打开命令行终端执行如下指令即可下载最新版本的Diffusers: ```bash pip install diffusers ``` 如果希望获得更稳定的体验,则可以选择指定特定版本号的方式进行安装: ```bash pip install "diffusers==0.9.0" ``` 另外,在某些情况下可能还需要额外安装其他依赖项,比如transformers等辅助来增强功能支持。此时可以通过下面这条语句一次性搞定所有必要的组件: ```bash pip install "diffusers[torch]" ``` #### 三、基础操作实例 一旦成功设置了工作空间之后就可以着手尝试一些简单的例子啦! 这里给出一段用来加载预训练好的稳定扩散模型(Stable Diffusion Model)并将随机噪声逐步转化为逼真图片的小脚本作为入门级练习: ```python from diffusers import StableDiffusionPipeline import torch model_id = "CompVis/stable-diffusion-v1-4" device = "cuda" if torch.cuda.is_available() else "cpu" pipe = StableDiffusionPipeline.from_pretrained(model_id).to(device) prompt = "a photograph of an astronaut riding a horse" image = pipe(prompt)["sample"][0] image.save("astronaut_rides_horse.png") ``` 上述代码片段展示了如何定义目标描述文本(`prompt`)并通过调用`pipe()`方法传入参数触发生成流程最终得到一张保存于本地磁盘上的PNG格式文件。 #### 四、深入探究 当掌握了基础知识以后不妨继续挖掘更多有趣的话题吧!例如探索不同类型的扩散算法差异所在或是研究怎样优化超参设置提高产出效率等等。官方文档提供了详尽的技术细节说明以及丰富的实践案例供参考学习[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值