本文作者:劉遠,騰訊雲泛互聯網首席解決方案架構師。
概述
Stable Diffusion 微調
Stable Diffusion 微調的目標,是將新概念注入預訓練模型,利用新注入的概念以及模型的先驗知識,基於文本引導條件生成自定義圖片。目前主流訓練 Stable Diffusion 模型的方法有 Full FineTune、Dreambooth、Text Inversion 和 LoRA,不同方法的實現邏輯和使用場景不同,選型簡單對比如下:
訓練方法 | 方法 | 侷限性 |
---|---|---|
Text Inversion |
使用提供的一組圖片訓練一個新單詞的Embedding ,並將其與詞彙表中的已有單詞關聯起來,這個新單詞即為這組圖片概念的指代。 |
訓練過程只對應 Embedding,擴散模型沒有新知識輸入,所以也無法產生新的內容。 |
Full FineTune |
最樸素的方式,使用圖片+ 標註的數據集,進行迭代訓練,數據集標註可以選擇BLIP來生成。訓練直接對原模型的所有權重進行調整。 |
容易過擬合,導致生成圖片的多樣性不夠,結果難以控制。模型體積大,不便於傳播。 |
Dreambooth |
提供代表某個新概念(instance) 對應的一組圖像,並使用罕見字符(identifier) 進行概念Mapping,訓練過程充分考慮原有相關主題(class)生成,避免過擬合。訓練直接對原模型的所有權重進行調整。 |
訓練過程只針對新概念 (instance),多樣性差。如果需要多概念生成,需要多次訓練。模型體積大,不便於傳播。 |
LoRA(w Dreambooth) |
凍結預訓練模型參數,在每個Transformer塊插入可訓練層,不需要完整調整 UNet 模型的全部參數。訓練結果只保留新增的網絡層,模型體積小。 |
訓練效果不如Dreambooth |
需要注意的是,LoRA 是一種加速訓練的方法,Stable Diffusion 從大語言模型微調中借鑑而來,可以搭配 Full FineTune 或 Dreambooth 使用。針對上述幾種訓練方法,我們在 A10-24G 機型上進行測試,5-10張訓練圖片,所需資源和時長對比如下:
Dreambooth | Text Inversion | LoRA | |
---|---|---|---|
模型體積 |
~ 4 GB | 3-10 KB | 3-10 MB |
訓練顯存 | ~ 22GB | ~ 5GB | ~ 20GB |
訓練時長 | 15分鐘 | 1小時 | 10分鐘(w Dreambooth) 4小時(w Full FineTune) |
Dreambooth
accelerate launch train_dreambooth.py \
--pretrained_model_name_or_path=$MODEL_NAME \
--instance_data_dir=$INSTANCE_DIR \
--class_data_dir=$CLASS_DIR \
--output_dir=$OUTPUT_DIR \
--with_prior_preservation --prior_loss_weight=1.0 \
--mixed_precision=fp16 \
--instance_prompt="a photo of az baby" \
--class_prompt="a photo of baby" \
--resolution=512 \
--train_batch_size=1 \
--gradient_accumulation_steps=1 \
--learning_rate=5e-6 \
--lr_scheduler="constant" \
--lr_warmup_steps=0 \
--num_class_images=200 \
--max_train_steps=800
python ../scripts/convert_diffusers_to_original_stable_diffusion.py --model_path ./dreambooth_baby --checkpoint_path dreambooth_baby.safetensors --use_safetensors
LoRA(w Dreambooth)
accelerate launch train_dreambooth_lora.py \
--pretrained_model_name_or_path=$MODEL_NAME \
--instance_data_dir=$INSTANCE_DIR \
--class_data_dir=$CLASS_DIR \
--output_dir=$OUTPUT_DIR \
--instance_prompt="a photo of az baby" \
--class_prompt="a photo of baby" \
--resolution=512 \
--train_batch_size=1 \
--gradient_accumulation_steps=1 \
--checkpointing_steps=100 \
--learning_rate=1e-4 \
--lr_scheduler="constant" \
--lr_warmup_steps=0 \
--max_train_steps=1000 \
--validation_prompt="a photo of az baby" \
--validation_epochs=50 \
--seed="0"
python diffusers-lora-to-safetensors.py --file pytorch_lora_weights.bin
Stable Diffusion 性能優化
Dreambooth 優化
docker run -it --gpus=all --network=host -v /[diffusers_model_directory]:/[custom_container_directory] sd_taco:v3 bash
script_model = torch.jit.trace(model, test_data, strict=False)
script_model.save("trace_module.pt")
import torch
import taco
import os
taco_path = os.path.dirname(taco.__file__)
torch.ops.load_library(os.path.join(taco_path, "torch_tensorrt/lib/libtorchtrt.so"))
optimized_model = torch.jit.load("optimized_recursive_script_module.pt")
pic = torch.rand(1, 4, 64, 64).cuda() // picture
timesteps = torch.tensor([1]*1) // timesteps
context = torch.randn(1, 77, 768) // text embedding
with torch.no_grad():
output = optimized_model(pic, timesteps, context)
print(output)
LoRA 優化
python networks/merge_lora.py --sd_model ../v1-5-pruned-emaonly.safetensors --save_to ../lora-v1-5-pruned-emaonly.safetensors --models <LoRA文件目錄> --ratios <LoRA權重>