开头段落(约350字)
这篇是系列教程的第七章,前六章聊了不少训练参数、底模选择、学习率调度这些偏后端的活儿,但说实话,每次在社区里帮人排查 LoRA 训练翻车,十有八九都不是死在参数上,而是死在数据集上。不是图片太少,就是素材乱七八糟;不是打标打歪了,就是训练集灌进去一堆重复图。数据这块如果没做好,哪怕你把学习率调到完美,出来的模型依然是崩的。
LoRA 训练想“稳赢”,最该花时间的地方其实是数据集工程。这次我把它拆成“三件套”:第一件是采集与初筛,决定素材上限;第二件是清洗与统一处理,建立可用底线;第三件是打标与训练集构建,控制精度下限。三件套环环相扣,每一件都有不只一个坑。这篇文章适合正在用各种开源训练脚本做 LoRA、又总在数据上纠结的朋友,也适合拿着一张图就想硬训的新手——看完你就明白,为什么没人能用三五张乱图炼出好东西。
1. 三件套的整体设计:为什么数据工程决定 LoRA 成败
1.1 先别急着跑训练,数据才是那块最短的板
很多人在拿到 LoRA 训练脚本之后,第一反应是改学习率、调网络维度,仿佛这些数字能拯救一切。但 LoRA 的本质是什么?是在底模基础上用低秩矩阵去“记住”你提供的样本分布。它不是在凭空创造特征,而是在你给的图像特征里找规律。如果你的样本里根本没有某个角度、某个光线、某个表情,那模型就是想破头也编不出来。
数据决定了 LoRA 能力的上限,训练参数只是尽量靠近这个上限。这一点用一句土话来说就是:训练跑得快不快不重要,数据是不是有效才是决定你能不能“稳赢”的关键。所以我的习惯永远是把 70% 的时间花在数据集工程上,真正点开训练按钮的过程反而很快。
1.2 “三件套”具体指什么,为什么这么拆
我之所以把数据集工程分成三件套,不是因为这种框架听起来漂亮,而是因为它对应了 LoRA 训练中三个完全不同的风险来源:
- 采集与初筛负责“有什么”。素材的范围、数量、多样性决定了模型能覆盖多少维度。素材全是同一角度,产出就只会摆固定姿势;素材全是模糊图,细节就永远学不会。
- 清洗与统一处理负责“能不能用”。同一批次图片的分辨率五花八门、构图歪七扭八、重复图极高,模型就会被噪声带偏,训练曲线看着正常,实际生成却一塌糊涂。
- 打标与训练集构建负责“学得准”。训练时模型需要知道哪些是可以固化的特征、哪些是应该忽略的属性。标签贴反了,概念就串味;触发词设置不当,模型推理时就叫不出你要的东西。
很多知名问题看起来是“网络能力不行”或者“底模不行”,剖开一看,其实都出在这三件套其中一环。后面三个部分我会一步步拆开讲。
2. 第一件套:采集与初筛,决定模型上限
2.1 从源头把关:素材从哪里来,要攒多少张
先回答一个被问了八百遍的问题:到底要准备多少张图?
针对不同类型的 LoRA 目标,这个数字差别挺大。人物类通常建议 50 到 150 张高质量图,少于 30 张往往连基本人脸一致性都不够稳定;画风类可以少一点,30 到 80 张高质量作品就够,因为画风的规律通常比单个人物的特征更明显;纯物体或者logo/产品类,建议 50 张以上,特别是要兼顾多角度时。如果你的目标是某种生物、机械、服装等复杂对象,数量可以更进一步往上提。
这里说的“张”,指的是经过筛选后真正进入训练集的有效图。下载 200 张、清洗完只剩 80 张,这是很正常的事。素材来源可以是自己拍摄的照片、图库授权素材,或者经过允许的作品集。我的经验是,宁可用 50 张横跨各种环境的高质量图,不要用 200 张内容高度雷同的图。因为模型需要的是“变化量”,不是“数量”。
2.2 好素材的四个硬指标:清晰度、占比、多样性、可分离性
我筛选图片时会逐张过四种判断,缺一不可:
- 清晰度:人眼看着舒服不一定够,要看细节。人物的眼睛、毛发边缘、纹理必须清楚,尤其是脸部区域。我会把图片放到 100% 缩放,重点看皮肤纹理和边缘是否发虚。一张 512×512 的正常图如果是手机随手拍、脸部占画面很小,那即便整体清晰也没用,放大后必然糊。
- 主体占比:主体在整张图中最好占 30% 以上。对于人物 LoRA 来说,脸如果只占画面 10%,放大后信息不足,模型就只能学到“大概这么个人”,学不到五官特征。最好的做法是想清楚你要训练的是“头像”还是“全身”,再按这个目标去选图。哪怕你目标是全身 LoRA,有效的脸部特写也能帮助模型锁定脸部特征。
- 多样性:这是个容易被忽略的指标。角度、光线、表情、背景、姿态、服装风格都要有变化。最怕的就是从某个平台扒下来一组同一场景的连拍图,角度背景几乎一样,这种数据喂进去,模型很快会过拟合到那个固定场景上,换个背景就崩。
- 可分离性:素材中带有的特征,哪些是你希望模型固定下来的,哪些是希望模型忽略的?用人物举例,如果你希望模型保持某个角色的样貌,那就不应该让鞋帽配饰等随机元素在每张图里都出现。反过来,如果某个角色几乎每张图都戴着眼镜,那么“眼镜”就必须作为标签明确标注出来,让模型知道这是独立属性而不是脸部本身的一部分。
2.3 初筛三步走:去重、去糊、去无关
很多人的素材库里重复问题非常严重,尤其是从视频抽帧得到的序列图,相邻几帧几乎一模一样。这种数据放进训练集,等于无形中把某几张图重复了很多遍,不仅浪费步数,还会强化某个角度的权重。我过滤重复主要靠三招:
- 先按缩略图模式扫一遍,把肉眼可见的重复图和宫格图挑出来。
- 再对整体相似但缩略图不好判断的图,用脚本算出感知哈希值,两两比较。相似度过高就直接删。这个阶段我一般保留一个印象:一个对象最终在训练集里出现的有效“角度/场景”数量最好超过 20 种,不然非常容易在推理时陷入复制粘贴式的输出。
- 模糊图、带大块水印或马赛克的图、画面被严重遮挡的图,统统剔掉。特别是水印,如果你训练 LoRA 时把水印也当成图像特征学了,最后生成时会莫名其妙出现一条半透明文字带,那个效果非常难消除。
关于要不要用专用软件自动筛选:可以,但不要完全依赖。自动算法擅长找特征相似度,不擅长判断“这张图虽然糊但正好是唯一能提供俯视角度的那张”。所以我建议自动筛选用于粗筛,人工浏览用于最终确认。
2.4 素材要不要做裁剪和旋转预处理
采集完之后,第一件事往往不是立即打标,而是先做构图上的整理。很多人会把 1920×1080 的大图直接丢进训练脚本,脚本虽然会做缩放裁切,但裁切中心默认是图片中心,主体在角落时会直接被切掉。这是数据集工程里非常典型的翻车原因。
我的做法是先用工具把主体区域裁出来,尽量让主体居中且占比例合适,再统一缩放。比如素材是 1920×1080,我会先把中间或包含主体的大块区域裁成 1080×1080 正方形,再缩到训练分辨率,比如 512 或 768。有基础的朋友也可以配合语义分割工具按主体边界裁,但大多数场景下手动框选已经足够。
3. 第二件套:清洗与统一处理,建立“可用”底线
3.1 统一分辨率:等比缩放、中心裁剪、还是Serde填边?
训练脚本对输入图有一个固定的训练分辨率,常见 512、768,SDXL 类底模用 1024 也很常见。但你的原始素材不可能全是这个尺寸。这时候有三个选择:
- 直接拉伸:不推荐,画面变形会严重影响特征学习,人脸比例都会歪掉。
- 等比缩放后中心裁剪:这是最常用方案。原图按短边缩放后,把超出训练分辨率的部分裁掉。好处是画面比例正确,坏处是主体可能在边缘被裁切。
- 等比缩放后填边:把背景填到目标尺寸。好处是信息完整,坏处是填出的边缘区域在生成时可能会形成一条固定色带痕迹。
我个人的优先级是:手动裁好主体后再等比缩放到目标分辨率,必要时用填边方案,但不要让它成为默认。如果你的素材主体足够居中,直接用脚本的中心裁剪也问题不大。
这里还需要注意一个点:训练脚本在做 resize 的时候,一般会对长边规则做内部缩放,但如果图片比例过于极端,比如竖长图 600×2000,即使缩放到目标短边,长边信息也会大量丢失。这种素材就应该提前拆成多个局部裁切图,或者直接舍弃。
3.2 文件命名、格式与目录结构规划
训练脚本通常不挑文件名,但是好的命名习惯能让你在排查的时候少掉很多头发。我的目录结构类似:
dataset/ ├── train/ │ ├── character_x/ │ │ ├── 001.png │ │ ├── 001.txt │ │ ├── 002.png │ │ └── 002.txt │ └── style_y/ │ ├── 101.png │ ├── 101.txt │ └── ... └── config.toml文件名可以有前缀,但建议不要包含特殊字符和空格。图片格式上 png 和 jpg 都可以,但 png 通常能避免二次压缩带来的锯齿。如果你在训练后要在各种 UI 里预览模型效果,jpg 也没问题,但底层训练时我一般统一转成 png。
3.3 检查并剔除“污染特征”
有些特征是无意中混进数据里的,但模型会当真。举几个实际场景:
- 一个角色所有照片都在室内暖光下拍摄,模型就会把暖黄色调当成角色的固有属性。生成时换了冷光场景,角色肤色依然偏黄。这类问题需要对图片进行白平衡调整,让素材的光线色温更中性,或者补充不同色温条件下的图。
- 主题是某个机械,但所有参考图背景都在草地上。模型可能把草地纹理当成机械的一部分。这不意味着你要把背景全抠掉,而是要增加背景多样性,让模型区分“主体”和“环境”。
- 系列图片都带同款边框或相框,模型会学会输出这个边框,而且极难通过标签压制。最彻底的办法是提前裁掉边框。
清洗阶段的核心思想是把“数据里稳定的变量”降到你真正想要的属性上。你想要的稳定变量是“样貌”或“笔触”,那光线、背景、服装、构图这些就都要被处理成可变量。
3.4 数据增强:能用,但别乱用
如果你的图实在不够,可以用数据增强扩充数量。比如轻微旋转(±15 度以内)、水平翻转、亮度微调、色调微调等,都能扩展样本分布。但增强不是无脑套,我有一个明确禁忌:不要对包含文本或方向性的物体做水平翻转。你训练一个服装上的字母图案,水平翻转后字母反了,模型学到的就是个混乱的镜像文字。
还有一点,增强强度过大反而会破坏关键特征。比如对人脸做强烈的色彩抖动,模型会认为脸部颜色不稳定;对精细纹理做随机遮挡,会让细节学不清楚。增强的正确用途是多创造“不同角度和光线”的假样本,而不是制造变形版本。能用真实多样化素材解决的问题,尽量不要靠增强硬凑。
4. 第三件套:打标与训练集构建,把控制精度
4.1 触发词与标签体系:模型怎么认出你要的东西
LoRA 训练里,标签系统决定了“模型能把什么和什么分开”。触发词(trigger word)是一个极其重要的设计。它本质上是一个没有任何先验语义的占位词,用来让模型在推理时锁定你的 LoRA 特征。选择触发词的原则是:短、独特、不常用。常见英文词或常用昵称最好不要用,因为底模已经对它们形成了很强的语义联想,你很难把一个全新概念覆盖上去。
举个例子,如果你训练一个虚构角色,触发词可以设计为tsvxx这种无意义的短串。配套的打标方式很简单:每一张训练图的标签文本里都保留这个触发词,而且最好放在开头,再配合keep_tokens参数让它不被随机打散。训练完成后,生成时输入“套着触发词 + 一些属性描述(如 tsvxx, portrait)”就能唤起模型记忆。
标签体系要遵循“少即是多”的原则。不需要把画面里的每一根草都写成标签,只需要写出对模型有区分意义的元素。但有一点必须注意:主体特征如果不是你想固定的,就必须明确标记出来。例如角色总是穿红色衣服,你希望模型能学会“换衣服”,那就必须打上 red dress 这类标签,否则模型会认为红衣服是这个人的固有特征。
4.2 反推标签之后,必须人工修正
现在有很多现成的打标工具,能自动反推出图片标签。这些工具的效率相当高,但反推结果不能直接当训练标签用。主要有几个问题:
- 反推工具会把画面里所有次要元素都列出来,包括背景里的杂物。这些标签如果保留,模型会试图把一些无关杂物也学进特征里,造成生成时带着杂讯。我一般会删掉与主体无关的环境标签。
- 部分工具对中文语义的支持不强,反推结果是英文短句。如果工具生成的句子结构很碎,可以在标签之间加逗号,整批保持稳定风格就好。如果条件允许,人工逐条检查一遍是最稳的。
- 同一批素材要保证标签措辞一致。比如一会儿写“green shirt”,一会儿写“shirt, green”,模型在处理时会多花不必要的学习成本。统一风格后,训练效果会稳定很多。
打标文本文件的内容,通常就是逗号分隔的标签列表,例如:tsvxx, 1girl, blue eyes, black hair, school uniform, indoors。如果训练脚本支持shuffle_caption,这些标签在训练时还会被打乱顺序,所以触发词必须通过keep_tokens固定在开头,否则触发词也会被随机打散,影响模型收敛。
4.3 分组、重复次数与 steps 估算
不同的图片子集,在训练中的地位不一定相等。假设你训练一个角色 LoRA,其中有 60 张高质量正脸图,还有 20 张全身图。如果你希望模型更重视脸部,那可以在配置里给脸部图子集更大的num_repeats,也就是重复次数。训练脚本里有一个常见配置结构:
[general] shuffle_caption = true caption_extension = ".txt" keep_tokens = 1 [[datasets]] resolution = 512 batch_size = 4 [[datasets.subsets]] image_dir = "/path/to/dataset/train/face" num_repeats = 12 [[datasets.subsets]] image_dir = "/path/to/dataset/train/fullbody" num_repeats = 5这样脸部图在每轮中的曝光次数高于全身图,训练出的模型会更侧重脸部细节。这个机制也能用来应对数据量不平衡的问题。但要注意num_repeats并不是越大越好,重复次数过高会加快过拟合,一般控制在 10 到 20 之间比较稳妥。
关于训练总步数的估算,有一个非常基础但容易算错的公式:
每轮步数 = 图片数量 × 该图重复次数 ÷ batch_size 总步数 = 每轮步数 × epoch 数假设有 80 张有效图,平均 repeat 为 10,batch_size 为 4,epoch 为 5:
- 每轮样本数 = 800
- 每轮步数 = 800 ÷ 4 = 200
- 总步数 = 200 × 5 = 1000
我在推荐别人起步时,通常建议用 1000 到 3000 步这个范围,再根据验证集效果动态调整。如果步数太少,特征学不进去;步数太多,模型开始死记硬背,生成结果会变得单一枯燥。
4.4 进阶可选:正则化图与其他数据组织技巧
如果你担心 LoRA 过拟合导致底模能力被破坏,可以引入一组所谓的“正则化图像”。这些图通常用底模配合同样的触发词批量生成,内容与训练目标相似,但多样性更强。它们在训练中起到“锚点”作用,让模型在贴近新特征的同时不至于把旧知识忘光。
我的经验是,正则化图像并非必需品,适合在数据集重复次数偏高、训练步数偏长、明显出现过拟合时使用。不要一上来就搞全套正则化,那样会让训练时间翻倍,收益却不明显。
另外还有一个容易被忽略的小技巧:给数据集做顺序打乱。同一个人物如果所有训练图按时间顺序排列,模型可能会学到一种“固定出场模式”。大多数脚本本身就带打乱逻辑,但如果你用自定义脚本,记得在每轮 epoch 之前重新 shuffle。这样才能保证数据集每个子集都被公平地反复接触。
5. 常见问题速查与翻车实录
5.1 模型“千人一面”或“单姿势复读机”
很多人训练完发现,不管输入什么姿势、什么环境,人物的脸和姿态几乎都一样。绝大部分原因是数据集本身的姿态多样性太差。还有一个隐含原因:标签体系里写了太多“站姿、看向镜头、正面”这类重复描述,模型把这些当成了核心特征。
排查方法很简单:先将训练集图片缩略图全部铺开,看看姿态、视线方向、取景范围的变化数量。如果有 50 张图里 40 张都是正脸大头照,那模型不可能学会侧面和全身。解决办法是补图,而不是调参。
5.2 紫脸、崩脸、纹理异常
这一类问题的根源通常可以分成三种:第一,训练步数过长导致过拟合;第二,数据集中图片质量过低,颜色过饱和或色调偏移严重;第三,训练分辨率与底模分辨率不匹配。
我遇到最典型的场景是:素材里很多夜间图片和强烈滤镜图片,训练完生成时脸部出现发紫的肤色偏移。这是因为模型把滤镜色调学进去了。清洗阶段把色温不正常、滤镜过重的图片尽量剔除,或做色彩校正,能有效缓解。还有,如果底模是 512 训练的,你却用 768 分辨率训练数据集并强行上线,脸部纹理会出现不稳定的闪烁感,建议先用与底模匹配的分辨率做初步实验。
5.3 概念串味:标签污染带来的隐患
这个概念非常隐蔽。假设你要训练一只机械猫,猫的每张图里都带着“机械齿轮”元素。但反推标签时,没有对背景里的齿轮单独标注,模型就会把“齿轮”和“猫”绑定到一起。生成时你想输出一只不带齿轮的机械猫,模型却会在背景里画满齿轮。
解决办法是:确保主体与容易混淆的视觉元素之间,在不同图片上能解耦。也就是要让同样的背景元素同时出现在没有目标的图片中,或者让目标出现在不同背景中。打标时对非主体但有大面积存在的元素,都要显式标注,用标签来强迫模型把它们视为可分离属性。
5.4 标签系统一致性自查清单
我在打标完成后会做一个非常机械但有效的检查:把所有 txt 文件里的标签做词频统计,对高频属性、高频环境、高频配饰进行逐一复查。
- 高频属性是否确实是你想固定的?如果不想固定,就要调整素材或删标签。
- 有没有某张图上独特的配饰被忘记了?比如只有一张图带了围巾,那这张图的标签必须包含围巾,否则模型会对“围巾”这个外形特征产生混淆。
- 触发词是否在所有标签文本的开头?训练配置里是否启用了 keep_tokens?
这个清单花不了十分钟,却能拦掉至少一半的诡异训练结果。每次有人说“我参数完全没问题,但模型就是怪”,我都会先要一份标签词频统计表,结果总能发现问题出在这几个地方。
6. 一些个人体会与收尾
写了这么多,其实核心想表达的就一句话:LoRA 训练里,真正决定“稳赢”的不是某次跑批训练时调出来的那个学习率,而是你在数据集工程里愿意花多少笨功夫。
我自己练过很多不同风格的 LoRA,每次最有价值的复盘材料都是“素材筛选记录”和“标签修改历史”。跑训练脚本只需要几分钟或几十分钟,但数据的取舍和标签的打磨是持续多轮的。一个数据集往往要来回改三到五版,才能达到“怎么换环境都不崩、怎么换姿势都不重影”的状态。所以如果你现在正卡在某个训练效果怎么调都不对,不妨先退回到数据集工程三件套上,从头检查一遍采集、清洗、打标这三个环节。很多困扰你很久的问题,答案其实都在数据里。