- 媒体生成
- 计算机视觉
- 深度学习
- 人工智能
- 大模型
【免费下载链接】mmagic
OpenMMLab Multimodal Advanced, Generative, and Intelligent Creation Toolbox. Unlock the magic 🪄: Generative-AI (AIGC), easy-to-use APIs, awsome model zoo, diffusion models, for text-to-image generation, image/video restoration/enhancement, etc.
导读
本文以 MMagic 仓库中 configs/vico/README_zh-CN.md 为核心,系统讲解 ViCo(Detail-Preserving Visual Condition for Personalized Text-to-Image Generation,2023)这一插件式个性化生成算法的原理、配置与完整实操流程。通过本文,你将掌握:如何在 MMagic 中使用TextualInversionDataset准备个性化概念数据,如何通过修改concept_dir、placeholder、initialize_token三个核心字段定制自己的概念,如何用单卡或多卡命令训练 ViCo,以及如何加载预训练权重完成带参考图的文本引导推理;同时结合 模型实现 与 工具模块 源码,深入理解图像交叉注意力模块、基于注意力的对象蒙版与注意力正则化损失的真实实现。
ViCo 是什么:不微调扩散模型参数的个性化生成
ViCo 是 2023 年提出的一种插件式(plug-in)个性化文本到图像生成方法。与多数个性化方案直接微调扩散模型参数不同,ViCo 的核心主张是:
- 给定仅包含一个新概念(例如一只独特的玩具)的少量图像,通过调整生成模型来捕捉该概念的精细视觉细节,并依据文本条件生成逼真图像;
- 不微调原始扩散模型的任何参数,只在扩散 U-Net 中额外插入轻量的图像交叉注意力(image cross attention)模块与可训练的新 token 嵌入,全部可训练参数约占扩散 U-Net 的6%;
- 由于原始参数保持不变,模型部署更加灵活、可迁移,训练也更轻量快速。
在 MMagic 中,ViCo 的任务类型被标注为文本图像生成(Text2Image),相关论文信息与元数据可在 metafile.yml 中查证。模型的整体实现继承自 MMagic 的StableDiffusion基类(见 mmagic/models/editors/vico/vico.py 中class ViCo(StableDiffusion)),底层组件(VAE、UNet、CLIP 文本编码器、tokenizer、scheduler)均来自 HuggingFace diffusers 生态的 stable-diffusion-1.5 权重,这一点在文档的 Comments 部分也有说明。
模型结构一览
| 模型 | 数据集 | 权重下载 |
|---|---|---|
| ViCo | textual_inversion_dataset | 需从 ViCo 官方发布渠道获取预训练权重 |
其中,配置文件 configs/vico/vico.py 是训练与推理的统一入口,数据集则复用了 MMagic 的TextualInversionDataset(该数据集同时服务于 Textual Inversion 与 ViCo 两类任务,通过with_image_reference参数区分是否启用参考图)。
第一步:数据准备与目录结构
ViCo 的训练数据是一个概念(concept)图像文件夹加一个文本模板文件。文档要求先下载概念数据集与imagenet_templates_small.txt模板,并统一保存到data/vico/目录下。
文件结构应如下:
data └── vico └──batman ├── 1.jpg ├── 2.jpg ├── 3.jpg └── 4.jpg └──clock ├── 1.jpg ├── 2.jpg ├── 3.jpg └── 4.jpg ... └──imagenet_templates_small.txt要点说明:
- 每个概念子文件夹(如
batman、clock)内放置该概念的少量参考图(通常 4 张左右即可),文件名无硬性要求; imagenet_templates_small.txt是 ImageNet 小模板集合,每一行是一个形如a photo of a {}的模板句子,训练时会被随机抽取,并用{}占位符替换为你的个性化 token;- 该模板文件在配置中被显式引用:
template='data/vico/imagenet_templates_small.txt'(见 configs/vico/vico.py)。
从数据集实现看,TextualInversionDataset在prepare_data阶段会随机选择概念文件夹中的另一张图作为参考图(img_ref),并从模板文件中随机抽取一行生成 prompt(selected_template.format(self.placeholder)),细节见 mmagic/datasets/textual_inversion_dataset.py。这正是 ViCo 训练同时需要"概念图"与"参考图"的数据来源。
第二步:自定义配置文件
ViCo 的训练配置高度复用默认生成式运行时(_base_ = '../_base_/gen_default_runtime.py'),用户通常只需要关注以下三个自定义项:
# 请关注以下需自定义的内容 # 设置concept文件夹名 concept_dir = 'dog7' # 设置代表这个concept的新字符 placeholder: str = 'S*' # 初始化字符,最好是设置这个concept所属的类别 initialize_token: str = 'dog'三个字段的语义与影响:
| 字段 | 示例值 | 作用 |
|---|---|---|
concept_dir | 'dog7' | 指定data/vico/下承载该概念图片的子文件夹名,训练时由TextualInversionDataset按此目录加载图像 |
placeholder | 'S*' | 代表该概念的新 token 字符串,会出现在 prompt 中(如'A photo of S*');训练时通过tokenizer.add_placeholder_token注册为可学习 token |
initialize_token | 'dog' | 初始化字符,用于初始化新 token 的嵌入向量。文档建议设为该概念所属的类别(超类),例如狗概念用'dog',可显著加速收敛 |
从源码看,placeholder与initialize_token在ViCo.add_tokens中被消费:先用initialize_token查询其嵌入embedding_layer.weight[init_id],再按num_vectors_per_token复制扩展后作为新 token 的初始嵌入,并标记为可训练(token_info['trainable'] = True),见 mmagic/models/editors/vico/vico.py。因此initialize_token选择越接近真实类别,新 token 的起点越好。
第三步:训练
使用以下命令启动训练:
# 4 GPUS bash tools/dist_train.sh configs/vico/vico.py 4 # 1 GPU python tools/train.py configs/vico/vico.py训练入口分别是 tools/dist_train.sh(多卡)与 tools/train.py(单卡)。训练超参数在配置中已预置妥当,无需额外修改即可运行:
- 迭代数:
train_cfg = dict(max_iters=500),即默认训练 500 个 iteration(ViCo 收敛极快); - 优化器:
AdamW,lr=0.005,weight_decay=0.01,并使用paramwise_cfg对两类可训练参数施加差异化学习率:image_cross_attention:lr_mult=2e-3(图像交叉注意力模块,学习率相对主学习率放大 2e-3 倍);trainable_embeddings:lr_mult=1.0(新 token 嵌入,保持默认倍率);
- 批次:
batch_size=1,num_workers=16,采样器为InfiniteSampler; - 随机种子:
randomness = dict(seed=2023, diff_rank_seed=True),保证多卡可复现; - 日志与可视化:
default_hooks中 logger 每 10 个 iteration 打印一次日志;custom_hooks中配置了VisualizationHook,每 50 个 iteration 用固定输入可视化一次生成结果(vis_kwargs_list=dict(type='Data', name='fake_img')),方便训练过程中直观观察概念是否被学会。
训练数据流水线
配置中的pipeline展示了每个样本的处理链路(configs/vico/vico.py):
pipeline = [ dict(type='LoadImageFromFile', key='img', channel_order='rgb'), dict(type='LoadImageFromFile', key='img_ref', channel_order='rgb'), dict(type='Resize', keys=['img', 'img_ref'], scale=(512, 512)), dict( type='PackInputs', keys=['img', 'img_ref'], data_keys='prompt', meta_keys=[ 'img_channel_order', 'img_color_type', 'img_ref_channel_order', 'img_ref_color_type' ]) ]即:同时加载概念图img与参考图img_ref,统一缩放到 512×512,并打包 prompt 作为数据键。这也解释了为什么推理时 prompt 中的S*需要与训练时一致。
训练过程源码视角
ViCo.train_step(mmagic/models/editors/vico/vico.py)的关键逻辑:
- 将概念图
img与参考图img_ref在 batch 维度拼接(torch.cat([image, image_ref], dim=0)),共用一次 VAE 编码,减少一次前向开销; - 只对源概念图加噪(
scheduler.add_noise(latents[:num_batches], ...)),参考图保持干净 latent 并拼接回去; - 定位 prompt 中 placeholder token 的位置与 EOS(end-of-text)位置,组成
placeholder_position传入 UNet; - UNet 前向同时返回噪声预测
model_pred['sample']与注意力正则损失model_output['loss_reg']; - 总损失 = 扩散 MSE 损失(
vico_loss)+reg_loss_weight * loss_reg,其中reg_loss_weight默认5e-4。
此外,prepare_models(mmagic/models/editors/vico/vico.py)在训练前会冻结 VAE 与 UNet 原有参数(requires_grad_(False)),只保留文本编码器新增嵌入与image_cross_attention模块可训练——这是"仅训练约 6% 参数"的工程实现。
第四步:推理
使用预训练权重进行推理的完整脚本如下(来自原文档):
import torch from mmengine import Config from PIL import Image from mmagic.registry import MODELS from mmagic.utils import register_all_modules register_all_modules() # say you have downloaded the pretrained weights cfg = Config.fromfile('configs/vico/dog.py') state_dict = torch.load("./dog.pth") vico = MODELS.build(cfg.model) vico.load_state_dict(state_dict, strict=False) vico = vico.cuda() prompt = ["A photo of S*", "A photo of S* on the beach"] reference = "data/vico/dog7/01.jpg" image_ref = Image.open(reference) with torch.no_grad(): output = vico.infer(prompt=prompt, image_reference=image_ref, seed=123, num_images_per_prompt=2)['samples'][0] output.save("infer.png")其中configs/vico/dog.py指你按第二步自定义后的配置文件(文档示例命名,可按实际修改)。vico.infer的核心参数(对应 mmagic/models/editors/vico/vico.py 的签名):
| 参数 | 默认值 | 说明 |
|---|---|---|
prompt | 必填 | 文本提示,可传字符串或字符串列表;需包含训练时的 placeholder(如S*) |
image_reference | None | 参考图(PIL Image 或 Tensor),是 ViCo 视觉条件的信息来源 |
height/width | 由 UNet 与 VAE 尺度推导(512×512) | 生成图像尺寸 |
num_inference_steps | 50 | DDIM 去噪步数,越多质量越高但越慢 |
guidance_scale | 7.5 | 无分类器引导(CFG)强度,>1.0时启用引导 |
negative_prompt | None | 负向提示,仅在启用 CFG 时生效 |
num_images_per_prompt | 1 | 每个 prompt 生成的图像数量 |
eta | 0.0 | DDIM 的 η 参数,仅对 DDIMScheduler 生效 |
seed | 1 | 随机种子,用于可复现生成 |
return_type | 'image' | 返回类型:'image'(PIL 列表)、'numpy'、'tensor' |
推理流程(infer内部)值得注意的细节:
- 参考图会被缩放到与生成尺寸一致,经 VAE 编码为 latent,并在每一步去噪时与当前 latent 拼接送入 UNet;
- 推理时若 prompt 中不含 placeholder,则
ph_pos会退化为 EOS 位置,避免索引越界; - 采用无分类器引导时,会分别用负向/正向文本嵌入各跑一次 UNet 前向,再按
noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)合成最终噪声预测(mmagic/models/editors/vico/vico.py)。
第五步(可选):从训练 checkpoint 提取轻量推理权重
如果你希望直接用第三步训练得到的 checkpoint 推理,可以先用以下脚本把可训练参数(即image_cross_attention模块与trainable_embeddings)提取出来,得到体积小得多的权重文件:
import torch def extract_vico_parameters(state_dict): new_state_dict = dict() for k, v in state_dict.items(): if 'image_cross_attention' in k or 'trainable_embeddings' in k: new_k = k.replace('module.', '') new_state_dict[new_k] = v return new_state_dict checkpoint = torch.load("work_dirs/vico/iter_400.pth") new_checkpoint = extract_vico_parameters(checkpoint['state_dict']) torch.save(new_checkpoint, "work_dirs/vico/dog.pth")提取后的dog.pth即可按第四步的方式加载推理。这一脚本与配置中paramwise_cfg的可训练键(image_cross_attention、trainable_embeddings)完全对应,也与prepare_models中仅保留这两类参数梯度的设计一致,从侧面印证了"轻量训练、轻量部署"的设计目标。
深入原理:图像交叉注意力与注意力正则化
在 mmagic/models/editors/vico/vico_utils.py 中可以找到 ViCo 三个核心机制的完整实现,这也是论文方法的工程落地:
1. 图像交叉注意力模块(Image Cross Attention)
set_vico_modules(mmagic/models/editors/vico/vico_utils.py)会依次完成三件事:
- 用
ViCoTransformer2D替换 UNet 中所有的Transformer2DModel,并在have_image_cross=True的层上新增一个BasicTransformerBlock作为image_cross_attention(mmagic/models/editors/vico/vico_utils.py); - 用
ViCoCrossAttnProcessor替换所有attn2的 processor,使其在前向时把文本注意力概率保存到attn.attn_probs(mmagic/models/editors/vico/vico_utils.py),供后续蒙版与正则化使用; - 用
ViCoUNet2DConditionModel、ViCoCrossAttnDownBlock2D、ViCoUNetMidBlock2DCrossAttn、ViCoCrossAttnUpBlock2D包装 UNet 整体及各下采样/中间/上采样块,逐层累加正则损失loss_reg_all并透传placeholder_position。
配置中的image_cross_layers列表(16 个元素,对应 6 个下采样 transformer 块 + 1 个中间块 + 9 个上采样 transformer 块)决定哪些层插入图像交叉注意力,默认在上采样块的第 2、4、6、8 个位置置 1(configs/vico/vico.py),与测试用例 tests/test_models/test_editors/test_vico/test_vico.py 中的配置保持一致,可作为对照。
2. 基于注意力的对象蒙版(Attention-based Object Mask)
在ViCoTransformer2D.forward中,文本注意力概率attn_ph(placeholder 位置对应的注意力)经otsu函数二值化,生成几乎零额外计算成本的对象蒙版,作为图像交叉注意力的encoder_attention_mask(mmagic/models/editors/vico/vico_utils.py)。otsu(mmagic/models/editors/vico/vico_utils.py)实现的是经典的 Otsu 阈值法:在 0 到 0.9 的阈值区间内枚举,选择类间方差最大的阈值完成前景/背景分割。这一蒙版引导图像交叉注意力只关注参考图中的对象区域,避免背景干扰。
3. 注意力正则化损失(Attention Regularization)
为缓解个性化训练常见的过拟合退化,ViCo 利用文本-图像注意力图的内在属性设计了一个简单正则:在训练模式下,将 placeholder 位置与 EOS(end-of-text)位置的注意力图分别归一化后计算 MSE(mmagic/models/editors/vico/vico_utils.py):
if self.image_cross_attention.training: loss_reg = F.mse_loss( attn_ph / attn_ph.max(-1, keepdim=True)[0], attn_eot / attn_eot.max(-1, keepdim=True)[0])该损失通过各层ViCoCrossAttn*Block2D累加后返回,最终由train_step按reg_loss_weight=5e-4加权计入总损失。
交互式演示:Gradio 一键训练与推理
仓库还提供了开箱即用的 Gradio 界面 demo/gradio_vico.py,包含两个 Tab:
- Train:上传图片目录作为训练样本,填写
Init token与Placeholder,一键启动训练(内部会动态改写配置中的data_root、concept_dir、placeholder、initialize_token,并通过Runner.from_cfg训练); - Inference:选择已下载的 checkpoint、上传参考图、填写 prompt 与 negative prompt,并可通过滑杆调节 CFG(0~13)、图像宽高(256~768)、seed、推理步数(20~80)与批大小(1~4),实时查看生成结果。
该脚本展示了与上述命令行完全一致的数据流:MODELS.build(cfg.model)构建模型、model.infer(...)生成图像,非常适合快速试验不同的概念与提示词。
测试验证
ViCo 的实现质量由单元测试保障:TestViCo(tests/test_models/test_editors/test_vico/test_vico.py)使用diffusers/tiny-stable-diffusion-torch小型权重构建模型,覆盖train_step、infer等关键路径;test_vico_utils.py则针对图像交叉注意力、Otsu 蒙版与块包装等工具函数进行验证。如果你修改了 ViCo 相关代码,可以运行这两份测试确认行为未回归。
小结
ViCo 在 MMagic 中的落地路径清晰完整:数据侧复用TextualInversionDataset并提供参考图采样,模型侧在冻结的 Stable Diffusion 1.5 上插入轻量图像交叉注意力与可训练 token,训练侧通过差异化学习率与注意力正则化实现快速、稳定的概念学习,推理侧保持与 StableDiffusion 一致的infer接口。从 配置文件 到 模型实现,再到 工具模块 与 Gradio 演示,整个流程只需修改concept_dir、placeholder、initialize_token三个字段即可服务于任意新概念,非常适合作为个性化文本到图像生成的轻量级基线方案。
引用
@inproceedings{Hao2023ViCo, title={ViCo: Detail-Preserving Visual Condition for Personalized Text-to-Image Generation}, author={Shaozhe Hao and Kai Han and Shihao Zhao and Kwan-Yee K. Wong}, year={2023} }- 媒体生成
- 计算机视觉
- 深度学习
- 人工智能
- 大模型
【免费下载链接】mmagic
OpenMMLab Multimodal Advanced, Generative, and Intelligent Creation Toolbox. Unlock the magic 🪄: Generative-AI (AIGC), easy-to-use APIs, awsome model zoo, diffusion models, for text-to-image generation, image/video restoration/enhancement, etc.
相关推荐
ViCo 个性化文生图实战:在 MMagic 中基于 Stable Diffusion 实现轻量级细节保持定制生成
ViCo 个性化文生图实战:在 MMagic 中基于 Stable Diffusion 实现轻量级细节保持定制生成 ViCo(Detail Preserving
媒体生成计算机视觉深度学习人工智能大模型mmagic 中的 FastComposer:无微调多主体文本到图像生成实战指南
mmagic 中的 FastComposer:无微调多主体文本到图像生成实战指南 FastComposer 是 2023 年提出的免微调(Tuning Free
媒体生成计算机视觉深度学习人工智能大模型DCGAN架构详解:从卷积层到批量归一化的核心组件
DCGAN架构详解:从卷积层到批量归一化的核心组件 DCGAN(深度卷积生成对抗网络)是一种革命性的深度学习模型,它结合了卷积神经网络(CNN)和生成对抗网络(
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考