- 人工智能
- 大模型
- 微调
- 模型评测
- 强化学习
- 多模态
【免费下载链接】LMFlow
An Extensible Toolkit for Finetuning and Inference of Large Foundation Models. Large Models for All.
导读
本文基于 LMFlow 仓库中 contrib/text2image 模块的官方文档,系统讲解如何在 LMFlow 框架下,借助 Hugging Face diffusers 生态对 Stable Diffusion 等文生图扩散模型进行端到端微调。全文覆盖环境准备、数据集目录结构与 JSON 格式规范、一键微调脚本finetune_t2i.sh的参数含义、基于 LoRA 的轻量训练原理(含源码级剖析),以及训练过程中的验证、测试与 checkpoint 保存机制。读完本文,你将能够独立组织自己的 text-image 数据集,并完整跑通一次 Stable Diffusion 的个性化微调(如概念定制、风格迁移)。
一、模块定位:LMFlow 生态中的 Text2Img 微调分支
LMFlow 是一个面向大模型微调与推理的可扩展工具箱,其核心能力集中在语言模型领域;而 contrib/text2image 则是仓库中专门为文生图扩散模型微调开辟的独立分支。官方文档将其描述为 "a fork function for fine-tuning text2image diffusion model based on diffusers, under the framework of lmflow"——即把 diffusers 的微调能力接入 LMFlow 的框架约定,复用了 LMFlow 的DatasetArguments参数体系与BaseTuner训练器基类。
从源码结构看,该分支由四个核心文件组成:
- finetune_t2i.sh:一键微调启动脚本(解析 CLI 参数并调用
accelerate launch); - finetune_t2i.py:微调入口,负责加载模型、构建数据集并启动训练;
- diffuser_args.py:三类参数类(模型、数据集、训练器)的定义;
- diffuser_finetuner.py:
DiffuserModelTuner训练器实现,继承自 LMFlow 的BaseTuner(见 src/lmflow/pipeline/finetuner.py 的同类设计)。
二、环境准备
在安装好lmflow主包之后,只需为 t2i 微调补充额外依赖:
pip install -r contrib/text2image/requirements.txt该 requirements.txt 的核心依赖为diffusers>=0.29.2。之所以单独列出,是因为扩散模型微调依赖 diffusers、peft(用于 LoRA)、accelerate(用于多卡训练)、wandb(用于日志与验证图片跟踪)等一整套生态,而主仓库的基础环境未必包含这些组件。
需要特别说明的是,当前脚本在 finetune_t2i.py 开头做了两项环境变量预设,无需用户干预:
os.environ["TOKENIZERS_PARALLELISM"] = "false" # 避免多进程 tokenizer 并行告警 os.environ["WANDB_MODE"] = "offline" # wandb 以离线模式运行,不强制联网上传其中WANDB_MODE=offline意味着验证生成的图片会记录到本地而非云端,可结合--logging_dir参数查看。
三、数据准备:目录结构与 JSON 格式
3.1 目录树结构
文档明确规定,数据集必须采用以下组织方式:在dataset_path下,默认使用img目录存放图片文件,train.json、valid.json、test.json分别作为训练、验证、测试数据的索引。后两者是可选的:如果只提供了其中一个,另一个会被自动设置为同一个文件(该逻辑由 diffuser_args.py 中的__post_init__实现)。
data └── example ├── img │ ├── 00.jpg │ ├── 01.jpg │ ├── 02.jpg │ ├── 03.jpg │ └── 04.jpg ├── train.json ├── [valid.json] └── [test.json]3.2 train.json:训练数据格式
训练集 JSON 的类型为text-image,每个实例由图片文件名与对应文本描述组成。以文档中的 DreamBooth 式概念定制(用<SKS>稀有 token 指代特定物体)为例:
{ "type": "text-image", "instances": [ { "image": "00.jpg", "text": "A photo of a <SKS> dog" }, ... ] }从 t2i_dataset.py 的实现可以确认:
CustomT2IDataset会断言data_dict["type"] == "text-image",类型不符直接报错;- 图片通过
Image.open读取后统一convert("RGB"); - 图片路径 =
dataset_path/image_folder + instance["image"],image_folder默认取参数--image_folder(脚本中传入img)。
3.3 valid.json / test.json:验证与测试数据格式
验证与测试集只需纯文本提示词(text-only类型),供训练中生成样例图片、评估模型表现使用:
{ "type": "text-only", "instances": [ { "text": "A photo of a <SKS> dog in front of Eiffel Tower." }, ... ] }官方还提供了一个可直接参考的示例数据 dog_t2i_data_example(文档中的外链,本文不再重复)。实际构建时建议:
- 训练图片保持主体清晰、背景多样,文本提示词与概念强绑定(如统一出现
<SKS>占位符); - 验证/测试提示词覆盖不同场景组合(地点、姿态、风格),用于观察模型泛化能力;
- 图片尺寸尽量一致或接近
--img_size设定值,减少 Resize/Crop 带来的形变。
3.4 数据加载与预处理的源码路径
t2i_dataset.py 的build_t2i_dataset是完整的数据流水线:
CustomT2IDataset读取原始图片与文本;EncodePreprocessor先对图片做Resize → CenterCrop/RandomCrop → ToTensor → Normalize(mean=[0.5], std=[0.5]),再通过 VAE 编码得到 latent,同时对文本用 CLIP tokenizer + text encoder 得到 embedding(t2i_dataset.py);PreprocessedT2IDataset把所有样本预先编码成{"image": latent, "text": embedding}缓存在内存中。
也就是说,训练期间 VAE 与 CLIP 文本编码器只在前处理阶段运行一次,训练循环内喂给 UNet 的是已经编码好的 latent 与 embedding——这是该实现省显存、提速的关键设计。前处理完成后,入口脚本会立刻del tokenizer, text_encoder, vae并清空 CUDA 缓存(finetune_t2i.py),进一步释放显存。
四、一键微调:finetune_t2i.sh
4.1 基本用法
文档给出的最简启动方式:
bash contrib/text2image/finetune_t2i.sh \ model_name_or_path=stabilityai/stable-diffusion-2-1 \ dataset_path=data/example其中:
model_name_or_path:Hugging Face 上的模型名或本地预训练模型路径,如stabilityai/stable-diffusion-2-1;dataset_path:按上文目录树组织的数据集根目录。
4.2 脚本支持的参数
脚本通过while/case循环解析-m/-t/-d/-o/-p/-i六个短选项(finetune_t2i.sh),默认值如下:
| 参数 | 短选项 | 默认值 | 说明 |
|---|---|---|---|
model_name_or_path | -m | stabilityai/stable-diffusion-2-1 | HF 模型名或本地模型路径 |
model_type | -t | unet | 微调目标,unet或transformer(后者尚未支持) |
dataset_path | -d | data/example | 数据集根目录 |
output_dir | -o | output | 微调结果输出目录 |
main_port | -p | 29500 | accelerate 分布式训练主端口 |
img_size | -i | 768 | 微调/验证/测试的图像尺寸 |
关于model_type=transformer:文档明确说明该类型暂未支持。对应实现中,finetune_t2i.py 在传入transformer时直接抛出NotImplementedError,其他非法值则抛出ValueError,因此当前版本请固定使用unet。
4.3 脚本背后的实际命令
脚本最终执行的是(finetune_t2i.sh):
accelerate launch \ --config_file=./accelerate_t2i_config.yaml \ --main_port=${main_port} \ finetune_t2i.py \ --model_name_or_path=${model_name_or_path} \ --model_type=${model_type} \ --use_lora=True \ --lora_target_module "to_k" "to_q" "to_v" "to_out.0" "add_k_proj" "add_v_proj" \ --dataset_path=${dataset_path} \ --image_folder="img" \ --image_size=${img_size} \ --train_file="train.json" \ --validation_file="valid.json" \ --test_file="test.json" \ --output_dir=${output_dir} \ --logging_dir="logs" \ --overwrite_output_dir=True \ --mixed_precision="fp16" \ --num_train_epochs=100 \ --train_batch_size=1 \ --learning_rate=1e-4 \ --valid_steps=50accelerate_t2i_config.yaml 默认配置为单机 4 卡(num_processes: 4、gpu_ids: all、mixed_precision: fp16)。如果显卡数量或显存规模不同,请相应调整该文件(如改为单卡可将distributed_type设为NO、num_processes设为1)。
五、参数详解:三类 Dataclass 的完整字段
脚本只是入口,真正决定行为的是 diffuser_args.py 中三个 dataclass 的全部字段。它们经HfArgumentParser合并解析,均可直接通过命令行覆盖。
5.1 T2IDatasetArguments(数据集参数)
继承自 LMFlow 的DatasetArguments(src/lmflow/args.py),新增字段:
| 字段 | 默认值 | 说明 |
|---|---|---|
image_folder | None(必填) | 图片目录名,如img |
image_size | 512 | 图片处理尺寸(脚本默认传 768) |
image_crop_type | center | 裁剪方式,center为中心裁剪,否则为随机裁剪 |
text_embedding_type | raw | 文本 embedding 获取方式 |
is_t2i | True | 模态类型标记 |
继承自基类的关键字段(脚本中已显式覆盖):train_file、validation_file、test_file。__post_init__中还有若干自动校验逻辑(diffuser_args.py):
train_file缺省时自动探测train.json,不存在则报错;- 各文件必须为
.json扩展名,否则断言失败; - 校验/测试文件若在磁盘上不存在,会被静默置回
None; - 校验与测试文件只提供一个时,两者共用同一个文件。
5.2 DiffuserModelArguments(模型参数)
| 字段 | 默认值 | 说明 |
|---|---|---|
model_name_or_path | None(必填) | 基座模型名或路径 |
model_type | None | unet(当前唯一支持) |
use_lora | False | 是否使用 LoRA 微调 |
lora_r | 8 | LoRA 秩,越小参数量越少 |
lora_alpha | 8 | LoRA 缩放系数(论文中的 alpha,控制合并比例) |
lora_target_modules | None | 应用 LoRA 的模块列表 |
lora_dropout | 0.1 | LoRA 线性层 dropout 率 |
脚本默认开启 LoRA,目标模块为 UNet 注意力层的投影矩阵:"to_k" "to_q" "to_v" "to_out.0" "add_k_proj" "add_v_proj"。对应实现见 finetune_t2i.py:开启 LoRA 时先将模型整体requires_grad_(False),再以gaussian初始化权重添加 PEFT 适配器;不开启时则全量requires_grad_(True)。
5.3 DiffuserTunerArguments(训练器参数)
| 字段 | 默认值 | 说明 |
|---|---|---|
output_dir | output | 输出目录 |
logging_dir | logs | 日志目录 |
overwrite_output_dir | False | 是否清空重建输出目录 |
mixed_precision | no | 混合精度,脚本传fp16 |
do_train | True | 是否训练 |
num_train_epochs | 50 | 训练轮数(脚本传 100) |
train_batch_size | 1 | 单卡 batch size |
learning_rate | 1e-4 | 学习率 |
weight_decay | 0.0 | 权重衰减 |
do_valid/do_test | True | 是否做验证/测试 |
valid_steps | 50 | 每多少步验证一次 |
valid_seed/test_seed | 42 | 验证/测试的随机种子(保证生成样例可复现) |
save_steps | 500 | 每多少步保存 checkpoint |
save_total_limit | None | 保留 checkpoint 总数上限 |
六、训练循环与底层原理:源码级剖析
DiffuserModelTuner(diffuser_finetuner.py)继承自BaseTuner,其tune()方法完整复刻了 Stable Diffusion 官方训练脚本的核心逻辑:
1. 噪声调度器与优化器
- 从基座模型加载
DDPMScheduler(diffuser_finetuner.py); - 只过滤
requires_grad=True的参数(即 LoRA 参数)送入 AdamW,学习率1e-4、weight decay 0; - 使用 diffusers 的
get_scheduler("constant")恒定学习率调度器(diffuser_finetuner.py)。
2. 加噪与去噪目标
每步训练随机采样 timestep,向 latent 加入高斯噪声:
noise = torch.randn_like(clean_latents) timesteps = torch.randint(0, noise_scheduler.config.num_train_timesteps, (bsz,), device=...) noisy_latents = noise_scheduler.add_noise(clean_latents, noise, timesteps) model_pred = model(noisy_latents, timesteps, text_embedding)[0]损失目标依据调度器的prediction_type分支:epsilon类型直接以噪声为回归目标,v_prediction类型则回归 v 速度(diffuser_finetuner.py),损失函数为 MSE。这是扩散模型训练的标准噪声预测损失。
3. 验证机制(valid_steps 触发)
每valid_steps步,在主进程上用当前 UNet 替换 DiffusionPipeline 中的 UNet,以valid_seed固定的生成器,按valid.json中的每个提示词生成一张图,结果写入output_dir/step_{global_step}_validation/并同步到 wandb(diffuser_finetuner.py)。这一步让你在训练中途直观看到生成质量的演进。
4. 测试机制(训练结束后)
训练完成后,若do_test=True且有test.json,会用test_seed生成最终测试图集,保存到output_dir/test_final/(diffuser_finetuner.py)。
5. Checkpoint 保存策略
- LoRA 模式:将 PEFT 状态字典转换为 diffusers 格式,通过
LoraLoaderMixin.save_lora_weights保存为 diffusers 兼容的 LoRA 权重(保存到output_dir/checkpoints/final/); - 非 LoRA 模式:用
accelerator.save保存完整模型状态字典final.pt; - 若 checkpoint 数量超过
max_checkpoints,会删除最旧的 checkpoint 以控制磁盘占用(diffuser_finetuner.py)。
6. 分布式与精度
模型、数据、优化器、调度器均经accelerator.prepare包装;mixed_precision=fp16时训练权重 dtype 为torch.float16(diffuser_finetuner.py)。main_port参数即传给accelerate launch --main_port用于分布式通信。
七、LoRA 微调:轻量概念定制的推荐路径
脚本默认--use_lora=True,这也是文档示例(Stable Diffusion 2.1 +<SKS>宠物狗定制)的标准做法。LoRA 模式的核心收益在于:
- 只训练 UNet 注意力层的低秩适配矩阵(目标模块为
to_k/to_q/to_v/to_out.0/add_k_proj/add_v_proj),训练参数量远小于全量微调,显存占用低,适合单卡或小显存环境; - 产物是 diffusers 格式的 LoRA 权重,可通过
pipeline.load_lora_weights(...)随时加载合并到原模型,实现"一个底座模型 + 多个轻量 LoRA"的多概念复用; - 训练结束后自动以
pytorch_lora_weights.safetensors形式保存(diffuser_finetuner.py)。
若想全量微调,将脚本中的--use_lora=True改为--use_lora=False即可,代价是显存需求显著上升,请务必结合accelerate_t2i_config.yaml的卡数规划。
八、从零跑通全流程:操作清单
- 安装依赖:先安装 LMFlow 主包,再执行
pip install -r contrib/text2image/requirements.txt; - 准备数据:按 3.1 的目录树组织
img/与三个 JSON 文件(参考 3.2/3.3 格式),注意train.json类型必须是text-image; - 启动训练:
bash contrib/text2image/finetune_t2i.sh \ model_name_or_path=stabilityai/stable-diffusion-2-1 \ dataset_path=data/example- 按需调参:修改脚本内默认值或直接追加
-m/-d/-o/-i等短选项;显存不足时降低img_size(如 512)、调低train_batch_size、改用单卡配置; - 观察训练:训练中每
valid_steps步在output_dir/step_*_validation/下生成验证图,配合 wandb 离线日志(output_dir/logs)监控 loss 与学习率; - 获取产物:LoRA 权重位于
output_dir/checkpoints/final/,测试图集位于output_dir/test_final/。
九、已知限制与注意事项
model_type=transformer尚未实现,当前只能微调unet(源码直接抛NotImplementedError);- 训练入口使用
WANDB_MODE=offline,未联网也能运行,但 wandb 需要本地有可写缓存目录; --overwrite_output_dir=True会先删除已有输出目录(仅主进程执行,见 finetune_t2i.py),重复实验注意保存旧结果;- 验证/测试 JSON 中任意一项缺失时,二者会被自动指向同一文件;磁盘上不存在时则静默禁用对应流程;
- 数据集图片在前处理阶段一次性编码进内存,样本量大时内存占用可观,小显存机器建议控制数据集规模并适时调低
img_size。
结语
LMFlow 的 text2image 分支用约数百行代码,将 Stable Diffusion 微调所需的模型加载、数据编码、LoRA 注入、扩散训练循环、过程验证与结果保存完整封装,同时无缝复用 LMFlow 的参数体系与BaseTuner基类。理解本文的数据格式与参数含义后,你只需准备一份规范的数据集,即可在 LMFlow 框架下快速完成文生图模型的个性化微调;深入阅读 finetune_t2i.py、diffuser_finetuner.py 与 t2i_dataset.py 三个源码文件,还能进一步按需扩展自己的训练流程。
- 人工智能
- 大模型
- 微调
- 模型评测
- 强化学习
- 多模态
【免费下载链接】LMFlow
An Extensible Toolkit for Finetuning and Inference of Large Foundation Models. Large Models for All.
相关推荐
DPOK:用强化学习(策略梯度)微调文本到图像扩散模型的完整实战指南
DPOK:用强化学习(策略梯度)微调文本到图像扩散模型的完整实战指南 DPOK 是论文《DPOK: Reinforcement Learning for Fin
人工智能深度学习NLP计算机视觉强化学习Home Assistant 上传图片到 OpenDisplay 电子墨水屏实战指南
Home Assistant 上传图片到 OpenDisplay 电子墨水屏实战指南 想让 Home Assistant 的 opendisplay.uploa
文档教程智能家居物联网PEFT 中的 OFT 详解:基于正交微调的文本到图像扩散模型参数高效微调
PEFT 中的 OFT 详解:基于正交微调的文本到图像扩散模型参数高效微调 OFT(Orthogonal Finetuning,正交微调)是 PEFT 仓库中一
人工智能大模型微调LoRA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考