@@ -36,70 +36,58 @@ python -u train_dreambooth.py \
3636 --instance_data_dir=$INSTANCE_DIR \
3737 --output_dir=$OUTPUT_DIR \
3838 --instance_prompt=" a photo of sks dog" \
39- --height=512 \
40- --width=512 \
39+ --resolution=512 \
4140 --train_batch_size=1 \
4241 --gradient_accumulation_steps=1 \
4342 --learning_rate=5e-6 \
4443 --lr_scheduler=" constant" \
4544 --lr_warmup_steps=0 \
4645 --max_train_steps=400
4746```
48- 或
49- ``` bash
50- bash run_single.sh
51- ```
52- | ppdiffusers支持的模型名称 | huggingface对应的模型地址 | Tips备注 |
53- | ---------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------- |
54- | CompVis/stable-diffusion-v1-4 | https://huggingface.co/CompVis/stable-diffusion-v1-4 | 原版SD模型,模型使用PNDM scheduler。 |
55- | hakurei/waifu-diffusion | https://huggingface.co/hakurei/waifu-diffusion | Waifu v1-2的模型,模型使用了DDIM scheduler。 |
56- | hakurei/waifu-diffusion-v1-3 | https://huggingface.co/hakurei/waifu-diffusion | Waifu v1-3的模型,模型使用了PNDM scheduler。 |
57- | naclbit/trinart_stable_diffusion_v2_60k | https://huggingface.co/naclbit/trinart_stable_diffusion_v2 | trinart 经过60k步数训练得到的模型,模型使用了DDIM scheduler。 |
58- | naclbit/trinart_stable_diffusion_v2_95k | https://huggingface.co/naclbit/trinart_stable_diffusion_v2 | trinart 经过95k步数训练得到的模型,模型使用了DDIM scheduler。 |
59- | naclbit/trinart_stable_diffusion_v2_115k | https://huggingface.co/naclbit/trinart_stable_diffusion_v2 | trinart 经过115k步数训练得到的模型,模型使用了DDIM scheduler。 |
60- | Deltaadams/Hentai-Diffusion | https://huggingface.co/Deltaadams/Hentai-Diffusion | Hentai模型,模型使用了PNDM scheduler。 |
61- | IDEA-CCNL/Taiyi-Stable-Diffusion-1B-Chinese-v0.1 | https://huggingface.co/IDEA-CCNL/Taiyi-Stable-Diffusion-1B-Chinese-v0.1 | 中文StableDiffusion模型,模型使用了PNDM scheduler。 |
62- | IDEA-CCNL/Taiyi-Stable-Diffusion-1B-Chinese-EN-v0.1 | https://huggingface.co/IDEA-CCNL/Taiyi-Stable-Diffusion-1B-Chinese-EN-v0.1 | 中文+英文双语言的StableDiffusion模型,模型使用了PNDM scheduler。 |
63-
6447
6548` train_dreambooth.py ` 代码可传入的参数解释如下:
6649> 主要修改的参数
67- > * ` --pretrained_model_name_or_path ` : 所使用的Stable Diffusion模型权重名称或者本地下载的模型路径 ,目前支持了上表中的8种模型权重,我们可直接替换使用。
50+ > * ` --pretrained_model_name_or_path ` : 所使用的 ` Stable Diffusion ` 模型权重名称或者本地下载的模型路径 ,目前支持了上表中的8种模型权重,我们可直接替换使用。
6851> * ` --instance_data_dir ` : 实例(物体)图片文件夹地址。
69- > * ` --instance_prompt ` : 带有特定实例(物体)的提示词描述文本,例如『 a photo of sks dog』 ,其中dog代表实例(物体)。
52+ > * ` --instance_prompt ` : 带有特定实例(物体)的提示词描述文本,例如` a photo of sks dog ` ,其中dog代表实例(物体)。
7053> * ` --class_data_dir ` : 类别(class)图片文件夹地址,主要作为先验知识。
71- > * ` --class_prompt ` : 类别(class)提示词文本,该提示器要与实例(物体)是同一种类别,例如『 a photo of dog』 ,主要作为先验知识。
54+ > * ` --class_prompt ` : 类别(class)提示词文本,该提示器要与实例(物体)是同一种类别,例如` a photo of dog ` ,主要作为先验知识。
7255> * ` --num_class_images ` : 事先需要从` class_prompt ` 中生成多少张图片,主要作为先验知识。
7356> * ` --prior_loss_weight ` : 先验` loss ` 占比权重。
7457> * ` --sample_batch_size ` : 生成` class_prompt ` 文本对应的图片所用的批次(batch size),注意,当GPU显卡显存较小的时候需要将这个默认值改成1。
7558> * ` --with_prior_preservation ` : 是否将生成的同类图片(先验知识)一同加入训练,当为` True ` 的时候,` class_prompt ` 、` class_data_dir ` 、` num_class_images ` 、` sample_batch_size ` 和` prior_loss_weight ` 才生效。
7659> * ` --num_train_epochs ` : 训练的轮数,默认值为` 1 ` 。
7760> * ` --max_train_steps ` : 最大的训练步数,当我们设置这个值后,它会重新计算所需的` num_train_epochs ` 轮数。
78- > * ` --save_steps ` : 每间隔多少步` (global step步数) ` ,保存学习到的 ` pipe ` 。
79- > * ` --gradient_accumulation_steps ` : 梯度累积的步数,用户可以指定梯度累积的步数,在梯度累积的step中 。减少多卡之间梯度的通信,减少更新的次数,扩大训练的batch_size 。
61+ > * ` --checkpointing_steps ` : 每间隔多少步` (global step步数) ` ,保存模型权重 。
62+ > * ` --gradient_accumulation_steps ` : 梯度累积的步数,用户可以指定梯度累积的步数,在梯度累积的 step 中 。减少多卡之间梯度的通信,减少更新的次数,扩大训练的 batch_size 。
8063> * ` --train_text_encoder ` : 是否一同训练文本编码器的部分,默认为` False ` 。
8164
8265> 可以修改的参数
83- > * ` --height ` : 输入给模型的图片` 高度 ` ,由于用户输入的并不是固定大小的图片,因此代码中会将原始大小的图片压缩成指定` 高度 ` 的图片,默认值为` 512 ` 。
84- > * ` --width ` : 输入给模型的图片` 宽度 ` ,由于用户输入的并不是固定大小的图片,因此代码中会将原始大小的图片压缩成指定` 宽度 ` 的图片,默认值为` 512 ` 。
66+ > * ` --height ` : 输入给模型的图片` 高度 ` ,由于用户输入的并不是固定大小的图片,因此代码中会将原始大小的图片压缩成指定` 高度 ` 的图片,默认值为` None ` 。
67+ > * ` --width ` : 输入给模型的图片` 宽度 ` ,由于用户输入的并不是固定大小的图片,因此代码中会将原始大小的图片压缩成指定` 宽度 ` 的图片,默认值为` None ` 。
68+ > * ` --resolution ` : 输入给模型图片的` 分辨率 ` ,当` 高度 ` 或` 宽度 ` 为` None ` 时,我们将会使用` resolution ` ,默认值为` 512 ` 。
8569> * ` --learning_rate ` : 学习率。
8670> * ` --scale_lr ` : 是否根据GPU数量,梯度累积步数,以及批量数对学习率进行缩放。缩放公式:` learning_rate * gradient_accumulation_steps * train_batch_size * num_processes ` 。
8771> * ` --lr_scheduler ` : 要使用的学习率调度策略。默认为 ` constant ` 。
88- > * ` --lr_warmup_steps ` : 用于从 0 到 ` learning_rate ` 的线性 warmup 的步数。
72+ > * ` --lr_warmup_steps ` : 用于从 0 到 ` learning_rate ` 的线性 ` warmup ` 的步数。
8973> * ` --train_batch_size ` : 训练时每张显卡所使用的` batch_size批量 ` ,当我们的显存较小的时候,需要将这个值设置的小一点。
9074> * ` --center_crop ` : 在调整图片宽和高之前是否将裁剪图像居中,默认值为` False ` 。
75+ > * ` --random_flip ` : 是否对图片进行随机水平反转,默认值为` False ` 。
9176> * ` --gradient_checkpointing ` : 是否开启` gradient_checkpointing ` 功能,在一定程度上能够更显显存,但是会减慢训练速度。
9277> * ` --output_dir ` : 模型训练完所保存的路径,默认设置为` dreambooth-model ` 文件夹,建议用户每训练一个模型可以修改一下输出路径,防止先前已有的模型被覆盖了。
9378
9479> 基本无需修改的参数
9580> * ` --seed ` : 随机种子,为了可以复现训练结果,Tips:当前paddle设置该随机种子后仍无法完美复现。
96- > * ` --adam_beta1 ` : AdamW 优化器时的 beta1 超参数。默认为 ` 0.9 ` 。
97- > * ` --adam_beta2 ` : AdamW 优化器时的 beta2 超参数。默认为 ` 0.999 ` 。
98- > * ` --adam_weight_decay ` : AdamW 优化器时的 weight_decay 超参数。 默认为` 0.02 ` 。
99- > * ` --adam_weight_decay ` : AdamW 优化器时的 epsilon 超参数。默认为 1e-8。
100- > * ` --max_grad_norm ` : 最大梯度范数(用于梯度裁剪)。默认为 ` None ` 表示不使用。
81+ > * ` --adam_beta1 ` : ` AdamW ` 优化器时的 ` beta1 ` 超参数。默认为 ` 0.9 ` 。
82+ > * ` --adam_beta2 ` : ` AdamW ` 优化器时的 ` beta2 ` 超参数。默认为 ` 0.999 ` 。
83+ > * ` --adam_weight_decay ` : ` AdamW ` 优化器时的 ` weight_decay ` 超参数。 默认为` 0.02 ` 。
84+ > * ` --adam_weight_decay ` : ` AdamW ` 优化器时的 ` epsilon ` 超参数。默认为 ` 1e-8 ` 。
85+ > * ` --max_grad_norm ` : 最大梯度范数(用于梯度裁剪)。默认为 ` -1 ` 表示不使用。
10186> * ` --logging_dir ` : Tensorboard 或 VisualDL 记录日志的地址,注意:该地址会与输出目录进行拼接,即,最终的日志地址为` <output_dir>/<logging_dir> ` 。
102- > * ` --writer_type ` : 用于记录日志的工具,可选` ["tensorboard", "visualdl"] ` ,默认为` visualdl ` ,如果选用` tensorboard ` ,请使用命令安装` pip install tensorboardX ` 。
87+ > * ` --report_to ` : 用于记录日志的工具,可选` ["tensorboard", "visualdl"] ` ,默认为` visualdl ` ,如果选用` tensorboard ` ,请使用命令安装` pip install tensorboardX ` 。
88+ > * ` --push_to_hub ` : 是否将模型上传到 ` huggingface hub ` ,默认值为 ` False ` 。
89+ > * ` --hub_token ` : 上传到 ` huggingface hub ` 所需要使用的 ` token ` ,如果我们已经登录了,那么我们就无需填写。
90+ > * ` --hub_model_id ` : 上传到 ` huggingface hub ` 的模型库名称, 如果为 ` None ` 的话表示我们将使用 ` output_dir ` 的名称作为模型库名称。
10391
10492
10593#### 1.2.3 单机多卡训练
@@ -115,19 +103,14 @@ python -u -m paddle.distributed.launch --gpus "0,1,2,3" train_dreambooth.py \
115103 --instance_data_dir=$INSTANCE_DIR \
116104 --output_dir=$OUTPUT_DIR \
117105 --instance_prompt=" a photo of sks dog" \
118- --height=512 \
119- --width=512 \
106+ --resolution=512 \
120107 --train_batch_size=1 \
121108 --gradient_accumulation_steps=1 \
122109 --learning_rate=5e-6 \
123110 --lr_scheduler=" constant" \
124111 --lr_warmup_steps=0 \
125112 --max_train_steps=400
126113```
127- 或
128- ``` bash
129- bash run_multi.sh
130- ```
131114
132115#### 1.2.4 预测生成图片
133116
@@ -142,7 +125,7 @@ bash run_multi.sh
142125 ├── model_state.pdparams
143126 ├── config.json
144127 ├── text_encoder # text_encoder权重文件夹
145- ├── model_config .json
128+ ├── config .json
146129 ├── model_state.pdparams
147130 ├── unet # unet权重文件夹
148131 ├── model_state.pdparams
@@ -194,8 +177,7 @@ python -u train_dreambooth.py \
194177 --with_prior_preservation --prior_loss_weight=1.0 \
195178 --instance_prompt=" a photo of sks dog" \
196179 --class_prompt=" a photo of dog" \
197- --height=512 \
198- --width=512 \
180+ --resolution=512 \
199181 --train_batch_size=1 \
200182 --gradient_accumulation_steps=1 \
201183 --learning_rate=5e-6 \
@@ -222,7 +204,79 @@ image.save("sks-dog-with-class.png")
222204</p >
223205
224206
207+ # 使用 LoRA 和 DreamBooth 技术进行模型训练
208+
209+ [ LoRA: Low-Rank Adaptation of Large Language Models] ( https://arxiv.org/abs/2106.09685 ) 是微软研究员引入的一项新技术,主要用于处理大模型微调的问题。目前超过数十亿以上参数的具有强能力的大模型 (例如 GPT-3) 通常在为了适应其下游任务的微调中会呈现出巨大开销。LoRA 建议冻结预训练模型的权重并在每个 Transformer 块中注入可训练层 (秩-分解矩阵)。因为不需要为大多数模型权重计算梯度,所以大大减少了需要训练参数的数量并且降低了 GPU 的内存要求。研究人员发现,通过聚焦大模型的 Transformer 注意力块,使用 LoRA 进行的微调质量与全模型微调相当,同时速度更快且需要更少的计算。
210+
211+ 简而言之,LoRA允许通过向现有权重添加一对秩分解矩阵,并只训练这些新添加的权重来适应预训练的模型。这有几个优点:
212+
213+ - 保持预训练的权重不变,这样模型就不容易出现灾难性遗忘 [ catastrophic forgetting] ( https://www.pnas.org/doi/10.1073/pnas.1611835114 ) ;
214+ - 秩分解矩阵的参数比原始模型少得多,这意味着训练的 LoRA 权重很容易移植;
215+ - LoRA 注意力层允许通过一个 ` scale ` 参数来控制模型适应新训练图像的程度。
216+
217+ [ cloneofsimo] ( https://github.com/cloneofsimo ) 是第一个在 [ LoRA GitHub] ( https://github.com/cloneofsimo/lora ) 仓库中尝试使用 LoRA 训练 Stable Diffusion 的人。
218+
219+ ## 训练
220+
221+ ** ___ Note: 如果我们使用 [ stable-diffusion-2] ( https://huggingface.co/stabilityai/stable-diffusion-2 ) 进行训练,那么我们需要将 ` resolution ` 改成 768 .___ **
222+
223+ ``` bash
224+ export MODEL_NAME=" runwayml/stable-diffusion-v1-5"
225+ export INSTANCE_DIR=" path-to-instance-images"
226+ export OUTPUT_DIR=" path-to-save-model"
227+
228+ python train_dreambooth_lora.py \
229+ --pretrained_model_name_or_path=$MODEL_NAME \
230+ --instance_data_dir=$INSTANCE_DIR \
231+ --output_dir=$OUTPUT_DIR \
232+ --instance_prompt=" a photo of sks dog" \
233+ --resolution=512 \
234+ --train_batch_size=1 \
235+ --gradient_accumulation_steps=1 \
236+ --checkpointing_steps=100 \
237+ --learning_rate=1e-4 \
238+ --report_to=" visualdl" \
239+ --lr_scheduler=" constant" \
240+ --lr_warmup_steps=0 \
241+ --max_train_steps=500 \
242+ --validation_prompt=" A photo of sks dog in a bucket" \
243+ --validation_epochs=50 \
244+ --seed=0
245+ ```
246+
247+ ** ___ Note: 当我使用 LoRA 训练模型的时候,我们需要使用更大的学习率,因此我们这里使用 * 1e-4* 而不是 * 2e-6* .___ **
248+
249+ 最终经过微调后的 LoRA 权重,我们已经上传到了 [ junnyu/lora_dreambooth_dog_example] ( https://huggingface.co/junnyu/lora_dreambooth_dog_example ) . ** ___ Note: [ 最终的权重] ( https://huggingface.co/junnyu/lora_dreambooth_dog_example/blob/main/paddle_lora_weights.pdparams ) 只有 3 MB 的大小.___ **
250+
251+ ## 推理
252+
253+ 经过训练, LoRA 权重可以直接加载到原始的 pipeline 中。
254+
255+ 首先我们需要加载原始的 pipeline:
256+
257+ ``` python
258+ from ppdiffusers import DiffusionPipeline, DPMSolverMultistepScheduler
259+ import paddle
260+
261+ pipe = DiffusionPipeline.from_pretrained(" runwayml/stable-diffusion-v1-5" , paddle_dtype = paddle.float16)
262+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
263+ ```
264+
265+ 接下来, 我们需要使用 ` load_attn_procs ` 方法将 ` adapter layers ` 添加到 UNet 模型中。
266+ ``` python
267+ pipe.unet.load_attn_procs(" junnyu/lora_dreambooth_dog_example" , from_hf_hub = True )
268+ ```
269+
270+ 最终, 我们可以使用模型进行推理预测.
271+
272+ ``` python
273+ image = pipe(" A picture of a sks dog in a bucket" , num_inference_steps = 25 ).images[0 ]
274+ image.save(" demo.png" )
275+ ```
276+ <p align =" center " >
277+ <img src="https://user-images.githubusercontent.com/50394665/218384517-b89667f4-b5c9-4ecf-afcb-8b667c5532bb.jpg">
278+ </p >
225279
226- ## 2 参考资料
280+ # 参考资料
227281- https://github.com/huggingface/diffusers/tree/main/examples/dreambooth
228282- https://github.com/CompVis/stable-diffusion
0 commit comments