AIGC玩家速成:用LoRA微调Stable Diffusion,省显存又出片快

“兄弟,我显卡只有8G,跑个全量微调直接蓝屏,房东还以为我在屋里挖矿要涨我房租!”
别急,把全量微调扔进垃圾桶,今天咱们聊的LoRA,就是给穷鬼显卡续命的回血包。看完你也能用笔记本搓出专属画风,顺便把作品甩群里装逼。


LoRA到底是个啥玩意儿——说人话版

先别被“低秩适应”四个字吓到,我翻译成大白话:
SD(Stable Diffusion)原模型就像一辆顶配奔驰,你想给它换内饰,没必要把整车拆了重造,直接套个座椅套、贴个膜,一样能开出夜店风。LoRA就是那个“座椅套”——它只改极少的参数,剩下的全照抄原模型,所以显存占用从“32G起跳”直接砍到“4G能跑”,训练时间从“三天三夜”缩成“一顿烧烤”。

技术细节一句话:
把原来 1280×1280 的权重更新 ΔW 拆成两个小矩阵 A×B,尺寸 1280×4 和 4×1280,参数量瞬间变成原来的 1/320。训练完把 A×B 加回去,完事。
公式记不住?没关系,记住“拆小矩阵→省显存→快出片”就行。


为啥LoRA比Dreambooth和Textual Inversion香

方案 显存占用 收敛速度 效果 社交复现
Dreambooth 16G+ 过拟合常客 得传整个模型,3个G
Textual Inversion 2G 只能学个词向量,弱鸡 发个小文件,但效果拉
LoRA 4~6G 1小时起步 风格、物体、人脸都能打 发几十KB,别人一加载就能复现

一句话总结:
Dreambooth是“富二代”玩法,Textual Inversion是“乞丐版”,LoRA就是“打工人神器”——花小钱办大事,还能叠加buff:

# 同时加载两个LoRA,0.7日系 + 0.3赛博,味道刚刚好
pipe.load_lora_weights("japanese_v1.safetensors", adapter_name="jp")
pipe.load_lora_weights("cyberpunk_v2.safetensors", adapter_name="cp")
pipe.set_adapters(["jp", "cp"], adapter_weights=[0.7, 0.3])

别人还在git lfs拉3G模型,你20KB文件甩过去,群里瞬间安静。


LoRA在SD里怎么工作的——可视化版

想象UNet是一条火锅底料生产线:

  1. 原本要更新整条传送带(全量微调);
  2. LoRA只在关键工位(CrossAttention)旁边挂了两个小外挂:
    • 一个4×1280的“降维小漏斗”A
    • 一个1280×4的“升维小喇叭”B
      前向传播时,特征先被A压成4维,再被B吹回1280维,与原特征相加。
      参数量≈原传送带的0.3%,但味道(风格)一样能冲。

源码级伪代码,一看就懂:

class LoRALinear(nn.Module):
    def __init__(self, in_features=1280, out_features=1280, rank=4):
        super().__init__()
        self.rank = rank
        # 原权重冻住,不参与训练
        self.weight = nn.Parameter(torch.empty(out_features, in_features))
        self.weight.requires_grad = False
        # 两个小矩阵可训练
        self.lora_A = nn.Parameter(torch.empty(rank, in_features))
        self.lora_B = nn.Parameter(torch.empty(out_features, rank))
        nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
        nn.init.zeros_(self.lora_B)

    def forward(self, x):
        # 原路径 + LoRA路径
        return F.linear(x, self.weight) + F.linear(F.linear(x, self.lora_A.T), self.lora_B.T)

训练时只优化lora_Alora_B,显存当场腰斩。


