Diffusers Textual Inversion 加载指南:TextualInversionLoaderMixin 原理与实战
【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers
Textual Inversion(文本反演)是一种仅凭 3~5 张示例图片即可个性化扩散模型概念(如某个物体、某种画风)的训练方法,其产物是极小的词嵌入文件(仅几 KB),可随后加载进文本编码器使用。本文围绕TextualInversionLoaderMixin展开,讲解在 Diffusers 中加载 Diffusers 格式与 Automatic1111 格式嵌入的完整流程、底层实现原理,并覆盖多向量嵌入、负向嵌入与卸载等进阶用法。
什么是 Textual Inversion
Textual Inversion 通过微调模型的**词嵌入(word embeddings)**来学习新概念:把 3~5 张示例图片与一个特殊 token(如<sks>)绑定,训练后该 token 的嵌入向量便"记住"了概念。由于只更新嵌入向量而不动 UNet/VAE,训练产物通常只有几 KB,扩散模型本身仍以原始方式使用。
正因为权重极小,嵌入必须在用DiffusionPipeline.from_pretrained加载完模型之后再加载。Diffusers 通过TextualInversionLoaderMixin提供统一入口:既能加载 Diffusers 官方格式的嵌入,也能加载 Automatic1111(WebUI)生态生成的.pt嵌入文件,并把对应 token 注册进 tokenizer。
加载嵌入的完整流程
准备 pipeline
先加载基础 pipeline,再挂载嵌入:
import torch from diffusers import AutoPipelineForText2Image pipeline = AutoPipelineForText2Image.from_pretrained( "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16 ).to("cuda") # 或 "mps"、"xpu"、"cpu"加载 Diffusers 格式嵌入
pipeline.load_textual_inversion("sd-concepts-library/gta5-artwork") prompt = "A cute brown bear eating a slice of pizza, stunning color scheme, masterpiece, illustration, <gta5-artwork> style" pipeline(prompt).images[0]加载后,只需在 prompt 中写入嵌入对应的特殊 token(如<gta5-artwork>),即可激活该概念。
加载 Automatic1111 格式嵌入
Automatic1111 格式的嵌入是.pt文件(可从 CivitAI 等站点下载),加载时通常需要显式指定token:
from diffusers import StableDiffusionPipeline import torch model_id = "stable-diffusion-v1-5/stable-diffusion-v1-5" pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16).to("cuda") pipe.load_textual_inversion("./charturnerv2.pt", token="charturnerv2") prompt = "charturnerv2, multiple views of the same character in the same outfit, a character turnaround of a woman wearing a black jacket and red shirt, best quality, intricate details." image = pipe(prompt, num_inference_steps=50).images[0] image.save("character.png")源码通过_retrieve_tokens_and_embeddings自动识别两种格式:Diffusers 格式的 state dict 只有单个键(token→embedding);A1111 格式则包含string_to_param键与name键(见 textual_inversion.py)。
自定义权重文件名
若嵌入文件以自定义名称保存,用weight_name指定:
pipeline.load_textual_inversion( "EvilEngine/easynegative", weight_name="easynegative.safetensors", token="easynegative" )负向嵌入:用 Textual Inversion 提升画质
Textual Inversion 也可训练负向嵌入(negative embeddings),引导模型远离"模糊""丑陋"等不良特征。EasyNegative 是广泛使用的多概念负向嵌入。加载后把对应 token 传给negative_prompt即可生效:
import torch from diffusers import AutoPipelineForText2Image pipeline = AutoPipelineForText2Image.from_pretrained( "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16 ).to("cuda") # 或 "mps"、"xpu"、"cpu" pipeline.load_textual_inversion( "EvilEngine/easynegative", weight_name="easynegative.safetensors", token="easynegative" ) prompt = "A cute brown bear eating a slice of pizza, stunning color scheme, masterpiece, illustration" negative_prompt = "easynegative" pipeline(prompt, negative_prompt).images[0]参数详解
load_textual_inversion支持多种输入与选项,关键参数如下(完整签名见 textual_inversion.py):
| 参数 | 类型 | 说明 |
|---|---|---|
pretrained_model_name_or_path | str/PathLike/Dict或它们的 list | Hub 上的模型 ID(如sd-concepts-library/low-poly-hd-logos-icons)、本地目录(./my_text_inversion_directory/)、本地文件(./my_text_inversions.pt)或 torch state dict |
token | str/list[str],可选 | 覆盖嵌入自带的 token;当传入 list 时长度须与模型 list 一致 |
tokenizer | CLIPTokenizer,可选 | 缺省使用self.tokenizer |
text_encoder | CLIPTextModel,可选 | 缺省使用self.text_encoder |
weight_name | str,可选 | 自定义权重文件名,适用于 Diffusers 格式改名保存或 A1111 格式 |
cache_dir | str/PathLike,可选 | 模型下载缓存目录 |
force_download | bool,默认False | 是否强制重新下载权重 |
proxies | dict[str, str],可选 | 按协议/端点配置代理,如{'http': 'foo.bar:3128'} |
local_files_only | bool,默认False | 为True时只加载本地权重,不从 Hub 下载 |
hf_token | str/bool,可选 | Hub 鉴权 token;为True时使用diffusers-cli login生成的 token |
revision | str,默认"main" | 指定模型版本(分支名、标签名或 commit id) |
subfolder | str,默认"" | 模型仓库内的子目录位置 |
mirror | str,可选 | 国内下载镜像源 |
源码原理:加载过程拆解
load_textual_inversion的执行可拆解为以下步骤:
- 归一化输入:将
pretrained_model_name_or_path与token包装为 list,若未提供 token 则按模型数量复制None(L379-L387)。 - 校验输入:
_check_text_inv_inputs检查 tokenizer/text_encoder 是否缺失、list 长度是否匹配、token 是否重复(L180-L201)。 - 加载 state dict:
load_textual_inversion_state_dicts优先尝试.safetensors(learned_embeds.safetensors),失败后回退到 pickle 格式(learned_embeds.bin),两个常量定义于 textual_inversion.py。 - 解析 token 与嵌入:
_retrieve_tokens_and_embeddings区分 torch.Tensor、单键 diffusers 格式、含string_to_param的 A1111 格式三种情况;若用户传入的 token 与文件内 token 不同,会以传入的为准并打印日志(L229-L232)。 - 处理多向量嵌入:
_extend_tokens_and_embeddings将形状为(N, dim)的多向量嵌入拆成token, token_1, ..., token_{N-1}多个单向量 token(L244-L269)。 - 维度校验:每个嵌入的最后一维必须等于
text_encoder.get_input_embeddings().weight.shape[-1],否则报错(L412-L417)。 - 注入文本编码器:先处理 CPU offload hook(若之前启用过 model/sequential offload,先移除再重挂),再调用
resize_token_embeddings(len(tokenizer) + len(tokens))扩展嵌入矩阵,最后tokenizer.add_tokens(token)+input_embeddings.data[token_id] = embedding写入新向量(L420-L465)。
多向量 token 的 prompt 展开
多向量嵌入的 token 在 prompt 中如何生效?maybe_convert_prompt(L123-L178)负责把 prompt 里的单一 token 展开为token token_1 token_2 ...序列。这一逻辑被 SD、SDXL、Flux、AnimateDiff 等众多 pipeline 在编码 prompt 前调用,例如 pipeline_animatediff.py 与 encoders.py。
多嵌入批量加载与显式 tokenizer/text_encoder
load_textual_inversion支持一次加载多个嵌入(pretrained_model_name_or_path传 list 时token也须等长),并可显式指定 tokenizer 与 text_encoder。典型场景是 SDXL:它的两个文本编码器需要分别加载嵌入。
pipeline = AutoPipelineForText2Image.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0") embedding_path = hf_hub_download(repo_id="linoyts/web_y2k", filename="web_y2k_emb.safetensors", repo_type="model") state_dict = load_file(embedding_path) # 加载到 text_encoder 1(CLIP ViT-L/14) pipeline.load_textual_inversion( state_dict["clip_l"], tokens=["<s0>", "<s1>"], text_encoder=pipeline.text_encoder, tokenizer=pipeline.tokenizer, ) # 加载到 text_encoder 2(CLIP ViT-G/14) pipeline.load_textual_inversion( state_dict["clip_g"], tokens=["<s0>", "<s1>"], text_encoder=pipeline.text_encoder_2, tokenizer=pipeline.tokenizer_2, )卸载嵌入
unload_textual_inversion(L467-L605)支持移除全部或指定的嵌入:
from diffusers import AutoPipelineForText2Image pipeline = AutoPipelineForText2Image.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5") # 示例 1:移除所有 token 嵌入 pipeline.load_textual_inversion("sd-concepts-library/gta5-artwork") pipeline.load_textual_inversion("sd-concepts-library/moeb-style") pipeline.unload_textual_inversion() # 示例 2:只移除一个 token pipeline.load_textual_inversion("sd-concepts-library/moeb-style") pipeline.load_textual_inversion("sd-concepts-library/gta5-artwork") pipeline.unload_textual_inversion("<moe-bius>") # 示例 3:SDXL 上按编码器分别卸载 pipeline = AutoPipelineForText2Image.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0") # ... 先按上文方式分别加载到两个编码器 ... pipeline.unload_textual_inversion( tokens=["<s0>", "<s1>"], text_encoder=pipeline.text_encoder, tokenizer=pipeline.tokenizer ) pipeline.unload_textual_inversion( tokens=["<s0>", "<s1>"], text_encoder=pipeline.text_encoder_2, tokenizer=pipeline.tokenizer_2 )卸载时只清理"非特殊"的 added token(保留[UNK]、[EOS]等真正的特殊 token),并从文本编码器的嵌入矩阵中删除对应行、重建nn.Embedding(L592-L605)。Fast 与 Slow tokenizer 走两条不同的内部清理路径(L558-L590)。
测试验证:多格式与 CPU offload 兼容性
仓库测试 test_stable_diffusion.py 提供了三个关键用例:
test_stable_diffusion_textual_inversion:同时加载 Hub 上的 Diffusers 格式嵌入(low-poly-hd-logos-icons)与两个 A1111 格式文件(winter_style.pt、winter_style_negative.pt),并断言生成结果与基准 numpy 数据的最大差异小于阈值;test_stable_diffusion_textual_inversion_with_model_cpu_offload:验证启用enable_model_cpu_offload后加载嵌入仍正常——这正是源码中"先移除 hook、加载、再恢复 hook"逻辑(L422-L463)的回归保护;test_stable_diffusion_textual_inversion_with_sequential_cpu_offload:同上,覆盖enable_sequential_cpu_offload场景。
训练侧补充:嵌入从何而来
加载是消费端,训练是生产端。Diffusers 提供完整的训练脚本 textual_inversion.py,核心训练参数包括:
--pretrained_model_name_or_path:Hub 模型名或本地路径;--train_data_dir:训练图片目录;--placeholder_token:学习到的嵌入所绑定的特殊词(推理时必须写在 prompt 中);--initializer_token:粗略描述训练对象的初始化词;--learnable_property:style(风格,如梵高画风)或object(物体,如你的狗);--num_vectors:学习嵌入所用的向量数,越大效果越好但训练成本越高;--checkpointing_steps:保存检查点的频率,配合--resume_from_checkpoint可断点续训。
训练细节可参考 训练指南,其中还建议在显存受限时开启gradient_checkpointing与mixed_precision。训练产出的嵌入即可用本文的方法加载使用。
总结
- Textual Inversion 只训练词嵌入,产物仅几 KB,须在
from_pretrained之后通过load_textual_inversion加载; - 同时兼容 Diffusers(
learned_embeds.safetensors/.bin)与 Automatic1111(.pt)两种格式,A1111 格式通常需显式传token; - 支持多向量嵌入(自动展开为
token token_1 ...)、负向嵌入(配合negative_prompt)、批量加载与按编码器精确卸载; - 与 model/sequential CPU offload 兼容,仓库测试给出了完整的回归验证;
- 训练侧脚本与参数可参考 textual_inversion.py 与 训练文档。
【免费下载链接】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),仅供参考