尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Diffusers 管道加载指南:Pipeline、模型与 Scheduler 的加载、替换与复用实战

Diffusers 管道加载指南:Pipeline、模型与 Scheduler 的加载、替换与复用实战 Diffusers 管道加载指南Pipeline、模型与 Scheduler 的加载、替换与复用实战【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers本篇技术指南以 Diffusers 官方文档《파이프라인, 모델, 스케줄러 불러오기》加载管道、模型与调度器为骨架系统讲解如何通过DiffusionPipeline.from_pretrained从 Hugging Face Hub 或本地磁盘加载完整扩散模型如何按任务替换管道内部的调度器与安全检测器等组件、复用组件以节省内存以及如何加载 fp16 / non-EMA 等 checkpoint variant。读完本文你将掌握 Diffusers 中管道Pipeline 模型Model 调度器Scheduler三类对象的加载机制、背后的model_index.json工作原理并能直接在自己的推理与微调脚本中落地这些用法。Diffusion 管道一次加载全链路可用扩散模型天然由多个组件构成——文本编码器、VAE、UNet或 Transformer、分词器、调度器、特征提取器等它们之间存在着复杂的交互关系。Diffusers 的设计目标就是把这些复杂性收敛到一个简洁统一的 API 之下同时保留对每个组件进行灵活定制的空间。DiffusionPipeline正是这个统一入口它将扩散模型的复杂性封装进单一管道 API并允许你针对具体任务自由替换其中的任何组件。从 Hub 自动加载DiffusionPipeline.from_pretrainedDiffusionPipeline是从 Hub 加载扩散模型最简单、最通用的方式。DiffusionPipeline.from_pretrained会依次完成三件事自动探测合适的管道类、下载并缓存所需的配置文件与权重文件、返回管道实例from diffusers import DiffusionPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 pipe DiffusionPipeline.from_pretrained(repo_id)从源码实现看from_pretrained定义于 pipeline_utils.py首先会判断传入的pretrained_model_name_or_path是否为本地目录若是本地路径则直接使用否则调用cls.download(...)走 Hub 下载与缓存流程。随后通过cls.load_config(cached_folder)读取仓库根目录下的model_index.json并据此解析出应加载的管道类与各个组件见下文DiffusionPipeline 工作原理一节。显式指定管道类你也可以跳过自动探测直接实例化具体的管道类。下面的代码与上面自动加载返回的是同一个实例from diffusers import StableDiffusionPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 pipe StableDiffusionPipeline.from_pretrained(repo_id)多任务 checkpoint按任务选择管道像CompVis/stable-diffusion-v1-4或stable-diffusion-v1-5/stable-diffusion-v1-5这类 checkpoint 可以同时服务于多个任务例如同时支持 text-to-image 与 image-to-image。如果你想把它用于非默认任务就必须使用与该任务对应的 task-specific 管道类from diffusers import StableDiffusionImg2ImgPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 pipe StableDiffusionImg2ImgPipeline.from_pretrained(repo_id)同一份权重文件由不同管道类包装后即可服务于不同任务这正是 Diffusers 管道体系的核心灵活性所在。从本地路径加载管道如果不希望每次都走 Hub可以先用git-lfs把 checkpoint 完整克隆到本地磁盘git lfs install git clone https://huggingface.co/stable-diffusion-v1-5/stable-diffusion-v1-5执行后会在当前目录生成./stable-diffusion-v1-5文件夹然后直接把本地路径传给from_pretrainedfrom diffusers import DiffusionPipeline repo_id ./stable-diffusion-v1-5 stable_diffusion DiffusionPipeline.from_pretrained(repo_id)当repo_id是本地路径时from_pretrained会自动识别并跳过 Hub 下载对应源码中if not os.path.isdir(pretrained_model_name_or_path)的分支判断见 pipeline_utils.py。这也意味着即使本地 checkpoint 不是最新版本它也不会主动去拉取新版本而是直接使用磁盘上现有的权重——适合离线环境与版本固定的复现场景。管道内组件替换按需定制推理链路管道内部的每个组件都可以替换为兼容的其他组件。组件替换之所以重要主要有三个原因调度器决定了速度与质量的权衡选用哪种调度器直接定义了生成速度与生成质量之间的取舍组件独立训练、择优替换扩散模型的各组件通常是独立训练的当某个更优的组件出现时可以直接替换进去提升整体效果微调通常只动部分组件微调阶段往往只训练 UNet 或文本编码器等部分组件其余组件保持预训练权重即可。查看兼容调度器compatibles 属性某个调度器与哪些调度器兼容可以通过compatibles属性查询。从源码看该属性定义在 scheduling_utils.py它会基于调度器类声明的_compatibles列表返回一组可互相替换的调度器类from diffusers import DiffusionPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 stable_diffusion DiffusionPipeline.from_pretrained(repo_id) stable_diffusion.scheduler.compatibles替换调度器示例换用 EulerDiscreteScheduler下面用SchedulerMixin.from_pretrained把默认的PNDMScheduler替换为收敛更快的EulerDiscreteScheduler。注意加载调度器时必须用subfolder参数指明该管道仓库中的scheduler子目录即 scheduler/scheduler_config.json然后把这个新实例作为scheduler参数传入管道from diffusers import DiffusionPipeline, EulerDiscreteScheduler, DPMSolverMultistepScheduler repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 scheduler EulerDiscreteScheduler.from_pretrained(repo_id, subfolderscheduler) stable_diffusion DiffusionPipeline.from_pretrained(repo_id, schedulerscheduler)调度器替换是 Diffusers 中成本最低、收益最直观的优化手段——不改动任何模型权重仅通过改变采样步进策略就能影响生成速度与画质。禁用安全检测器safety_checkerNone像 Stable Diffusion 这类模型可能生成有害内容。为此 Diffusers 内置了安全检测器safety checker对输出图像进行有害性筛查其实现位于仓库的 safety_checker.py。如果你不希望使用安全检测器例如在本地实验、内容审核已自行处理等场景把safety_checker参数设为None即可from diffusers import DiffusionPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 stable_diffusion DiffusionPipeline.from_pretrained(repo_id, safety_checkerNone)组件复用多个管道共享同一份权重如果多个管道反复使用同一个模型没有必要在 RAM 中重复加载相同权重。DiffusionPipeline.components属性见 pipeline_utils.py会返回一个包含管道全部模块的字典——实现上它会从管道配置中提取所有非可选组件并逐一与管道类签名中的期望模块比对不一致时主动抛错保证复用时的类型安全。全量复用from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline model_id stable-diffusion-v1-5/stable-diffusion-v1-5 stable_diffusion_txt2img StableDiffusionPipeline.from_pretrained(model_id) components stable_diffusion_txt2img.components然后把这个components字典整体传给另一个管道从而在不重复占用内存的前提下复用同一批权重stable_diffusion_img2img StableDiffusionImg2ImgPipeline(**components)选择性复用也可以逐一手动挑选组件。例如复用 txt2img 管道中的全部核心组件但显式剔除安全检测器safety_checker与特征提取器feature_extractorfrom diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline model_id stable-diffusion-v1-5/stable-diffusion-v1-5 stable_diffusion_txt2img StableDiffusionPipeline.from_pretrained(model_id) stable_diffusion_img2img StableDiffusionImg2ImgPipeline( vaestable_diffusion_txt2img.vae, text_encoderstable_diffusion_txt2img.text_encoder, tokenizerstable_diffusion_txt2img.tokenizer, unetstable_diffusion_txt2img.unet, schedulerstable_diffusion_txt2img.scheduler, safety_checkerNone, feature_extractorNone, requires_safety_checkerFalse, )注意这里同时把requires_safety_checker设为False因为管道类在初始化时会根据该标志决定是否强制要求安全检测器组件。Checkpoint variantsfp16 与 non-EMA 权重Variant 通常指下面两类 checkpoint低精度浮点权重如torch.float16体积更小、推理更快但无法用于继续训练也无法在 CPU 环境运行Non-EMA 权重EMA指数移动平均权重在推理阶段通常效果更稳定而 non-EMA 权重一般仅推荐在微调阶段使用不建议用于推理。 提示如果两个 checkpoint 模型结构相同、但由不同的训练环境或数据集训练而成它们不应作为 variant 存放于同一仓库而应作为独立仓库分开管理例如stable-diffusion-v1-4与stable-diffusion-v1-5就是两个独立仓库。权重文件命名约定checkpoint 类型权重文件名加载参数原始originaldiffusion_pytorch_model.bin浮点精度floating pointdiffusion_pytorch_model.fp16.binvariant、dtypenon-EMAdiffusion_pytorch_model.non_ema.binvariant两个关键参数dtype 与 variant加载 variant 时有 2 个重要的参数dtype定义加载权重的浮点精度。例如传dtypetorch.float16会把权重转换为 fp16不指定时默认加载 fp32 权重。也可以先不带variant加载 checkpoint再用dtypetorch.float16在内存中完成 fp16 转换——此时会先下载默认 fp32 权重加载后再转换variant指定从仓库中加载哪个 variant。例如要从diffusers/stable-diffusion-variants仓库加载non_emacheckpoint需要传variantnon_ema。from diffusers import DiffusionPipeline # 加载 fp16 variant stable_diffusion DiffusionPipeline.from_pretrained( stable-diffusion-v1-5/stable-diffusion-v1-5, variantfp16, dtypetorch.float16 ) # 加载 non_ema variant stable_diffusion DiffusionPipeline.from_pretrained(stable-diffusion-v1-5/stable-diffusion-v1-5, variantnon_ema)从源码看variant 的识别与校验发生在 pipeline_utils.py加载时会调用_identify_model_variants检查各子文件夹中是否存在与 variant 匹配的权重文件例如由diffusion_pytorch_model.safetensors匹配diffusion_pytorch_model.fp16.safetensors若指定了variant却找不到任何对应文件会直接抛出ValueError提示。保存 variantsave_pretrained要把其他浮点精度或 non-EMA 权重的 checkpoint 保存下来需要使用DiffusionPipeline.save_pretrained并显式传入variant参数。variant 应当与原始 checkpoint 保存在同一文件夹中这样同一个文件夹可以同时加载原始 checkpoint 与各 variantfrom diffusers import DiffusionPipeline # 保存为 fp16 variant stable_diffusion.save_pretrained(stable-diffusion-v1-5/stable-diffusion-v1-5, variantfp16) # 保存为 non-ema variant stable_diffusion.save_pretrained(stable-diffusion-v1-5/stable-diffusion-v1-5, variantnon_ema)本地文件夹加载 variant 的注意事项如果 variant 没有与原始 checkpoint 保存在同一文件夹中那么加载时必须显式传入variant参数否则会因为找不到原始 checkpoint 而报错# 这样不行 stable_diffusion DiffusionPipeline.from_pretrained(./stable-diffusion-v1-5, dtypetorch.float16) # 这样才行 stable_diffusion DiffusionPipeline.from_pretrained( ./stable-diffusion-v1-5, variantfp16, dtypetorch.float16 )单独加载模型组件用 ModelMixin.from_pretrained 加载模型模型通过ModelMixin.from_pretrained加载定义于 modeling_utils.py。该方法会下载并缓存最新版本的权重文件与配置文件如果本地缓存中已有最新版本则直接复用缓存不再重复下载。模型从subfolder参数指定的子文件夹加载。例如stable-diffusion-v1-5/stable-diffusion-v1-5的 UNet 权重存放在unet子文件夹中from diffusers import UNet2DConditionModel repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 model UNet2DConditionModel.from_pretrained(repo_id, subfolderunet)也可以直接从模型自身的独立仓库加载此时无需 subfolder例如from diffusers import UNet2DModel repo_id google/ddpm-cifar10-32 model UNet2DModel.from_pretrained(repo_id)加载带 variant 的模型前面讲过的variant参数同样适用于单独加载模型——可以加载 non-EMA 或 fp16 权重并配合save_pretrained保存from diffusers import UNet2DConditionModel model UNet2DConditionModel.from_pretrained(stable-diffusion-v1-5/stable-diffusion-v1-5, subfolderunet, variantnon-ema) model.save_pretrained(./local-unet, variantnon-ema)调度器加载无权重纯配置驱动调度器通过SchedulerMixin.from_pretrained加载见 scheduling_utils.py。与模型不同调度器没有独立的权重因此不需要训练完全由子文件夹中的配置文件scheduler_config.json定义——从源码可以看到from_pretrained的核心就是load_config读取配置 JSON再交给from_config实例化。加载多个调度器并不会显著增加内存消耗而且多个调度器可以共享同一份调度器配置。下面这些调度器都与StableDiffusionPipeline兼容意味着它们可以共用同一个调度器配置文件from diffusers import StableDiffusionPipeline from diffusers import ( DDPMScheduler, DDIMScheduler, PNDMScheduler, LMSDiscreteScheduler, EulerDiscreteScheduler, EulerAncestralDiscreteScheduler, DPMSolverMultistepScheduler, ) repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 ddpm DDPMScheduler.from_pretrained(repo_id, subfolderscheduler) ddim DDIMScheduler.from_pretrained(repo_id, subfolderscheduler) pndm PNDMScheduler.from_pretrained(repo_id, subfolderscheduler) lms LMSDiscreteScheduler.from_pretrained(repo_id, subfolderscheduler) euler_anc EulerAncestralDiscreteScheduler.from_pretrained(repo_id, subfolderscheduler) euler EulerDiscreteScheduler.from_pretrained(repo_id, subfolderscheduler) dpm DPMSolverMultistepScheduler.from_pretrained(repo_id, subfolderscheduler) # 把 dpm 换成 ddpm、ddim、pndm、lms、euler_anc、euler 中的任意一个都可以 pipeline StableDiffusionPipeline.from_pretrained(repo_id, schedulerdpm)DiffusionPipeline 工作原理model_index.json 与组件结构from_pretrained 的两大职责作为类方法DiffusionPipeline.from_pretrained承担两件事下载并缓存最新版本的管道文件若本地缓存中已存在最新版本则直接复用缓存不再重复下载通过model_index.json探测与 checkpoint 对应的合适管道类并完成实例化。源码中对应的关键步骤位于 pipeline_utils.py先完成下载/本地路径判断接着load_config读取model_index.json随后_get_pipeline_class根据_class_name解析出目标管道类最后按model_index.json中声明的组件清单逐一加载各子模型load_sub_model。管道文件夹结构与类结构一一对应管道的文件夹结构与管道类的结构直接对应。以StableDiffusionPipeline为例它对应stable-diffusion-v1-5/stable-diffusion-v1-5仓库的结构. ├── feature_extractor │ └── preprocessor_config.json ├── model_index.json ├── safety_checker │ ├── config.json │ └── pytorch_model.bin ├── scheduler │ └── scheduler_config.json ├── text_encoder │ ├── config.json │ └── pytorch_model.bin ├── tokenizer │ ├── merges.txt │ ├── special_tokens_map.json │ ├── tokenizer_config.json │ └── vocab.json ├── unet │ ├── config.json │ ├── diffusion_pytorch_model.bin └── vae ├── config.json ├── diffusion_pytorch_model.bin每个组件都有自己独立的子文件夹。加载管道后打印实例可以看到StableDiffusionPipeline由 7 个组件构成from diffusers import DiffusionPipeline repo_id stable-diffusion-v1-5/stable-diffusion-v1-5 pipeline DiffusionPipeline.from_pretrained(repo_id) print(pipeline)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 ] }各组件说明feature_extractorCLIPImageProcessor实例来自 transformerssafety_checker用于筛查有害内容的StableDiffusionSafetyChecker组件实现在 safety_checker.pyschedulerPNDMScheduler实例text_encoderCLIPTextModel实例来自 transformerstokenizerCLIPTokenizer实例来自 transformersunetUNet2DConditionModel实例vaeAutoencoderKL实例。每个组件都可以通过管道实例的属性直接访问例如pipeline.tokenizerCLIPTokenizer( name_or_path/root/.cache/huggingface/hub/models--runwayml--stable-diffusion-v1-5/snapshots/39593d5650112b4cc580433f6b0435385882d819/tokenizer, vocab_size49408, model_max_length77, is_fastFalse, padding_sideright, truncation_sideright, special_tokens{ bos_token: AddedToken(|startoftext|, rstripFalse, lstripFalse, single_wordFalse, normalizedTrue), eos_token: AddedToken(|endoftext|, rstripFalse, lstripFalse, single_wordFalse, normalizedTrue), unk_token: AddedToken(|endoftext|, rstripFalse, lstripFalse, single_wordFalse, normalizedTrue), pad_token: |endoftext|, }, )model_index.json管道的装配说明书每个管道仓库根目录下的model_index.json都向DiffusionPipeline传递三类关键信息_class_name告知应使用哪个管道类_diffusers_version告知管道内模型是由哪个版本的 Diffusers 创建的各组件条目告知每个组件由哪个库的哪个类创建。例如feature_extractor: [transformers, CLIPImageProcessor]表示feature_extractor组件由 transformers 库的CLIPImageProcessor类创建。{ _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 ] }理解这份文件就等于理解了 Diffusers 管道加载的底层契约DiffusionPipeline只是读说明书装配机器——它按model_index.json声明的类清单从对应子文件夹加载每个组件最终组装成可运行的管道实例。这也解释了为什么自定义管道、社区管道community pipeline都能通过同一套from_pretrained机制被加载只要仓库里存在合法的model_index.json或对应的pipeline.py装配流程就能自动完成。小结加载管道DiffusionPipeline.from_pretrained自动探测管道类并下载缓存权重也可显式使用StableDiffusionPipeline、StableDiffusionImg2ImgPipeline等 task-specific 类本地加载直接传目录路径即可。替换组件调度器通过subfolderscheduler单独加载后传入管道不想要安全检测器就传safety_checkerNone用components属性在多个管道间复用权重避免 RAM 重复占用。加载 variant用variantfp16/variantnon_ema配合dtype加载低精度或 non-EMA 权重用save_pretrained(..., variant...)保存未与原始权重同目录时加载必须显式指定 variant。加载模型与调度器模型用ModelMixin.from_pretrained支持subfolder与variant调度器用SchedulerMixin.from_pretrained纯配置驱动、无权重、可共享同一份配置。理解原理管道文件夹结构与管道类一一对应model_index.json中的_class_name、_diffusers_version与组件类声明共同驱动整个装配流程相关实现可深入阅读 pipeline_utils.py、modeling_utils.py 与 scheduling_utils.py。掌握这些加载技巧后无论是快速跑通推理、做调度器对比实验、多任务复用权重还是管理 fp16 / non-EMA 等异构 checkpoint你都能以最少的代码与内存开销完成。【免费下载链接】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),仅供参考
返回列表