🧠 第三章 数据获取:构建AI模型的知识库
📄 一句话概括

模板批量生成 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 秒实验

  1. 把模板从 3 个加到 20 个,再跑一遍,看句法多样性涨到多少。 涨上去的是句式,长度和首字还是那么窄。
  2. 手工添 12 条「脏样本」(带错别字、口语、截断),重算长度标准差和首字种类,看分布有没有被拉开。
  3. 把某个主语的出现次数改成别的 5 倍(模拟业务偏斜),看类别分布怎么变,以及模型会偏向哪一类。

常见误区

  1. 「模板生成就是数据增强」。增强是在原有的多样性上加变化,模板生成是从零造出一个很窄的分布。 它加的是量,不是多样性。
  2. 「相似度 p50 是 0 说明数据很分散」。短句子的三元组集合小,碰不上几个重合的。 看 p90 才有信息。
  3. 「数据越多模型越好」。模板造出来的数据量再大,教的还是那 3 种句式。量变不引起质变。
自测三问(点开对答案) 1. 为什么说模板生成「造得出量,造不出分布」? —— 因为模板固定了句法结构。 72 条只有 3 种句式、7 种开头、长度挤在 6 到 13 字,而真实用户的问法在句式、长度、 开头三个维度上都散得多。 2. 三元组相似度的 p50 是 0,为什么不能说明数据多样化? —— 因为样本都很短,三元组集合小,本来就不容易重合。 要看 p90——最像的那一成里重复度是多少,那才反映「有没有大量同构样本」。 3. 怎么判断一批生成数据够不够用? —— 抽 20 条出来遮住答案,看能不能一眼认出是模板造的。 能认出来就说明分布太窄,需要加口语、错别字、截断、方言这些「不完美」。

数据准备好了,接下来要有个地方把它存起来、切块、检索。下一节装那个「知识库外壳」。

相关笔记