mirror of
https://github.com/modelscope/DiffSynth-Studio.git
synced 2026-03-20 23:58:12 +00:00
update doc
This commit is contained in:
38
docs/Training/Differential_LoRA.md
Normal file
38
docs/Training/Differential_LoRA.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# 差分 LoRA 训练
|
||||
|
||||
差分 LoRA 训练是一种特殊的 LoRA 训练方式,旨在让模型学习图像之间的差异。
|
||||
|
||||
## 训练方案
|
||||
|
||||
我们未能找到差分 LoRA 训练最早由谁提出,这一技术已经在开源社区中流传甚久。
|
||||
|
||||
假设我们有两张内容相似的图像:图 1 和图 2。例如两张图中分别有一辆车,但图 1 中画面细节更少,图 2 中画面细节更多。在差分 LoRA 训练中,我们进行两步训练:
|
||||
|
||||
* 以图 1 为训练数据,以[标准监督训练](./Supervised_Fine_Tuning.md)的方式,训练 LoRA 1
|
||||
* 以图 2 为训练数据,将 LoRA 1 融入基础模型后,以[标准监督训练](./Supervised_Fine_Tuning.md)的方式,训练 LoRA 2
|
||||
|
||||
在第一步训练中,由于训练数据仅有一张图,LoRA 模型很容易过拟合,因此训练完成后,LoRA 1 会让模型毫不犹豫地生成图 1,无论随机种子是什么。在第二步训练中,LoRA 模型再次过拟合,因此训练完成后,在 LoRA 1 和 LoRA 2 的共同作用下,模型会毫不犹豫地生成图 2。简言之:
|
||||
|
||||
* LoRA 1 = 生成图 1
|
||||
* LoRA 1 + LoRA 2 = 生成图 2
|
||||
|
||||
此时丢弃 LoRA 1,只使用 LoRA 2,模型将会理解图 1 和图 2 的差异,使生成的内容倾向于“更不像图1,更像图 2”。
|
||||
|
||||
单一训练数据可以保证模型能够过拟合到训练数据上,但稳定性不足。为了提高稳定性,我们可以用多个图像对(image pairs)进行训练,并将训练出的 LoRA 2 进行平均,得到效果更稳定的 LoRA。
|
||||
|
||||
用这一训练方案,可以训练出一些功能奇特的 LoRA 模型。例如,使用丑陋的和漂亮的图像对,训练提升图像美感的 LoRA;使用细节少的和细节丰富的图像对,训练增加图像细节的 LoRA。
|
||||
|
||||
## 模型效果
|
||||
|
||||
我们用差分 LoRA 训练技术训练了几个美学提升 LoRA,可前往对应的模型页面查看生成效果。
|
||||
|
||||
* [DiffSynth-Studio/Qwen-Image-LoRA-ArtAug-v1](https://modelscope.cn/models/DiffSynth-Studio/Qwen-Image-LoRA-ArtAug-v1)
|
||||
* [DiffSynth-Studio/ArtAug-lora-FLUX.1dev-v1](https://modelscope.cn/models/DiffSynth-Studio/ArtAug-lora-FLUX.1dev-v1)
|
||||
|
||||
## 在训练框架中使用差分 LoRA 训练
|
||||
|
||||
第一步的训练与普通 LoRA 训练没有任何差异,在第二步的训练命令中,通过 `--preset_lora_path` 参数填入第一步的 LoRA 模型文件路径,并将 `--preset_lora_model` 设置为与 `lora_base_model` 相同的参数,即可将 LoRA 1 加载到基础模型中。
|
||||
|
||||
## 框架设计思路
|
||||
|
||||
在训练框架中,`--preset_lora_path` 指向的模型在 `DiffusionTrainingModule` 的 `switch_pipe_to_training_mode` 中完成加载。
|
||||
@@ -1,2 +1,97 @@
|
||||
# 两阶段拆分训练
|
||||
|
||||
本文档介绍拆分训练,能够自动将训练过程拆分为两阶段进行,减少显存占用,同时加快训练速度。
|
||||
|
||||
(拆分训练是实验性特性,尚未进行大规模验证,如果在使用中出现问题,请在 GitHub 上给我们提 issue。)
|
||||
|
||||
## 拆分训练
|
||||
|
||||
在大部分模型的训练过程中,大量计算发生在“前处理”中,即“与去噪模型无关的计算”,包括 VAE 编码、文本编码等。当对应的模型参数固定时,这部分计算的结果是重复的,在多个 epoch 中每个数据样本的计算结果完全相同,因此我们提供了“拆分训练”功能,该功能可以自动分析并拆分训练过程。
|
||||
|
||||
对于普通文生图模型的标准监督训练,拆分过程是非常简单的,只需要把所有 [`Pipeline Units`](/docs/Developer_Guide/Building_a_Pipeline.md#units) 的计算拆分到第一阶段,将计算结果存储到硬盘中,然后在第二阶段从硬盘中读取这些结果并进行后续计算即可。但如果前处理过程中需要梯度回传,情况就变得极其复杂,为此,我们引入了一个计算图拆分算法用于分析如何拆分计算。
|
||||
|
||||
## 计算图拆分算法
|
||||
|
||||
> (我们会在后续的文档更新中补充计算图拆分算法的详细细节)
|
||||
|
||||
## 使用拆分训练
|
||||
|
||||
拆分训练已支持[标准监督训练](./Supervised_Fine_Tuning.md)和[直接蒸馏训练](./Direct_Distill.md),在训练命令中通过 `--task` 参数控制,以 Qwen-Image 模型的 LoRA 训练为例,拆分前的训练命令为:
|
||||
|
||||
```shell
|
||||
accelerate launch examples/qwen_image/model_training/train.py \
|
||||
--dataset_base_path data/example_image_dataset \
|
||||
--dataset_metadata_path data/example_image_dataset/metadata.csv \
|
||||
--max_pixels 1048576 \
|
||||
--dataset_repeat 50 \
|
||||
--model_id_with_origin_paths "Qwen/Qwen-Image:transformer/diffusion_pytorch_model*.safetensors,Qwen/Qwen-Image:text_encoder/model*.safetensors,Qwen/Qwen-Image:vae/diffusion_pytorch_model.safetensors" \
|
||||
--learning_rate 1e-4 \
|
||||
--num_epochs 5 \
|
||||
--remove_prefix_in_ckpt "pipe.dit." \
|
||||
--output_path "./models/train/Qwen-Image_lora" \
|
||||
--lora_base_model "dit" \
|
||||
--lora_target_modules "to_q,to_k,to_v,add_q_proj,add_k_proj,add_v_proj,to_out.0,to_add_out,img_mlp.net.2,img_mod.1,txt_mlp.net.2,txt_mod.1" \
|
||||
--lora_rank 32 \
|
||||
--use_gradient_checkpointing \
|
||||
--dataset_num_workers 8 \
|
||||
--find_unused_parameters
|
||||
```
|
||||
|
||||
拆分后,在第一阶段中,做如下修改:
|
||||
|
||||
* 将 `--dataset_repeat` 改为 1,避免重复计算
|
||||
* 将 `--output_path` 改为第一阶段计算结果保存的路径
|
||||
* 添加额外参数 `--task "sft:data_process"`
|
||||
* 删除 `--model_id_with_origin_paths` 中的 DiT 模型
|
||||
|
||||
```shell
|
||||
accelerate launch examples/qwen_image/model_training/train.py \
|
||||
--dataset_base_path data/example_image_dataset \
|
||||
--dataset_metadata_path data/example_image_dataset/metadata.csv \
|
||||
--max_pixels 1048576 \
|
||||
--dataset_repeat 1 \
|
||||
--model_id_with_origin_paths "Qwen/Qwen-Image:text_encoder/model*.safetensors,Qwen/Qwen-Image:vae/diffusion_pytorch_model.safetensors" \
|
||||
--learning_rate 1e-4 \
|
||||
--num_epochs 5 \
|
||||
--remove_prefix_in_ckpt "pipe.dit." \
|
||||
--output_path "./models/train/Qwen-Image-LoRA-splited-cache" \
|
||||
--lora_base_model "dit" \
|
||||
--lora_target_modules "to_q,to_k,to_v,add_q_proj,add_k_proj,add_v_proj,to_out.0,to_add_out,img_mlp.net.2,img_mod.1,txt_mlp.net.2,txt_mod.1" \
|
||||
--lora_rank 32 \
|
||||
--use_gradient_checkpointing \
|
||||
--dataset_num_workers 8 \
|
||||
--find_unused_parameters \
|
||||
--task "sft:data_process"
|
||||
```
|
||||
|
||||
在第二阶段,做如下修改:
|
||||
|
||||
* 将 `--dataset_base_path` 改为第一阶段的 `--output_path`
|
||||
* 删除 `--dataset_metadata_path`
|
||||
* 添加额外参数 `--task "sft:train"`
|
||||
* 删除 `--model_id_with_origin_paths` 中的 Text Encoder 和 VAE 模型
|
||||
|
||||
```shell
|
||||
accelerate launch examples/qwen_image/model_training/train.py \
|
||||
--dataset_base_path "./models/train/Qwen-Image-LoRA-splited-cache" \
|
||||
--max_pixels 1048576 \
|
||||
--dataset_repeat 50 \
|
||||
--model_id_with_origin_paths "Qwen/Qwen-Image:transformer/diffusion_pytorch_model*.safetensors" \
|
||||
--learning_rate 1e-4 \
|
||||
--num_epochs 5 \
|
||||
--remove_prefix_in_ckpt "pipe.dit." \
|
||||
--output_path "./models/train/Qwen-Image-LoRA-splited" \
|
||||
--lora_base_model "dit" \
|
||||
--lora_target_modules "to_q,to_k,to_v,add_q_proj,add_k_proj,add_v_proj,to_out.0,to_add_out,img_mlp.net.2,img_mod.1,txt_mlp.net.2,txt_mod.1" \
|
||||
--lora_rank 32 \
|
||||
--use_gradient_checkpointing \
|
||||
--dataset_num_workers 8 \
|
||||
--find_unused_parameters \
|
||||
--task "sft:train"
|
||||
```
|
||||
|
||||
我们提供了样例训练脚本和验证脚本,位于 `examples/qwen_image/model_training/special/split_training`。
|
||||
|
||||
## 训练框架设计思路
|
||||
|
||||
训练框架通过 `DiffusionTrainingModule` 的 `split_pipeline_units` 方法拆分 `Pipeline` 中的计算单元。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 标准监督训练
|
||||
|
||||
在理解 [Diffusion 模型基本原理](./Understanding_Diffusion_models.md)之后,本文档介绍框架如何实现 Diffusion 模型的训练。
|
||||
在理解 [Diffusion 模型基本原理](./Understanding_Diffusion_models.md)之后,本文档介绍框架如何实现 Diffusion 模型的训练。本文档介绍框架的原理,帮助开发者编写新的训练代码,如需使用我们提供的默认训练功能,请参考[模型训练](/docs/Pipeline_Usage/Model_Training.md)。
|
||||
|
||||
回顾前文中的模型训练伪代码,当我们实际编写代码时,情况会变得极为复杂。部分模型需要输入额外的引导条件并进行预处理,例如 ControlNet;部分模型需要与去噪模型进行交叉式的计算,例如 VACE;部分模型因显存需求过大,需要开启 Gradient Checkpointing,例如 Qwen-Image 的 DiT。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user