迁移学习实战:用Stable Diffusion快速打造专属AI绘画模型

引言:当你的创意遇上别人的模型,会发生什么?

先说个真事。
去年双十一前夜,我蹲在公司茶水间,用一台 RTX 3060 给电商部“生”了 800 张模特图。老板原话:“要东方脸、微喇牛仔裤、站在粉色霓虹前,最好带点赛博味,但别太吓人。” 我咖啡没喝完,图已经打包发过去。凌晨三点,美工妹子发来微信:
“哥,你这些图……是请外星团队拍的?”
我回她一个狗头表情,顺手把训练脚本扔进仓库,commit 信息只有一句:
“外星人收费太贵,我自己训了一个。”

这就是迁移学习的魅力——把别人的千亿级模型借过来,花十几分钟喂几张私图,就能让它替你打工。
今天这篇,把我踩过的坑、熬过的夜、以及被老板加过的鸡腿,全部打包写成一份“人类能看懂”的实战笔记。不拽公式,不堆黑话,只聊怎么把 Stable Diffusion 变成你的专属画笔。读完你能做到:

  • 用 10 张自家产品图,让 AI 生成 1000 张不同角度、不同光影的电商主图;
  • 给游戏角色画 360° 设定稿,且画风统一到美术总监挑不出刺;
  • 训练一个“听到你公司 Logo 名字就能吐出品牌 IP”的轻量模型,显存不到 6G 也能跑。

如果你只有一台游戏本,没卡、没钱、没数据,也别走,文末有“乞丐版”方案,连 CPU 都能跑——就是慢一点,泡碗面的功夫出图。

废话少说,先上第一道菜。


Stable Diffusion 到底是什么?—— 不只是一把“电动画笔”

很多人以为 SD 就是个“高级美图秀秀”,输入一句话,出来一张图。
错。它其实是一套开源宇宙

  • 模型本体(一个 890M 的 UNet + 文字编码器)
  • VAE(负责把像素空间和潜空间来回搬运)
  • CLIP(把人类语言翻译成向量,告诉 UNet 该画什么)

这三件套像乐高一样,可以拆、可以换、可以插外挂。
迁移学习玩的就是“换头手术”:保留原模型 99.999% 的权重,只动最表层几根神经,让它学会“你的脸”“你的包”“你的二次元老婆”。

举个不恰当的比喻:
Stable Diffusion 是新东方毕业的大厨,煎炒烹炸样样会;迁移学习就是告诉他:“兄弟,别做川菜了,我教你一道祖传秘制鸡翅,十分钟后上菜,记得别放香菜。” 大厨点点头,把菜谱背下来,锅铲翻飞,味道还对。
你不需要重新盖厨房,只需要递给他一张便签。


迁移学习在图像生成中的魔法:为什么不用从头训练?

先放一张血泪账单:

方案 数据量 训练时长 电费(8 卡 A100) 效果
从头训练 SD 1.5 6000 万张图 15 万 GPU 时 一辆 Model Y 通用且玄学
Dreambooth 微调 20 张图 8 分钟(单卡 3060) 一杯奶茶 专精且听话

看到差距了吗?迁移学习 = 站在 25 亿参数的巨人肩膀上撒野。
原理一句话:
“冻结主干,只调最后几层;把新概念塞进旧字典,让模型学会‘新单词’。”

技术细节拆成三步,保证你随时能复述给老板听:

  1. 潜空间劫持
    图片先被 VAE 压成 64×64 的“豆腐块”,UNet 在豆腐块上雕花。我们只需在豆腐块里圈出“你的主题”,让模型记住这块豆腐的味道。
  2. 文本编码器开小灶
    把“a photo of sks dog”里的 sks 当成新 token,嵌入矩阵里加一行向量,告诉 CLIP:“看到 sks 就给我吐狗”。
  3. 低秩适配(LoRA)
    不改原权重,而是插两块小矩阵 A×B,让 W = W0 + BA。训练只调 AB,参数量压缩 1/1000,显存直接砍半。

微调三大流派:Dreambooth、Textual Inversion、LoRA 怎么选?

Dreambooth——“土豪砸钱流”

原理:复制一份 UNet + CLIP,把新概念 <new1> 塞进去,学习率 1e-6 慢慢炖。
优点:效果最稳,姿势最全,能学会罕见角度。
缺点:显存占用 16G 起步,训练一次 300 张图以内容易过拟合,需要正侧样本平衡。
适用场景:电商主图、写实人像,对细节要求苛刻。

代码片段(基于 diffusers 0.21)

from diffusers import StableDiffusionPipeline, DreamBoothDataset
from accelerate import Accelerator

