ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LLM 微调实战(5):垂直领域数据构造:让训练样本像真实业务

LLM 微调实战(5):垂直领域数据构造:让训练样本像真实业务 承接与场景上篇预算表帮设备团队定了路线13B 走 QLoRA。栈选好了真正决定天花板的东西才登场——训练数据。垂直领域数据工程最容易犯的错是把条数够多当成像真实业务造了三万条样本分布却是拍脑袋的比例上线第一天就被真实流量的长尾打爆。本篇用两个确定性模拟回答两个具体问题多个类目、池子大小悬殊的数据一个 epoch 内到底该怎么配比用模板批量合成时多样性在哪个环节塌缩场景仍是那家工业设备厂商这次聚焦它们的故障报修语料。垂直数据与通用数据的两处差别第一处是事件分布。真实业务里改地址和爆炸申诉的出现频率差着数量级训练集如果各类目拉平模型对高频事件过度熟练、对低频事件反而陌生——低频高危事件安全红线恰恰是最不能出错的。正确做法是先从工单系统统计真实事件频率让采样分布对齐线上分布再对高危类目做有上限的过采样后面实验给出算法。第二处是行为规格。通用指令的数据集没有正确答案的写法垂直业务有报修话术必须包含确认停机→询问型号→给排查步骤→生成工单的 SOP 结构漏一步就是事故。这类规格没法从公开语料里蒸馏必须让业务专家定义模板、由模板反向约束合成与改写流程——这也是蒸馏数据需要重写的根本原因强模型不知道你的 SOP。数据来源构成一个金字塔塔基是强模型蒸馏便宜、量大、分布失真塔身是存量工单改写分布真实、需要脱敏与规范化塔尖是专家构造数量少、定行为规格、必须进评测集。健康的垂直数据集是三层混着按比例喂纯任何一层都有系统性偏差。实验一配比的水位分配算法设备团队的五个类目池子悬殊手册 QA 四万二、故障工单三千、备件查询八百、通用指令两万、安全红线案例只有一百二。目标是按温度 α0.5 把大池子向小类目倾斜份额 ∝ n^α介于自然分布与均分之间同时给过采样设硬上限——一个 epoch 内任何类目最多重复 4 轮否则模型只是在同批样本上多走了几圈背题而非学习。份额超限时用水位法把溢出量按比例让给未饱和类目训练数据配比: 自然分布 - 温度重加权 - 重复上限水位分配, 确定性。CATS{# 类目: 池内条数设备手册QA:42000,现场故障工单:3000,备件与库存查询:800,通用指令(防遗忘):20000,安全红线案例:120,}BUDGET30000# 一个 epoch 喂给优化器的条数CAP4# 单类目一个 epoch 内最多重复轮数ALPHA0.5# 温度: 1自然分布, 0各类目均分deftemp_shares(alpha):w{k:n**alphafork,ninCATS.items()}ssum(w.values())return{k:v/sfork,vinw.items()}defwater_fill(shares):按目标占比分配, 超过 CAP x 池容量的份额按比例让给未饱和类目。alloc{k:0.0forkinCATS}pool,budgetdict(CATS),float(BUDGET)for_inrange(10):live{k:shares[k]forkinpool}ssum(live.values())given{k:budget*v/sfork,vinlive.items()}ifall(given[k]CATS[k]*CAP1e-9forkingiven):alloc.update(given)breakforkinlist(pool):ifgiven[k]CATS[k]*CAP1e-9:alloc[k]CATS[k]*CAP budget-alloc[k]delpool[k]ifnotpool:breakreturnalloc natural{k:n/sum(CATS.values())fork,ninCATS.items()}targettemp_shares(ALPHA)allocwater_fill(target)print(%-14s %7s %8s %8s %8s %8s%(类目,池容量,自然占比,温度占比,实配条数,重复倍数))forkinCATS:aalloc[k]print(%-14s %7d %7.1f%% %7.1f%% %8.0f %7.1fx%s%(k,CATS[k],natural[k]*100,target[k]*100,a,a/CATS[k], -- 顶到上限ifaCATS[k]*CAP-0.5else))totsum(alloc.values())print(实配合计 %.0f 条 (预算 %d, 饱和让渡后未用满 %s)%(tot,BUDGET,0ifabs(tot-BUDGET)1else%.0f%(BUDGET-tot)))运行输出类目 池容量 自然占比 温度占比 实配条数 重复倍数 设备手册QA 42000 63.7% 46.5% 14088 0.3x 现场故障工单 3000 4.6% 12.4% 3765 1.3x 备件与库存查询 800 1.2% 6.4% 1944 2.4x 通用指令(防遗忘) 20000 30.3% 32.1% 9722 0.5x 安全红线案例 120 0.2% 2.5% 480 4.0x -- 顶到上限 实配合计 30000 条 (预算 30000, 饱和让渡后未用满 0)这张表把配比的三重张力全暴露了。温度 α0.5 把备件查询从自然占比 1.2% 提到 6.4%、安全红线从 0.2% 提到 2.5%——这是小类目获得存在感的方式同时设备手册从 63.7% 压到 46.5%且实际只取用池子的 0.3 倍大量池子根本喂不完这时候该做的是扩充类目多样性而不是堆量。最关键的是最后一行顶到上限的安全红线按目标份额应喂约 746 条但池子只有 120 条、4 轮重复封顶 480 条——水位算法诚实地暴露了数据缺口这个真问题想让模型多见安全案例正确反应是请专家补造至少 70 条新案例再吃 4 轮重复而不是把重复倍数调到 20。工程上这份分配表就是 DataLoader 的 weights 参数PyTorch 的 WeightedRandomSampler 能直接吃每轮训练前重算一次并归档配比从此有据可查。实验二模板合成数据的熵上限模板生成是塔尖规格下沉到塔基的通道把 SOP 写进句式模板槽位从业务枚举里取。它的隐患是组合空间被严重高估。设备团队有 12 个部件 × 12 种症状的槽位看着 144 种变化实际能产出多少不重复的问法取决于模板条数。生成 3000 条比较不同模板数下的唯一句数与 3-gram 熵理论唯一数用生日碰撞公式核算模板化合成数据的多样性塌缩: 模板数决定熵上限, 确定性模拟。importmathimportrandom COMPONENT[液压泵,主轴,刀库,冷却泵,伺服电机,编码器,丝杠,导轨,夹具,变压器,传感器,润滑油路]SYMPTOM[异响,过热,报警E-04,精度漂移,漏油,无法启动,抖动,间歇停机,压力不足,通信中断,限位误报,刀补失效]TEMPLATES[客户反馈设备{c}出现{s}请给出处理建议。,{c}{s}怎么排查,急{c}又{s}了现场催得紧。,请问{c}的{s}问题严重吗需要停机吗,{c}最近{s}之前换过一次件这次怎么处理,报修{c}{s}附报警代码。,新手提问{c}{s}一般是什么原因,{c}维护记录显示有过{s}历史现在复发了。,夜班遇到{c}{s}先做什么应急处理,{c}{s}客户要求 2 小时内恢复方案,{c}的{s}能不能在线解决不去现场行不行,对比上次故障这次{c}{s}有什么不同如何处理,]M3000# 每个配置的合成条数defmake(n_tpl):rngrandom.Random(7)return[TEMPLATES[rng.randrange(n_tpl)].format(crng.choice(COMPONENT),srng.choice(SYMPTOM))for_inrange(M)]defentropy(samples):cnt{}forxinsamples:foriinrange(len(x)-2):gx[i:i3]cnt[g]cnt.get(g,0)1totsum(cnt.values())ent-sum(c/tot*math.log2(c/tot)forcincnt.values())topmax(cnt.values())/totreturnlen(set(samples)),ent,topprint(槽位组合上限 模板数 x %d x %d%(len(COMPONENT),len(SYMPTOM)))forn_tplin(1,2,4,12):uniq,ent,topentropy(make(n_tpl))combosn_tpl*len(COMPONENT)*len(SYMPTOM)exp_uniqcombos*(1-(1-1/combos)**M)# 生日碰撞期望print( 模板%2d | 唯一句 %4d (碰撞理论 %4.0f, 组合上限 %5d) | 3-gram 熵 %5.2f bit | 最热 3-gram 占比 %.2f%%%(n_tpl,uniq,exp_uniq,combos,ent,top*100))运行输出槽位组合上限 模板数 x 12 x 12 模板 1 | 唯一句 144 (碰撞理论 144, 组合上限 144) | 3-gram 熵 6.10 bit | 最热 3-gram 占比 4.71% 模板 2 | 唯一句 288 (碰撞理论 288, 组合上限 288) | 3-gram 熵 6.81 bit | 最热 3-gram 占比 3.26% 模板 4 | 唯一句 574 (碰撞理论 573, 组合上限 576) | 3-gram 熵 7.80 bit | 最热 3-gram 占比 1.59% 模板12 | 唯一句 1430 (碰撞理论 1424, 组合上限 1728) | 3-gram 熵 8.88 bit | 最热 3-gram 占比 1.33%模拟数字把教训量化了单模板配 144 个槽位组合写三千条只有 144 句不重复——其余全是碰撞复读模板从 1 条加到 12 条唯一句数几乎线性增长3-gram 熵从 6.10 涨到 8.88。更微妙的是最热 3-gram 占比模板少时任何三字片段都高度集中模型会学到报修式口头禅而 12 模板配置里残留的 1.33% 集中片段正是槽位高频词设备“处理”属可接受。所以模板工程的检查动作是生成前先算组合上限生成后必测唯一率与 n-gram 熵上限不够就加模板、加槽位维度语气、客户角色、上下文片段或者把模板产物交给强模型做同义改写再回流去重——用蒸馏的多样性补模板的骨架两源合流的数据才既有分布又有变化。常见陷阱拍脑袋配比不问工单系统就定每类五千条上线后高频事件排队、低频事件瞎答。配比参数永远来自线上统计不来自直觉。过采样当扩充小类目重复倍数一路加到几十train loss 漂亮、评测崩盘——模型背题了。上限水位让渡是纪律。蒸馏数据零改写直接喂强模型原始输出把它的结构偏好列表癖、免责声明烙进你的模型。蒸馏产出必须过 SOP 模板重写这一道。负样本与红线缺失只造正确回答模型没见过该拒绝/该转人工的样子。安全红线类目的答案本身就是行为规格配比再小也不能为零。评测集同分布幻觉训练和评测都来自同一批模板熵塌缩双方一致分数全绿。评测集要掺真实工单原文与专家手写案例。落地清单每月从工单系统导出事件频率表作为温度配比的输入配比分配表随实验号归档类目级重复上限默认 3~4 轮水位算法自动暴露数据缺口清单模板合成三件套组合上限核算、唯一率报表、3-gram 熵基线本篇实验即模板三层来源金字塔配比起步蒸馏 60% / 改写 30% / 专家 10%之后按评测反馈调通用指令集以 5~10% 常驻配比防遗忘理由见下篇实验数据像业务了下一个问题立刻浮现改了这么多权重模型原来的能力还在不在下一篇《LLM 微调实战6评测集是护城河微调效果的自动化评测》先建立打分基础设施——没有它前面所有工程决策都是在裸奔。参考来源Enhancing Chat Language Models by Scaling High-quality Instructional Conversations (UltraChat)https://arxiv.org/abs/2305.14233Fin-LLM: 金融研报问答领域的长文本响应生成微调https://arxiv.org/abs/2109.01652FLAN: Scaling Instruction-Finetuned Language Modelshttps://arxiv.org/abs/2210.11416Wikipedia: Birthday problem组合碰撞与唯一率公式https://en.wikipedia.org/wiki/Birthday_problemPyTorch 文档: torch.utils.data.WeightedRandomSampler配比采样的生产实现https://pytorch.org/docs/stable/data.html
返回列表