🦙 第7章 多语言大模型技术介绍及其工业应用
📄 一句话概括

多语言的语料分布极度倾斜:一种语言占八成,最后几种加起来不到千分之一。 按自然分布训练,稀有语言一个月也轮不到一次。 这一节算三笔账:自然分布下每步能见到什么、温度采样能把它抬多高、以及「想让一种语言每步都出现, 至少需要多少语料」。

📝 本章和前面几章的关系

上一节说清了「词表为什么倾斜」,这一节说「语料为什么倾斜」——两者是同一个原因的两种表现。 数据清洗的一般流程在 5.2 节讲过;这一节只关注多语言特有的那一层:清洗规则本身会误杀长尾语言。

一、语料从哪来:四类源,四种偏差

第一类是网页抓取。量最大,覆盖最广,也最脏。它天然偏向有大量网页的语言——英语、中文、西班牙语。 第二类是百科与新闻。质量高,但只有几十种语言有像样的规模,而且都是书面语,跟口语差得远。 第三类是宗教与法律文本。 很多小语种唯一的成规模语料就是这类,语体古老、句式固定,训出来的模型说起话来像经文。

第四类是平行语料,也就是同一句话的多个语言版本。 它对翻译任务最有用,但量小,而且只覆盖被翻译过的内容——会议记录、产品说明、字幕。 四类源的共同偏差是:谁在网上写得多,谁的语料就多。这不是技术问题,是现实分布。

二、分布有多斜:一个 batch 能见到谁

演示里八种语言、四亿五千万句。英语一家占 79.9%,排最后的僧伽罗语只占 0.02%。 把这个比例换成一个 1024 句的 batch:英语能占 818 句,僧伽罗语 0.18 句。 0.18 句的意思是,平均五个 batch 才轮到它一次。 训练一个月,几百万步,它只被看了几十万分之一的时间。这就是「语料里有它,模型却不会它」的算术解释。

更极端的情况是「一步都轮不到」。 真实语料里,有一千多种语言的总量加起来不到百万句——按自然分布,它们在训练里等于不存在。

三、温度采样:把长尾抬起来,代价是稀释高资源

做法很朴素:把每种语言的采样权重从「语料量」改成「语料量的 α 次方」,再归一化。 α 等于 1 就是自然分布,α 越小,各语言被拉得越平。 演示里 α 从 1 降到 0.3,僧伽罗语从 0.02% 涨到 2.7%,提了一百五十倍;英语从 79.9% 掉到 33.3%。 所以 α 不是一个「越大越好」或「越小越好」的参数,它是在两种损失之间选:α 大,长尾学不会; α 小,高资源的语感被摊薄。

文献里管后者叫多语言的诅咒:语言数越多,每种语言能分到的模型容量越少,最后所有语言都变成半吊子。 实践里的折中是分两段:主体训练用接近 1 的 α 保住高资源的质量,最后一段用低 α 把长尾过一遍。 先学扎实,再补覆盖。

四、反推:想让一种语言每步都出现,至少要多少语料

这个反推很好用。batch 是 1024 句,要让某种语言平均出现 1 次,它的占比至少是千分之一。 演示里总语料四亿五千万句,千分之一就是四十四万句。 八种语言里有两种达不到——斯瓦希里语三十万,僧伽罗语八万。 这两句数的意义在于:它们不是「少」,是「不够」。不够到无论怎么调采样,模型都学不出稳定的语法。

这也解释了为什么小语种的模型往往「词对、句子不对」——它记住了词汇表,但没见过足够多的句子来学语序。 所以真正改变小语种效果的只有一件事:把语料量提上去。 采样、词表、模型结构都是在这之后才有意义的优化。

五、评测任务:评测集也在倾斜

常见的跨语言评测有几种:自然语言推理、跨语言问答、阅读理解、翻译质量。 它们覆盖的语言从七种到两百种不等,覆盖越广的,每种语言里的题越少。 这里有个隐蔽的坑:评测集也是人做的,也偏向高资源语言。一个覆盖两百种语言的翻译评测集, 每种语言可能只有一两千句,而且大多是从英语翻译过去的。 从英语翻过去的测试句,句式、用词、话题都带着英语的痕迹。 模型在这些题上分数高,不代表它能处理这种语言的原生表达。