accelerator = Accelerator(mixed_precision="fp16")
pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16)

# 数据集:每张图自带一句“a photo of sks toy”
train_dataset = DreamBoothDataset(
    instance_data_root="./my_toy",
    instance_prompt="a photo of sks toy",
    tokenizer=pipe.tokenizer,
    size=512
)

# 优化器只调 UNet 参数
optimizer = torch.optim.AdamW(pipe.unet.parameters(), lr=1e-6)

for epoch in range(800):
    for batch in train_loader:
        with accelerator.accumulate(pipe.unet):
            loss = compute_dreambooth_loss(batch)
            accelerator.backward(loss)
            optimizer.step()
            optimizer.zero_grad()

Textual Inversion——“抠门向量流”

原理:只动文本编码器,给新词学一个 768 维向量,冻结 UNet。
优点:模型体积 +0 KB,分享时只发一个 20KB 的 *.bin 文件即可。
缺点:学不会复杂细节,比如“带珍珠耳环的猫”。
适用场景:风格词、抽象概念、小团队快速 demo。

关键代码(官方 notebook 精简版)

# 新建占位符 token
placeholder_token = "<my-style>"
num_added = tokenizer.add_tokens(placeholder_token)
token_embeds = text_encoder.get_input_embeddings().weight.data
placeholder_id = tokenizer.convert_tokens_to_ids(placeholder_token)

# 随机初始化新向量
token_embeds[placeholder_id] = torch.randn_like(token_embeds[0])

# 训练 loop 只调这一行向量
optimizer = torch.optim.AdamW([text_encoder.get_input_embeddings().weight[placeholder_id]], lr=5e-3)

LoRA——“平民战神流”

原理:在 UNet 的注意力层插低秩矩阵,训练完导出 *.safetensors 只有 40~140MB。
优点:6G 显存能跑,效果逼近 Dreambooth,社区生态爆炸,Civitai 上 70% 模型都是 LoRA。
缺点:需要手动调 rank、alpha,rank 太高容易过拟合,太低会糊。
适用场景:个人开发者、游戏立绘、二次元盲盒。

训练脚本( kohya-ss 精简 wrapper)

accelerate launch --num_processes=1  train_network.py \
  --pretrained_model_name_or_path="runwayml/stable-diffusion-v1-5" \
  --dataset_config="dataset.toml" \
  --output_dir="./output" \
  --output_name="mylora" \
  --network_module=networks.lora \
  --network_dim=32 \
  --network_alpha=16 \
  --resolution=512,512 \
  --train_batch_size=1 \
  --max_train_epochs=10 \
  --optimizer_type="AdamW8bit" \
  --learning_rate=1e-4 \
  --lr_scheduler="cosine_with_restarts" \
  --lr_warmup_steps=100 \
  --mixed_precision="fp16" \
  --save_precision="fp16" \
  --gradient_checkpointing \
  --cache_latents \
  --xformers

真实项目拆解一:电商产品图“模特换头”

背景:某女装店上新 30 款卫衣,预算 0,模特档期无。
方案:

  1. 让运营妹子穿一件同款卫衣,站在白墙前,手机拍 15 张正面、侧面、背面。
  2. 用 Segment Anything 抠图,只留衣服,mask 保存为 png。
  3. Dreambooth 训练,prompt 统一写 “woman wearing sks hoodie, full body, studio light”。
  4. 推理时用 ControlNet OpenPose 固定姿势,再把“woman”换成“1girl, (Korean idol:1.2), denim shorts”。

效果:

  • 生成 800 张图,挑 200 张上架,点击率比往年提升 18%。
  • 老板问模特哪请的,我答:“韩国分公司,时差 24 小时在线。”

关键代码:ControlNet + Dreambooth 联合推理

from diffusers import StableDiffusionControlNetPipeline, ControlNetModel
from diffusers.utils import load_image
import cv2

controlnet = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-openpose", torch_dtype=torch.float16)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "./dreambooth-hoodie-output",
    controlnet=controlnet,
    torch_dtype=torch.float16
).to("cuda")

pose_image = load_image("./pose_reference.jpg")
prompt = "1girl, wearing sks hoodie, (Korean idol:1.2), denim shorts, studio light, best quality"
image = pipe(prompt, pose_image, num_inference_steps=30, guidance_scale=7.5).images[0]
image.save("./result.jpg")

真实项目拆解二:游戏角色“盲盒立绘”

