Stable Diffusion 微调实战:用 LoRA 训练自定义图像风格

1. 引言

Stable Diffusion 是当前最流行的开源文生图模型。通过 LoRA 微调,我们只需 20-50 张图片就能教会模型新的风格、角色或概念,且只需 8GB 显存。

本文将教你:

  • 准备训练数据集
  • 使用 kohya-ss 训练 LoRA
  • 在 ComfyUI/WebUI 中使用 LoRA
  • 调参技巧与常见问题

2. 环境搭建

bash 复制代码
# 克隆 kohya-ss 训练框架
git clone https://github.com/kohya-ss/sd-scripts.git
cd sd-scripts
pip install -r requirements.txt

# 下载基模型
# Stable Diffusion XL 1.0 (推荐)
# 从 HuggingFace 下载 safetensors 文件到 models/ 目录

3. 数据准备

3.1 数据集要求

条件 推荐值 说明
图片数量 20-50 张 风格学习 20 张足够
分辨率 1024×1024 SDXL 标准分辨率
格式 PNG/JPG 无损 PNG 更佳
多样性 不同构图/角度 避免过度拟合特定姿态

3.2 目录结构

复制代码
dataset/
├── 10_my_style/          # "10" 是重复次数, "my_style" 是触发词
│   ├── image001.png
│   ├── image001.txt      # 标签文件
│   ├── image002.png
│   ├── image002.txt
│   └── ...

3.3 自动打标签

bash 复制代码
# 使用 BLIP2 自动生成标签
accelerate launch scripts/finetune_tagger.py \
    --dataset_dir=dataset \
    --model_name=blip2 \
    --batch_size=8

# 或使用 WD14 Tagger(更精确)
python scripts/wd14_tagger.py \
    --dataset_dir=dataset \
    --thresh=0.35

标签编辑要点:

  • 将触发词(如 my_style)添加到每个标签文件开头

  • 删除标签中对风格的描述(避免冲突)

  • 保留内容描述(人物、物体、场景)

    修改前

    1girl, long hair, watercolor painting, soft colors

    修改后(移除风格描述,添加触发词)

    my_style, 1girl, long hair

4. 训练配置

4.1 TOML 配置文件

toml 复制代码
# train_lora.toml

[general]
shuffle_caption = true
caption_extension = ".txt"
keep_tokens = 1          # 保留前1个token(触发词)

[[datasets]]
resolution = 1024
batch_size = 1

  [[datasets.subsets]]
  image_dir = "dataset/10_my_style"
  num_repeats = 10

4.2 训练命令

bash 复制代码
accelerate launch sdxl_train_network.py \
    --pretrained_model_name_or_path="models/sd_xl_base_1.0.safetensors" \
    --train_data_dir="dataset" \
    --output_dir="output" \
    --output_name="my_style_lora" \
    --network_module=networks.lora \
    --network_dim=32 \
    --network_alpha=16 \
    --resolution="1024,1024" \
    --train_batch_size=1 \
    --max_train_epochs=10 \
    --learning_rate=1e-4 \
    --unet_lr=1e-4 \
    --text_encoder_lr=5e-5 \
    --lr_scheduler="cosine_with_restarts" \
    --lr_warmup_steps=100 \
    --optimizer_type="AdamW8bit" \
    --mixed_precision="bf16" \
    --save_every_n_epochs=2 \
    --seed=42 \
    --max_token_length=225 \
    --clip_skip=2 \
    --gradient_checkpointing \
    --xformers

4.3 关键参数解析

参数 推荐值 说明
network_dim 32-128 LoRA 秩,越大表达力越强
network_alpha dim/2 缩放因子,影响训练稳定性
learning_rate 1e-4 ~ 5e-5 UNet 学习率
text_encoder_lr 5e-5 文本编码器学习率,通常为 UNet 的 1/2
max_train_epochs 5-15 风格学习 5-10 轮足够
network_dim 32 风格 LoRA 推荐 32
optimizer_type AdamW8bit 节省显存

5. 训练监控

python 复制代码
# 查看训练日志
import json
import matplotlib.pyplot as plt

losses = []
with open("output/log.json") as f:
    for line in f:
        data = json.loads(line)
        if "loss" in data:
            losses.append(data["loss"])

plt.plot(losses)
plt.xlabel("Step")
plt.ylabel("Loss")
plt.title("LoRA Training Loss")
plt.savefig("training_loss.png")

判断训练状态:

  • loss 持续下降 → 正常训练
  • loss 震荡不下降 → 学习率过大,降低 50%
  • loss 快速降到 0.01 以下 → 过拟合,减少 epoch
  • 生成图片风格不明显 → 增加 network_dim 或 epoch

6. 使用 LoRA

6.1 ComfyUI 中使用

复制代码
1. 将 my_style_lora.safetensors 放入 ComfyUI/models/loras/
2. 添加 LoRA Loader 节点
3. 连接到 UNet 和 CLIP
4. 设置 strength_model = 0.7
5. Prompt: "my_style, a mountain landscape"

6.2 Python 推理

python 复制代码
from diffusers import StableDiffusionXLPipeline
import torch

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16,
).to("cuda")

# 加载 LoRA
pipe.load_lora_weights("output/", weight_name="my_style_lora.safetensors")

# 生成
image = pipe(
    "my_style, a beautiful sunset over the ocean",
    num_inference_steps=30,
    guidance_scale=7.5,
    cross_attention_kwargs={"scale": 0.7},  # LoRA 强度
).images[0]

image.save("output.png")

6.3 多 LoRA 混合

python 复制代码
# 加载多个 LoRA
pipe.load_lora_weights("lora_a/", weight_name="style_a.safetensors",
                       adapter_name="style_a")
pipe.load_lora_weights("lora_b/", weight_name="style_b.safetensors",
                       adapter_name="style_b")

# 设置权重
pipe.set_adapters(["style_a", "style_b"], adapter_weights=[0.6, 0.4])

7. 调参技巧

7.1 不同任务的参数建议

任务 network_dim epochs learning_rate LoRA 强度
风格迁移 32 5-10 1e-4 0.6-0.8
角色训练 64 10-15 8e-5 0.7-1.0
概念学习 128 15-20 5e-5 0.5-0.8

7.2 避免过拟合

  1. 数据增强:水平翻转、轻微旋转
  2. 减少重复次数:从 10 降到 5
  3. Early Stopping:每隔 2 epoch 测试生成效果
  4. 降低 network_dim:从 128 降到 32

8. 总结

Stable Diffusion LoRA 微调的核心流程:

  1. 数据:20-50 张高质量图片 + 自动打标签 + 手动修正
  2. 训练:kohya-ss 框架,AdamW8bit + cosine 学习率
  3. 使用:通过 ComfyUI 或 diffusers 库加载 LoRA
  4. 调参:先用默认参数跑 baseline,再根据效果微调

LoRA 文件通常只有几十 MB,可以方便地分享和组合使用。