日期:2026-08-24
一、项目背景 我们给一个行业客户做专属模型微调,基座选的是同尺寸里效果不错的通用模型,预期是微调后能在客户领域明显更强。结果训出来一测,效果还不如基座,某些指标甚至掉了。团队第一反应是模型结构或者学习率的问题,调了好几轮没起色。后来有人提议翻翻训练数据,这一翻吓一跳:业务方导出的几千条样本里,大量重复、格式错位、带噪声的脏数据,还有一批标注口径前后不一致的,等于模型在学噪音。我们这才意识到,微调这事儿,数据比结构更要命,地基是歪的,楼怎么盖都歪。
数据来源也很杂,业务方从客服记录、工单系统、历史导出里各捞一部分,格式五花八门,我们先用统一抽取层把它们规整成同一 schema,清洗规则才好往上叠。
清洗流水线我们做成可配置的,不同业务的数据特征不一样,去重阈值和校验规则都能调,避免一个固定参数在所有场景里要么误删要么漏网,灵活度比一开始想的更重要。
二、落地场景 第一块是数据去重,我们对样本做 embedding 后聚类,相似度高的归为一簇,超过阈值的重复样本只留一条,其余打标删除。第二块是格式错位检测,很多样本问答对错位,问题和答案对不上,我们用结构校验加模型判断把这类挑出来。第三块是标注一致性校验,同一类问题不同标注员给的标签冲突的,拉出来人工复核。第四块是质量打分,综合重复度、长度、语义完整度给每条样本打分,低分抽样人工看。最后是回流闭环,清洗后的数据版本化管理,每次微调都能追溯到用了哪版数据。
还有一类问题是标签漂移,同一个概念不同时期叫法不一样,我们做了同义词归并,否则模型学到的是分裂的语义,评测看着涨实际是记混了。
三、关键技术挑战与解决思路 去重最容易过头。我们一开始阈值设得紧,把一批合理相似但语义不同的样本也删了,模型在某个细分话题上反而变笨。后来把阈值放宽并加人工抽检,保留合理多样性。格式错位检测靠规则不够,我们用一个小模型做问答是否匹配的二分类,准确率比正则高不少。标注一致性最费人工,我们做成冲突自动聚堆,标注员一次看一堆同类冲突,效率比一条条看高很多。质量打分我们避免单一指标,组合了多个维度,防止某类样本被系统性误杀。
成本侧,自动化清洗把数据准备的人力从两个人一周压到一个人半天,而且每次微调都能复用同一套流水线,新业务接入时这套直接搬过去就能用。
校验规则的顺序也讲究,我们先做结构错位检测再做语义一致性,因为如果格式都错了语义对比没有意义,顺序反了会浪费大量人工在本来就该先淘汰的样本上,这个排布是吃了一次亏之后定的,当时先跑了语义对比,结果一半样本格式都不对,人工看了个寂寞。
四、效果数据 清洗后训练集里重复样本占比从约四成降到不足百分之三,格式错位的样本基本清零。用清洗后的数据重训,模型在客户领域的评测集上比基座提升了约八个点,之前掉的那部分也回来了。迭代周期从原来的训完才发现差变成训前先过质量关,一次微调的数据准备时间反而因为自动化降了约三成。客户侧实测任务准确率提升明显,终于达到了立项时的预期。
还有个意外收获,清洗过程本身成了数据资产,哪些样本被删、为什么删都留了记录,后来客户问某次效果波动,我们能直接溯源到那版数据,信任又加了一层。
五、可复用经验总结 微调效果不行,先别急着动模型结构和超参,把数据翻一遍,十次有八次问题在 data。去重要留多样性,阈值别太狠,否则洗得很干净但模型变傻。格式错位和标注冲突靠人是填不过来的,得用模型加聚类把问题聚堆再让人拍板。我们那次白调一周参数,教训就是:数据质量流水线要前置到训练之前,而不是训崩了才救火。
微调项目最容易在 data 上偷懒,大家总想直接拿现成数据训,我们这次是被教训出来的,现在任何微调立项头一件要做的事就是过质量关,模型的事反而排后面。
数据质量这件事,做一遍是救火,做成流水线才是资产,我们现在把它当基础设施而不是一次性项目。
结语 现在这家客户每次微调都先跑一遍清洗流水线,数据版本和模型版本绑定存档,近期在看自动生成难例补充训练集。
案例片段(已脱敏): 去重聚类片段(伪码):
emb = embed(batch.Samples) clusters = dbscan(emb, eps=0.12, minPts=2) // 相似度聚类 for c in clusters { if len(c) > 1 { keep := pickBest(c) // 留质量最高的一条 for x in c if x != keep { markDelete(x) } } } log.Info("dup removed", "before", len(batch), "after", survived)最初我们 eps 设成 0.08,删得不够,重复还占两成;放宽到 0.12 后重复压到百分之三,但再放到 0.16 就把合理相似样本也误删了,最终定在 0.12 这个平衡点。