需求:卡牌游戏要 60 张“兽耳机械娘”,画风统一,工期一周。
方案:

  • 先收集 200 张官方立绘,统一 512×768,用 tag 工具(WD14 Tagger)批量打标签。
  • LoRA 训练,rank=64,alpha=32,学习率 1e-4,带 0.1 的 dropout 防过拟合。
  • 关键词模板:
    “masterpiece, best quality, 1mecha girl, animal ears, lora:myLora:1, standing, dynamic angle, glowing eyes, weapon, sci-fi background”
  • 用 denoising strength 0.55 做 img2img,随机种子批量跑 2000 张,美术只负责挑图。

显存占用:6G 的 2060 笔记本,batch=1,训练 3 小时。
交付当天,策划小哥惊呼:“你们外包了哪个日本工作室?”
我笑而不语,把 LoRA 文件右键属性给他看:大小 124MB,创建时间昨晚 2 点。


排查“崩图”急救手册:从过拟合到语义错乱

  1. 脸崩
    现象:眼睛多一只,嘴巴错位。
    药方:

    • 把“face_focus”比例降到 0.8,加 Blur 数据增强。
    • 推理时加负面提示 “malformed face, extra eyes, bad anatomy”。
  2. 过拟合
    现象:无论 prompt 写什么,出来的都是训练图复刻。
    药方:

    • 把正则化图(class images)数量提到 3 倍,prompt 用 “a woman” 这种通用词。
    • 降低训练步数,early stopping 看 loss 曲线拐点。
  3. 语义错乱
    现象:输入 “红色连衣裙” 出来 “红色背景”。
    药方:

    • 检查 token 是否冲突,把 sks 换成更罕见的 xyz70
    • 训练集里务必包含 “连衣裙” 单独出现的样本,让模型学会解耦。

高效训练小妙招:数据、提示词、学习率的三叉戟

数据准备

  • 数量:20~50 张足够,角度、光照、背景最好三足鼎立。
  • 分辨率:统一短边 512,长边自适应,防止 VAE 抽风。
  • 清洗:用 opencv-magic-wand 自动去白边,省 80% 手工时间。

提示词模板

把 prompt 拆成“可变”+“不变”两段:
“不变”放画风、质量词;“可变”放主题、动作、背景。
示例:

[不变] masterpiece, best quality, 1girl, <lora:myLora:1>, 
[可变] (sks hoodie:1.2), (denim shorts:1.1), standing, (pink neon:1.3), cyberpunk city

训练时只改可变段,保证模型学会“换衣不换脸”。

学习率

  • LoRA:1e-4 起步,loss plateau 后手动 ÷2。
  • Dreambooth:1e-6 起步,别用 cosine,容易暴冲。
  • Textual Inversion:5e-3 起步,向量小,步子可以大一点。

别让 GPU 烧成炭:低资源环境生存指南

  • 用 8bit AdamW,显存立减 30%,速度几乎不掉。
  • gradient_checkpointing,训练慢 20%,显存再省 40%。
  • cache_latents 提前把 VAE 结果存硬盘,训练时省 1.2G。
  • xformers 必开,attention 内存复杂度从 O(n²) 砍到 O(n)。
  • 如果只有 CPU?上 Apple Silicon 的 mlx-framework,M2 Pro 20 分钟也能训完 1000 步,就是风扇有点吵。

提示工程 + 微调协同:让模型听你话

很多人训完模型发现:“怎么还是不听指挥?”
答案:prompt 和权重没配合好。
技巧:

  1. 训练时把触发词放最前,推理时也放最前,位置权重最高。
  2. 用括号加权重 (sks:1.3),比事后调 guidance_scale 更精准。
  3. 画风 LoRA 和主题 LoRA 混用,中间加 BREAK 关键词,防止互相污染。
    示例:
masterpiece, <lora:myStyle:0.8>, BREAK, <lora:myCharacter:1>, 1girl, sks, standing, ...

训练后处理:大佬们偷偷干的三件事

  1. 指数移动平均(EMA)
    训完再跑 500 步 EMA,出图稳定性提升肉眼可见。

  2. FP16 烘焙
    把最终权重 bake 成 FP16,体积减半,推理提速 15%,肉眼无差。

  3. 触发词压缩
    lora-tools 把多个 LoRA 合并,触发词写成 abcStyleAndChar,一键调用,懒人福音。


写在最后的碎碎念

迁移学习不是黑魔法,它只是把“巨人的肩膀”免费借给你。
你不需要 100 张 A100,也不需要 6000 万张图,几张私照 + 一杯咖啡的时间,就能让 AI 学会你的独家记忆。
下次老板再拍桌子:“三天给我 1000 张图!”
你可以淡定地把笔记本翻开,敲下:

python train.py --instance_prompt "a photo of sks boss_idea"

然后合上屏幕,去茶水间再续一杯——
让 GPU 替你熬夜,你负责梦里数鸡腿。

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