1. 为什么选择本地部署而不是云端Notebook
很多人第一次接触LoRA训练,第一反应是打开云端Notebook跑一遍示例。我最初也是这么干的,但很快就发现几个绕不过去的问题:免费额度跑两次SDXL微调就没了,数据集上传下载来回折腾,最要命的是训练到一半断线,几十个epoch白跑。后来我下定决心在本地把kohya_ss这套环境搭起来,前后折腾了大概三个晚上,踩了不少坑,也总结出一套相对稳定的流程。
kohya_ss本质上是一个围绕扩散模型训练脚本的图形化封装,它把原本需要手写命令行参数的训练过程变成了可视化配置。核心能力包括SD1.5/SDXL的LoRA训练、DreamBooth微调、Textual Inversion等。LoRA(Low-Rank Adaptation,低秩适应)的思路是在原有大模型的权重矩阵旁边挂两个小矩阵,训练时只更新这两个小矩阵,这样显存占用和训练时间都大幅下降。SDXL因为底模参数量比SD1.5大好几倍,直接全量微调基本不现实,LoRA几乎是个人玩家的唯一选择。
这篇文章适合谁看?如果你手上有一张8GB以上显存的N卡,想训练自己的角色LoRA或者画风LoRA,又不想被云端平台的各种限制绑住,那这套流程可以直接抄。如果你连Python都没装过,也不用慌,我会把每一步的命令和预期输出都写清楚。
先说结论性的硬件门槛,这是我实测下来的经验值:
| 训练类型 | 最低显存 | 推荐显存 | 备注 |
|---|---|---|---|
| SD1.5 LoRA | 6GB | 8GB | batch size=1,开启梯度检查点 |
| SDXL LoRA | 8GB | 12GB | 必须开gradient checkpointing |
| SDXL LoRA (高分辨率) | 12GB | 16GB | 1024分辨率训练 |
| DreamBooth SD1.5 | 10GB | 12GB | 全量微调显存需求高 |
显存不够的时候不要硬撑,先把batch size降到1,再开梯度检查点,还不行就降分辨率。我见过太多人卡在CUDA out of memory上反复重启,其实调两个参数就能解决。
2. 环境部署:从Python版本到依赖冲突的完整排雷
2.1 Python和CUDA版本的匹配逻辑
kohya_ss对Python版本有明确要求,我建议用Python 3.10.x,这是目前兼容性最好的版本。3.11和3.12虽然也能跑,但部分依赖包(尤其是bitsandbytes和xformers)的预编译轮子还没跟上,容易在安装阶段就卡住。
CUDA版本要和你的显卡驱动匹配。用nvidia-smi查看驱动支持的CUDA最高版本,然后去PyTorch官网找对应的安装命令。比如驱动显示CUDA 12.1,就装cu121版本的PyTorch。这里有个坑:很多人直接pip install torch,装到的是CPU版本,训练时才发现用不了GPU。正确的做法是明确指定index-url:
pip install torch==2.1.2 torchvision==0.16.2 --index-url https://download.pytorch.org/whl/cu121装完之后一定要验证:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))三行输出分别应该是版本号、True、你的显卡型号。如果第二行是False,后面所有训练都跑不起来,先解决这个问题再往下走。
2.2 kohya_ss的克隆与安装脚本选择
官方仓库的安装脚本分Windows和Linux两套。Windows下直接运行setup.bat,Linux/Mac下用setup.sh。但我要提醒一句:安装脚本会自动创建虚拟环境并装一大堆依赖,整个过程可能持续20到40分钟,取决于网络状况。国内网络环境下,建议先配置pip镜像源,否则大概率中途超时。
配置镜像源的方法:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple然后再跑安装脚本。安装完成后,启动脚本是gui.bat(Windows)或gui.sh(Linux)。启动成功后浏览器会自动打开一个本地页面,地址通常是http://127.0.0.1:7860。看到界面就说明环境基本通了。
2.3 依赖冲突的典型表现与修复
安装过程中最常见的报错是版本冲突,典型的有两类:
第一类是xformers和torch版本不匹配。xformers能显著降低显存占用、提升训练速度,但它对torch版本极其敏感。如果报错提示xformers requires torch==xxx,最省事的做法是先卸载xformers,用--no-deps参数单独装匹配版本:
pip uninstall xformers -y pip install xformers==0.0.23.post1 --no-deps第二类是bitsandbytes在Windows上的兼容问题。这个包在Linux下开箱即用,Windows下需要额外装一个补丁包。如果训练时提示bitsandbytes library load error,去GitHub搜bitsandbytes-windows,按说明替换dll文件即可。
提示:每次改动依赖后,建议重启一次GUI,让Python重新加载所有模块。我遇到过改完依赖不重启,训练脚本仍然调用旧版本的情况。
2.4 验证环境是否真正可用
环境装完不要急着上正式数据集,先用官方提供的示例配置跑一个最小训练。准备5到10张图片,分辨率统一到512,跑10个step看看能不能正常出loss曲线。这一步的目的是确认数据加载、模型加载、显存分配、保存输出这条链路全部通畅。我见过有人直接上几百张图训练,跑到一半报错,排查成本极高。先用小数据集验证,是省时间而不是浪费时间。
3. 数据集准备:标注质量决定LoRA上限
3.1 图片筛选与预处理的实际标准
数据集的质量比数量重要得多。我训练角色LoRA的经验是:15到30张高质量图片就能出不错的效果,关键是图片要有多样性。什么叫多样性?不同角度、不同表情、不同光照、不同背景、半身和全身都要有。如果全是同一个角度的自拍,训练出来的LoRA换个角度就崩。
分辨率方面,SD1.5训练用512x512或512x768,SDXL用1024x1024。图片不要强行拉伸,保持原始比例,用裁剪或者padding补齐。kohya_ss内置了预处理工具,在Utilities标签页里可以批量resize和裁剪。
图片格式统一用PNG或JPG,去掉透明通道。我遇到过带alpha通道的PNG导致训练报错的情况,批量转成RGB模式就好了。
3.2 打标:触发词的选择与正则化标签
打标是LoRA训练里最容易被忽视但影响最大的环节。每张图都要配一个txt文件,内容是对图片的描述。触发词(trigger word)是你希望用来激活这个LoRA的特殊词,建议用一个不常见的词,比如ohwx、sks这种,避免和底模已有的概念冲突。
打标工具推荐用BLIP或WD14 Tagger自动生成初稿,然后手动修正。自动打标的问题是它会描述所有细节,包括你不想让模型学的东西。比如你训练一个角色,背景里有桌子椅子,自动打标会把桌子椅子也标进去,结果模型把这个角色和桌子绑定了。手动修正的原则是:只保留你希望模型关联的特征,背景元素尽量删掉或者用通用词替代。
正则化标签(regularization)是另一个关键概念。简单说,你需要准备一批和训练目标同类但不包含特定特征的图片,配上通用标签,防止模型过拟合。比如训练特定人物,正则图就是各种不同的人,标签统一用person。kohya_ss支持在配置里指定正则图目录,训练时会混合采样。
3.3 目录结构组织与配置文件的对应关系
kohya_ss对目录结构有约定,搞错了会直接报找不到文件。标准结构是这样的:
train_data/ └── 10_ohwx/ ├── img1.png ├── img1.txt ├── img2.png └── img2.txt文件夹名10_ohwx里的10表示每张图重复训练10次,ohwx是触发词。这个数字不是随便定的,重复次数乘以图片数量再乘以epoch数,就是总训练步数。一般角色LoRA总步数控制在1500到3000之间比较合适。
正则图目录单独放:
reg_data/ └── 1_person/ ├── reg1.png └── reg1.txt配置界面里分别指定训练目录和正则目录即可。
3.4 数据集常见问题排查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 报错找不到图片 | 目录名格式不对 | 检查是否为数字_触发词格式 |
| 训练loss不下降 | 标注质量差或学习率过低 | 检查txt内容,适当提高学习率 |
| 过拟合严重 | 重复次数过高或图片太少 | 降低重复次数,增加图片多样性 |
| 生成图不带触发词也像 | 触发词太常见 | 换一个生僻词作为触发词 |
| 显存溢出 | 分辨率或batch size过高 | 降分辨率,batch size设为1 |
4. 训练参数配置:每个数字背后的取舍逻辑
4.1 学习率与优化器的搭配
学习率是训练中最敏感的参数。LoRA训练常用的优化器有AdamW和AdamW8bit,后者显存占用更低但精度略差。学习率建议从1e-4开始试,SDXL因为模型更大,可以适当降到5e-5。
这里有个反直觉的点:学习率不是越低越好。太低会导致训练不充分,loss降不下去;太高会导致过拟合或者训练崩溃。我的做法是先跑200步看loss曲线,如果loss在0.1以上且下降缓慢,说明学习率偏低;如果loss剧烈震荡或者直接变成nan,说明学习率偏高。
调度器(scheduler)推荐用cosine_with_restarts或者constant_with_warmup。warmup步数设为总步数的5%到10%,让学习率从0慢慢升上去,避免一开始就大步更新破坏预训练权重。
4.2 网络维度与alpha的关系
LoRA的rank(网络维度)决定了可训练参数的数量。rank越大,模型容量越大,但过拟合风险也越高。SD1.5常用rank 32到64,SDXL常用rank 16到32。alpha是缩放系数,一般设为rank的一半或者等于rank。
我实测下来的经验:角色LoRA用rank 32、alpha 16比较稳;画风LoRA用rank 64、alpha 32能保留更多风格细节。如果训练数据少于20张,rank不要超过32,否则几乎必然过拟合。
4.3 混合精度与梯度检查点的显存账
混合精度(mixed precision)有两个选项:fp16和bf16。bf16动态范围更大,训练更稳定,但需要显卡支持(RTX 30系及以上)。fp16兼容性好但容易出现梯度下溢。如果你的显卡支持bf16,优先选bf16。
梯度检查点(gradient checkpointing)是用时间换显存的技术,开启后显存占用能降低30%到50%,代价是训练速度慢20%左右。显存紧张时必开,显存充足时可以关掉提速。
算一笔显存账:SDXL LoRA训练,1024分辨率,batch size=1,开启梯度检查点和bf16,8GB显存勉强够用。如果关掉梯度检查点,至少需要12GB。这就是为什么我一直强调先确认显存再选参数。
4.4 保存策略与训练中断的恢复
kohya_ss支持按epoch或按步数保存checkpoint。建议每2个epoch保存一次,同时保存优化器状态(optimizer state),这样训练中断后可以从最近的checkpoint继续,不用从头再来。
保存的LoRA文件有两种格式:safetensors和ckpt。safetensors更安全,加载更快,优先选它。保存路径不要有中文和空格,否则某些脚本会报编码错误。
注意:训练过程中不要手动关闭GUI窗口,正确做法是在界面点Stop按钮,等它保存完当前checkpoint再退出。直接关窗口可能导致最后一个checkpoint损坏。
5. 训练过程监控与常见故障处理
5.1 loss曲线的正确读法
训练开始后,GUI会实时显示loss值。健康的loss曲线应该是先快速下降,然后趋于平缓。前100步loss从0.3降到0.15左右是正常的,之后缓慢降到0.08到0.1区间并稳定。
如果loss一直卡在0.2以上不降,检查三个地方:学习率是否太低、标注是否和图片内容匹配、触发词是否在每张图的txt里都出现了。如果loss降到0.05以下还在降,大概率过拟合了,赶紧停,用中间epoch的checkpoint。
5.2 显存溢出的逐步排查路径
CUDA out of memory是最高频的报错。排查顺序应该是这样的:
第一步,确认没有其他程序占用显存。浏览器开着一堆标签页、后台跑着游戏,都会抢显存。用nvidia-smi看当前占用。
第二步,降低batch size到1。这是最直接有效的手段。
第三步,开启梯度检查点。如果已经开了,尝试降低分辨率,比如从1024降到768。
第四步,换用AdamW8bit优化器,能省不少显存。
第五步,如果以上都不行,说明硬件确实不够,考虑用云端或者换显卡。
我遇到过一次诡异的情况:所有参数都调到最低还是溢出,最后发现是xformers版本不对导致显存泄漏。卸载xformers后反而正常了。所以排查时不要忽略依赖包本身的问题。
5.3 训练速度异常的定位方法
训练速度突然变慢,常见原因有三个:一是硬盘IO瓶颈,数据集放在机械硬盘上,每次加载图片都要等;二是CPU预处理跟不上,图片解码和增强在CPU上做,CPU太弱会拖后腿;三是显存快满了,系统在频繁做内存和显存之间的交换。
解决办法:数据集放SSD,关闭不必要的图片增强,监控nvidia-smi的显存占用率。如果显存占用率长期在95%以上,说明快满了,适当降参数。
5.4 出图效果不理想的归因分析
训练完了出图效果差,先别急着重新训练,按这个顺序排查:
先确认触发词用对了。txt里写的触发词和出图prompt里用的必须完全一致,大小写敏感。
再确认权重(weight)设置。LoRA加载时有个权重系数,默认1.0。效果太弱就调到1.2,效果太强导致画面崩坏就降到0.8。
然后看是不是过拟合。过拟合的表现是:出图风格单一、背景总是那几个、换个prompt就不像了。解决办法是用更早的checkpoint,或者减少训练步数重新训练。
最后才考虑数据集本身的问题。如果图片质量差、标注混乱,再怎么调参数也救不回来。
6. 模型验证与迭代:从能跑到好用
6.1 用固定prompt做横向对比
训练完成后,不要凭感觉判断好坏。准备一组固定的测试prompt,包含不同场景、不同角度、不同风格,用同一个seed生成图片。然后对比不同epoch的checkpoint,看哪个版本综合表现最好。
我通常会测这几类prompt:正面特写、侧面、全身、不同表情、和不同背景组合。如果某个checkpoint在大部分场景下都稳定,那就是最佳版本。
6.2 过拟合与欠拟合的补救训练
过拟合了怎么办?两个方案:一是用更早的checkpoint,二是用正则化图片重新训练一轮,降低学习率。欠拟合则相反,增加训练步数或者提高学习率。
还有一种情况是“局部过拟合”:某些特征学得很好,但整体不够自然。这种通常是标注不均衡导致的,比如大部分图都标注了某个特征,模型就过度关注它。解决办法是重新平衡标注,让每个特征的描述频率大致相当。
6.3 多LoRA叠加时的冲突处理
实际使用中经常需要叠加多个LoRA,比如一个角色LoRA加一个画风LoRA。叠加时容易出现特征冲突,表现为画面混乱或者某个LoRA完全不起作用。
处理原则是:主LoRA权重设高一些(0.8到1.0),辅助LoRA设低一些(0.4到0.6)。如果冲突严重,可以用分层控制,让不同LoRA作用于不同的网络层。kohya_ss支持在配置里指定block权重,这个功能进阶玩家可以深入研究。
6.4 版本管理与实验记录习惯
训练多了之后,最大的问题是记不清哪个LoRA是用哪套参数训的。我的习惯是每次训练建一个文件夹,命名格式为日期_触发词_rank_学习率,里面放配置文件副本、数据集信息、最终LoRA文件。这样半年后回头看也能快速定位。
另外建议用表格记录每次实验的关键参数和结果:
| 实验编号 | rank | 学习率 | 步数 | 效果评价 |
|---|---|---|---|---|
| exp001 | 32 | 1e-4 | 2000 | 略过拟合 |
| exp002 | 32 | 5e-5 | 1500 | 最佳 |
| exp003 | 64 | 1e-4 | 2000 | 风格强但崩坏 |
这个习惯看起来麻烦,但当你训练到第十个LoRA的时候,会感谢自己当初做了记录。
7. 一些没人告诉你的实操细节
训练SDXL LoRA时,底模的选择很关键。官方SDXL base模型适合训练通用能力,但如果你的目标是特定画风,用对应的微调底模效果更好。不过要注意,底模换了之后,之前训好的LoRA可能不兼容。
关于触发词,有个小技巧:在触发词后面加一个空格再跟其他描述词,能减少触发词和其他概念的粘连。比如ohwx, a person standing比ohwx person standing效果更干净。
还有一点,训练过程中如果发现loss突然飙升,不要慌,先看是不是到了某个epoch边界。有些调度器在epoch切换时会调整学习率,导致loss短暂波动。等几十步看是否恢复,恢复了就继续,没恢复再考虑中断。
最后说一个显存优化的偏方:把Windows的硬件加速GPU计划关掉,有时候能释放出几百MB显存。这个不是万能药,但在临界状态下可能刚好够用。
训练LoRA这件事,参数是死的,数据是活的。同样的参数,数据集质量差一倍,效果差十倍。与其反复调参,不如花时间把图片选好、标注写准。这是我踩了无数坑之后最深的体会。