所以看多语言评测要看三件事:覆盖多少语言、每种语言多少题、这些题是原生写的还是从英语翻的。 只看总分的排行榜,说明不了什么。

六、动手 Demo:八种语言的自然分布,和温度采样怎么改它

造一份八种语言的语料统计,量级参照公开的多语语料库:英语一家独大,中文第二, 后面迅速掉到千分之一以下。 算四件事:自然分布下每个 batch 能见到谁、温度采样怎么改、以及「每步都出现」至少需要多少语料。

CORPUS = [(u'英语', 36000), (u'中文', 6000), (u'日语', 1200),
          (u'阿拉伯语', 900), (u'斯瓦希里语', 30), (u'僧伽罗语', 8)]
BATCH = 1024

def share(alpha):            # p 正比于 n 的 alpha 次方
    w = [float(n) ** alpha for _, n in CORPUS]
    s = sum(w)
    return [x / s for x in w]

for a in (1.0, 0.7, 0.5, 0.3):
    print(a, [round(p * 100, 2) for p in share(a)])

实跑输出:

--------------------------------------------------------------------
八种语言的自然分布,和温度采样怎么改它
--------------------------------------------------------------------


  ① 语料分布:真实世界是极度倾斜的
  --------------------------------------------------------------------
| 语言 | 语料(万句) | 自然占比 | 每 1024 句出现 |
|---|---:|---:|---:|
| 英语 | 36000 | 79.93% | 818.51 |
| 中文 | 6000 | 13.32% | 136.42 |
| 日语 | 1200 | 2.66% | 27.28 |
| 阿拉伯语 | 900 | 2.00% | 20.46 |
| 越南语 | 600 | 1.33% | 13.64 |
| 泰语 | 300 | 0.67% | 6.82 |
| 斯瓦希里语 | 30 | 0.07% | 0.68 |
| 僧伽罗语 | 8 | 0.02% | 0.18 |

  合计 45038 万句。英语一家占 79.9%,最后两种加起来不到千分之一。
  ! 最后一列最直观:僧伽罗语平均要 5 个 batch 才轮到一次。训练一个月,它等于没参与。

  ② 温度采样:把长尾抬起来
  --------------------------------------------------------------------
| 语言 | α=1.0 | α=0.7 | α=0.5 | α=0.3 |
|---|---:|---:|---:|---:|
| 英语 | 79.93% | 64.30% | 49.67% | 33.27% |
| 中文 | 13.32% | 18.35% | 20.28% | 19.44% |
| 日语 | 2.66% | 5.95% | 9.07% | 11.99% |
| 阿拉伯语 | 2.00% | 4.86% | 7.85% | 11.00% |
| 越南语 | 1.33% | 3.66% | 6.41% | 9.74% |
| 泰语 | 0.67% | 2.25% | 4.53% | 7.91% |
| 斯瓦希里语 | 0.07% | 0.45% | 1.43% | 3.97% |
| 僧伽罗语 | 0.02% | 0.18% | 0.74% | 2.67% |

  α 是温度。α=1 就是自然分布;α 越小,各语言被拉得越平。
  ! 看两个极值:僧伽罗语从 0.018% 涨到 2.7%,提了 150 倍;英语从 79.9% 掉到 33.3%。
  这不是免费的——抬长尾的代价就是稀释高资源。

  ③ 一个 batch 里出现几次
  --------------------------------------------------------------------
| 语言 | α=1.0 | α=0.3 |
|---|---:|---:|
| 英语 | 818.51 | 340.73 |
| 中文 | 136.42 | 199.05 |
| 日语 | 27.28 | 122.82 |
| 阿拉伯语 | 20.46 | 112.67 |
| 越南语 | 13.64 | 99.76 |
| 泰语 | 6.82 | 81.03 |
| 斯瓦希里语 | 0.68 | 40.61 |
| 僧伽罗语 | 0.18 | 27.32 |

  ! α=0.3 时每种语言在 1024 句的 batch 里至少出现 27.3 次——这才叫「每步都在学」。
  α=1 时最后两种连一次都凑不齐。

  ④ 反推:想让某语言每步都出现,至少要多少语料
  --------------------------------------------------------------------
  自然采样下,要让一种语言平均每个 batch 出现 1 次,它至少要有 44 万句——也就是占全语料的千分之一。
