模板批量生成 72 条,看着不少——但只有 3 种句式,句法多样性 4.2%; 首字只有 7 种,长度全挤在 6 到 13 字。量造出来了,分布没造出来。
上一节讲从哪拿数据,这一节讲自己造。模板生成是最省事的办法,也是最容易把模型教坏的办法。
一、为什么需要自己造数据
公开数据集是「别人的业务」。你要做的是自家客服、自家图纸、自家话术,这些内容公开数据集里没有。 另一层原因是格式对齐:微调需要的是「指令—输入—输出」三元组,而手上的原始资料通常是文档、 聊天记录、工单。中间这一步转换只能自己做。 造数据有三条路,成本从低到高:模板拼装 → 大模型生成 → 人工标注。 三条路的差别不在量,在分布的多样性。 这一节重点讲第一条,因为它最容易被误用:它能造出量,造不出分布。而模型学的恰恰是分布。
二、模板生成能造出什么
Demo 用 3 个模板、6 个主语、4 个谓语,组合出 72 条。 去重后还是 72 条(组合没有重复),看着挺像样。 但换个角度看就露馅了:唯一句式只有 3 种,句法多样性 4.2%。也就是说, 这 72 条在语法结构上只教了模型三件事。 再看三项分布:长度挤在 6 到 13 字、标准差 2.09、首字只有 7 种。 真实用户不是这么问的。 有人打三个字(「能退吗」),有人贴一整段工单,有人开头是「那个」「麻烦问下」「在吗」。 这些形态模板造不出来,而它们占了真实流量的一大半。
三、相似度那一列说明了什么
两两比较 2556 对,用三元组重合度算相似:p10 和 p50 都是 0.000,p90 是 0.267。 p50 等于 0 不代表数据多样,只代表样本都很短——短句子的三元组集合小,碰不上几个重合的。 这一点要看清楚,否则会误读成「数据很分散」。 真正有信息的是 p90: 最像的那一成里,两条问题有 27% 的字面是重复的。重复的部分就是「的流程是」这种模板骨架。 模型在训练时反复看到同一个骨架,学到的是「看到这四个字就套模板」。 上线之后用户换个说法,这个触发条件就消失了,答案也就没了。
四、怎么把模板数据改成能用的
一句话:拿它当骨架,人工把它改脏。 加错别字(「退换或」)、加口语(「那个退货咋弄啊」)、加一半截断的话(「我想问下退货……」)、 加方言词(「咋整」)。 这些「不完美」不是噪声,它们就是真实分布本身。模型需要学会的是「在表达不完整、 不规范的情况下也能理解意图」。 还有两个更省力的做法:一是用大模型改写模板句(换个说法、换语气、换长度), 二是从真实日志里挖——客服记录、工单、聊天记录,里面全是最真实的问法。 最后一条判断标准:抽 20 条出来,遮住答案,你自己能不能一眼看出是模板造的?能看出来, 就说明还不够脏。
五、动手 Demo:72 条里只有 3 种句式、7 种开头、长度全在 6 到 13 字
用 3 个模板、6 个主语、4 个谓语批量组合出指令数据,然后量四件事:句法多样性、长度分布、首字种类、 两两之间的三元组重合度。
subj = [u'退货', u'换货', u'发票', u'运费', u'保修', u'安装']
verb = [u'怎么申请', u'要多久', u'需要什么材料', u'收费吗']
tmpl = [u'%s%s?', u'请问%s%s', u'%s的流程是%s吗']
gen = [t % (a, b) for a in subj for b in verb for t in tmpl]
uniq = sorted(set(gen))
print(len(gen), len(uniq), len(tmpl) / float(len(uniq)))
# 三元组重合度:看这批数据彼此像不像
def grams(s, k=3):
return set(s[i:i+k] for i in range(len(s) - k + 1))
实跑输出:
--------------------------------------------------------------------
生成微调数据集:模板能造量,造不出多样性
--------------------------------------------------------------------
用 3 个模板、6 个主语、4 个谓语批量生成:
生成条数 72 条
去重后 72 条
唯一句式 3 种(模板数)
句法多样性 4.2%
长度 区间 6 ~ 13 字
长度 标准差 2.09
首字种类 7 种
最后两行才是问题所在:**长度集中在一个很窄的区间,首字只有 7 种。**
真实用户不是这么问的:有人打三个字,有人贴一整段,有人开头是「那个」「麻烦问下」「在吗」。
再看这 72 条彼此像不像(三元组重合度):
两两比较对数 2556 对
相似度 p10 0.000
相似度 p50 0.000
相似度 p90 0.267
**p90 到了 0.27 意味着:最像的那一成里,两条问题有 27% 的字面是重复的。**
模型在训练时反复看到「的流程是」,就会学成「一看到这四个字就套模板」。
所以模板生成的正确用法只有一条:
**拿它当骨架,人工把它改脏。**
加错别字、加口语、加一半截断的话、加方言词——这些「不完美」才是真实分布。
直接拿模板产出去微调,模型会学成「只会答标准问法」,上线之后用户随便换个说法就崩。
第一组数:生成 72 条、去重后 72 条、唯一句式 3 种、句法多样性 4.2%。 去重一条都没删掉,说明重复的不是文本,是结构。 第二组:长度 6 到 13 字、标准差 2.09、首字 7 种(6 个主语加「请」)。 这两项最能说明问题——分布的形状完全不对。 第三组:两两比较 2556 对,p10 和 p50 都是 0.000,p90 是 0.267。 p50 为 0 是因为句子短,不代表分散;p90 那 0.27 才是真正的重复。 这三组数合起来就是一句结论:模板能把「条数」做上去, 把「句式」「长度」「开头」全钉死在一个很窄的范围里。 要诚实说明:这里的相似度是字三元组的重合率,没有语义。 真实的多样性评估会看「同一意图有几种表达」,那需要人工抽样或者用嵌入模型, 沙箱里两个都没有。但它给出的方向是对的:模板数据的分布,一眼就能看出是模板。
30 秒实验
- 把模板从 3 个加到 20 个,再跑一遍,看句法多样性涨到多少。 涨上去的是句式,长度和首字还是那么窄。
- 手工添 12 条「脏样本」(带错别字、口语、截断),重算长度标准差和首字种类,看分布有没有被拉开。
- 把某个主语的出现次数改成别的 5 倍(模拟业务偏斜),看类别分布怎么变,以及模型会偏向哪一类。
常见误区
- 「模板生成就是数据增强」。增强是在原有的多样性上加变化,模板生成是从零造出一个很窄的分布。 它加的是量,不是多样性。
- 「相似度 p50 是 0 说明数据很分散」。短句子的三元组集合小,碰不上几个重合的。 看 p90 才有信息。
- 「数据越多模型越好」。模板造出来的数据量再大,教的还是那 3 种句式。量变不引起质变。
自测三问(点开对答案)
1. 为什么说模板生成「造得出量,造不出分布」? —— 因为模板固定了句法结构。 72 条只有 3 种句式、7 种开头、长度挤在 6 到 13 字,而真实用户的问法在句式、长度、 开头三个维度上都散得多。 2. 三元组相似度的 p50 是 0,为什么不能说明数据多样化? —— 因为样本都很短,三元组集合小,本来就不容易重合。 要看 p90——最像的那一成里重复度是多少,那才反映「有没有大量同构样本」。 3. 怎么判断一批生成数据够不够用? —— 抽 20 条出来遮住答案,看能不能一眼认出是模板造的。 能认出来就说明分布太窄,需要加口语、错别字、截断、方言这些「不完美」。数据准备好了,接下来要有个地方把它存起来、切块、检索。下一节装那个「知识库外壳」。
- ☐ (本节完,下一节 3.2.1 下载并安装AnythingLLM)