动手前得搞清这些概念——踩坑笔记

  1. base model选谁?

    • 真人写真:SD1.5 + ChilloutMix,别用SDXL,显存翻倍。
    • 二次元:AnythingV5、CounterfeitV3,自带滤镜,训练量减半。
    • 产品图:SD1.5 + realisticVision,别带毛,会糊。
  2. 数据集多少张?

    • 人像:30~100张,正面、侧脸、仰头、低头、大笑、冷漠,全角度覆盖,少一张都可能把鼻子训歪。
    • 二次元:50张够了,但务必统一画风,别混进草稿图,否则AI以为“崩坏”是新风格。
    • 产品:白底+多角度+多光照,100张起步,不然阴影会穿帮。
  3. rank(r值)调多少?

    • 128:细节狂魔,但显存×2,适合商单。
    • 32~64:性价比 sweet spot,笔记本能跑。
    • 4~16:实验性玩具,想快速验证风格先拿它试水。
  4. 学习率别乱填
    1e-4是红线,新人直接cosine scheduler + warmup 5%,loss蹦迪立刻降到5e-5。


从零开始训一个LoRA模型全流程——实战脚本

1. 环境一键装好

# 创建虚拟环境,别污染系统python
conda create -n lora python=3.10 -y
conda activate lora
# 装pytorch 2.1,自带xformers省显存
pip install torch==2.1.0+cu118 torchvision xformers --index-url https://download.pytorch.org/whl/cu118
# Kohya_ss图形界面,点点鼠标就能跑
git clone https://github.com/bmaltais/kohya_ss.git
cd kohya_ss
pip install -r requirements.txt

2. 图片预处理——脚本一条龙

# auto_blip.py 自动打标+清洗
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image
import os, re

processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base").to("cuda")

def clean_tag(text):
    text = re.sub(r'[^\w\s]', '', text)  # 去符号
    text = re.sub(r'\b(person|people|image|photo)\b', '', text, flags=re.I)
    return ', '.join([w.strip() for w in text.split() if len(w) > 2])

for img_name in os.listdir("raw_img"):
    raw = Image.open(f"raw_img/{img_name}").convert("RGB")
    inputs = processor(raw, return_tensors="pt").to("cuda")
    out = model.generate(**inputs, max_length=40, num_beams=3)
    prompt = processor.decode(out[0], skip_special_tokens=True)
    with open(f"raw_img/{img_name.split('.')[0]}.txt", "w", encoding='utf-8') as f:
        f.write(clean_tag(prompt))

跑完你会得到一堆.txt,打开把“a person”这种废话删掉,保留特征词:1girl, silver hair, green eyes, hoodie。

3. 启动Kohua图形界面

python kohya_gui.py --listen 0.0.0.0 --server_port 7860

浏览器打开http://localhost:7860,按下图填:

  • pretrained_model:选chilloutmix_NiPrunedFp32Fix.safetensors
  • train_data_dir:刚才的raw_img
  • resolution:512(显存8G以下别硬刚768)
  • batch_size:1(6G显存)或2(8G显存)
  • max_train_epochs:10
  • save_every_n_epochs:2
  • rank:32
  • network_alpha:16(一半rank,防崩)
  • optimizer:AdamW8bit(省显存)
  • lr_scheduler:cosine_with_restarts
  • learning_rate:1e-4
  • unet_lr:1e-4
  • text_encoder_lr:5e-5(文本编码器别太高,会炸)
  • enable_bucket:打勾(自动多分辨率)
  • cache_latent:打勾(缓存潜变量,速度+30%)
  • xformers:打勾(省显存)
  • gradient_checkpointing:打勾(再省30%,速度换显存)

点“Start training”,去撸一把王者回来,30分钟~1小时就完事。


训练翻车现场与急救包——血泪史

症状 诊断 急救
loss曲线像心电图 学习率太高 降到5e-5,加warmup 5%
生成图全是噪点 分辨率没对齐 训练512却推理768,改一致
人脸崩成毕加索 过拟合 加reg图片:50张通用真人,权重0.1
显存直接红字OOM batch_size大 降batch,开gradient_checkpointing
训完没反应 触发词没写 prompt里加上abc(你填的activation word)

附送一键生成reg图片脚本:

# gen_reg.py 快速造50张正则化图
import torch, os
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16
).to("cuda")

os.makedirs("reg_img", exist_ok=True)
for i in range(50):
    img = pipe("portrait of a person", num_inference_steps=20, guidance_scale=7).images[0]
    img.save(f"reg_img/{i:03d}.jpg")

Kohya里“regularization folder”指到reg_img,权重0.1,过拟合立马老实。


怎么用LoRA做出商业级效果——甲方爸爸也点赞

1. 人像写真

  • 基础:ChilloutMix + 自训LoRA(rank=64)
  • 结构控制:ControlNet-depth保脸不崩
  • 肤色:外挂vae-ft-mse-840000,暗黄立刻奶油肌
  • prompt模板:
1girl, abc, (ultra detailed face:1.2), (photorealistic:1.2), soft light, highres, <lora:abc:0.8>
Negative: (worst quality:2), (oversaturated:1.3), (acne), (makeup)
Steps: 30, Sampler: DPM++ 2M Karras, CFG: 7, Size: 512x768

2. 二次元立绘

  • base:AnythingV5
  • 数据集:50张干净立绘,tag用DeepDanbooru打
  • 触发词:mystyle
  • 进阶:加LyCORIS变体,把UNet的up_blocks.1单独拎出来微调,线条更干净。

3. 电商产品图

  • 背景纯白,打灯左45°、右45°、顶光各拍一张,共30款×3张=90张
  • 训练resolution:512×512,把产品居中裁剪
  • prompt:
photo of abc, white background, softbox lighting, (ultra sharp:1.2), 8k uhd
Negative: cluttered background, shadow, watermark

训完直接批量出图,淘宝主图秒上架。


高级骚操作合集——卷死同行

  1. 动态权重
    WebUI里用<lora:abc:0.6>出细节,<lora:abc:1.2>出风格,0~1.5之间随意滑,比滤镜还爽。

  2. 多LoRA混音
    上面代码演示过,0.7写实+0.3赛博,一秒变“赛博写真”。
    还能三混:0.5 日系 + 0.3 油画 + 0.2 颗粒胶片,味道复杂到甲方看不懂,但直呼高级。

  3. LyCORIS扩展
    LoRA只能改attention,LyCORIS把Conv、FeedForward也撬开,rank=8就能顶LoRA rank=32的效果。
    安装:

    pip install lycoris_lora
    

    训练时选network_module=lycoris.kohyaalgo=lora,即插即用。

  4. SafeTensor防投毒
    别再传.ckpt,容易被塞恶意代码。导出.safetensors

    from safetensors.torch import save_file
    save_file(state_dict, "abc.safetensors")
    

    传模型放心,群友也敢下载。


别光顾着训,用不好等于白练——最后5%的魔鬼

很多人训完LoRA,prompt里只写abc,生成图却平平无奇,原因:没调火候

  • negative prompt一定写全:
    (worst quality:2), (lowres:1.2), (oversaturated:1.3), (acne:1.1), (extra fingers:1.2)
    把LoRA跑偏的色偏、畸变全压回去。

  • CFG Scale
    写真79,二次元1012,产品6~7,数字越高风格越冲,但也容易过饱和。

  • Sampler
    细节糊就换Euler a,想锐利用DPM++ SDE Karras,别一条道走到黑。

  • 高分辨率修复
    先512生成→图生图768→再SD upscale到1536,三步走,显存峰值才8G。


最后说句掏心窝的

LoRA不是魔法,它只是把“大模型”这种高岭之花拽到地摊上,让我们用8G显存、三天假期、一堆手机废片就能整出能发朋友圈、甚至接小单的作品。
AI绘画的尽头不是算力军备竞赛,是会玩的人用巧劲赢麻了。
下次再看到“32G显存起跳”的教程,直接把本文甩过去:
“兄弟,醒醒,2024年了,穷也能玩微调。”

在这里插入图片描述

Logo

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

更多推荐