| 语言 | 语料(万句) | 自然采样够不够 |
|---|---:|:---:|
| 英语 | 36000 | 够 |
| 中文 | 6000 | 够 |
| 日语 | 1200 | 够 |
| 阿拉伯语 | 900 | 够 |
| 越南语 | 600 | 够 |
| 泰语 | 300 | 够 |
| 斯瓦希里语 | 30 | 不够 |
| 僧伽罗语 | 8 | 不够 |

  ! 八种里有 2 种不够。这就是为什么语料少的小语种只能靠温度采样,不能靠「多收点数据」——收不到。
  ! 但温度也不能一路调低。
  α 太小,模型把所有语言都学成半吊子,高资源语言的语感反而退化——文献里管这个叫多语言的诅咒。
  ! 实际做法是分两段:主体训练用 α 接近 1,保住高资源的质量;
  最后一段用低 α 补长尾,让稀有语言也过一遍。

①先看这张分布表。英语 79.9%,中文 13.3%,两种加起来就九成三。最后两种加起来不到千分之一。 最后一列最直观:僧伽罗语每个 batch 平均出现 0.18 次。这不是「少」,这是「几乎不出现」。 ②温度采样那一栏,α=0.3 时僧伽罗语从 0.02% 涨到 2.7%,提了一百五十倍。看着很成功。 但同一行往上看:英语从 79.9% 掉到 33.3%。抬长尾的钱是从高资源身上收的。 ③换成「每个 batch 出现几次」更直观。α=0.3 时每种语言至少 27 次,这才叫「每步都在学」; α=1 时最后两种连一次都凑不齐。 ④这一格是全节最硬的结论:要让一种语言在每个 batch 平均出现一次,它至少要占全语料的千分之一, 也就是四十四万句。 八种里两种达不到。斯瓦希里语三十万句,差一点;僧伽罗语八万句,差五倍多。 而这还只是「每步出现一次」。要学会一门语言的语法,一次远远不够。 所以「小语种效果差」不是模型不努力,是它在训练里露面的次数太少。 这个结论可以一路推到底:先加语料,再谈优化。 最后一组提示是说不要矫枉过正:α 一路调低,所有语言都变成半吊子。分两段训练是常见的折中。

30 秒实验

  1. 把斯瓦希里语的语料从 30 万句改成 300 万句,重跑第 ① 步和 ④ 步。它的自然占比够千分之一了吗?
  2. 把 batch 从 1024 改成 256,重跑第 ④ 步的门槛。门槛变高还是变低?为什么?
  3. 假设你只想让五种语言「每步都出现」,需要把总语料砍到多少?砍掉的那些语料,损失的是什么?

常见误区

  1. 以为语料库里「有」这种语言就等于能学会。有八万句和没有,在训练里的区别约等于零。
  2. 把 α 调到很低,一劳永逸。低 α 会摊薄高资源,最后所有语言都变成「能说但说不地道」。
  3. 只看多语言排行榜的总分。 总分由高资源语言撑起来,长尾语言的分数被平均掉了——要看分语言的明细,不看总分。
  4. 拿从英语翻译过去的测试集当「原生能力」。 翻译过来的题带着英语的句式和话题,分数高不代表能处理原生表达。
自测三问(点开对答案) 1. 一个 batch 是 1024 句,某种语言每 batch 平均出现 0.2 次,说明什么? —— 说明平均五个 batch 才见到它一次。 按步数算,它只参与了百分之二十的训练——这个量级下,模型能记住它的词,学不到它的语法。 2. 温度采样为什么不能一路把 α 调低? —— 因为它是零和的:抬长尾的权重,就从高资源身上扣。 α 太低,高资源语言的语感被摊薄,而模型的主要能力恰恰来自它们。 最后是「什么都会一点,什么都不地道」。 3. 为什么说「看多语言评测的总分说明不了什么」? —— 因为题量按语言分布,高资源语言占大头,总分自然被它们撑起来。 长尾语言可能只有一两千道题,而且很多是从英语翻的,测不出原生能力。要看分语言明细。

料和评测都看清了,下一节进技术细节:数据怎么洗、词表怎么训、采样怎么落地。 这一节是本章最硬的一节,全部真跑。

相关笔记