下一个词最可能是什么:手写一个 Bigram 语言模型
下一个词最可能是什么:手写一个 Bigram 语言模型
你每天都在用语言模型
你在 IDE 里敲下 res 三个字母,补全列表已经弹出 response_body、response_time 两个候选。你按下 Tab,整行补完。这个动作背后没有魔法,编辑器只做了一件事:估算在当前上下文之后,下一个词最可能是什么。把这件事做成一个可以训练、可以查询的模型,就是语言模型的全部工作。
本文不从公式出发。我们从一份只有两句话、六个词的语料库开始,亲手把大模型的统计学祖先造一遍:数次数、做除法、填一张表。走完这一程,你会清楚三件事:语言模型算的到底是哪个概率;为什么数次数这种朴素操作是正经的统计估计而不是经验口诀;以及这张表天生带什么缺陷,逼出了后续所有的平滑技巧乃至神经网络。
阅读门槛只有会写循环和会查表。文中会出现公式,但每个公式都先落在代码或直觉上,再出现符号。
把预测写成一张表
把预测下一个词写成程序需求:输入已经出现的词,输出下一个词的概率分布。最诚实的实现是一张哈希表,键是完整前文,值是各后继词的计数。麻烦在于键的空间随前文长度指数膨胀,真实语料填不满它的零头,绝大多数查询永远 miss。一张几乎查不到的表,等于没有表。
统计语言模型的出路是主动丢信息:不看完整前文,只看最近一个词。我们把用来做依据的前一个词叫前驱词,把要预测的那个词叫后继词。只靠前驱词预测后继词的模型就是 Bigram,键缩短成一个词,表的大小降到词汇量级别,一次遍历语料就能填完。代价是模型变健忘,决定后继词的只有紧邻的前驱词,更远的上下文一律无视。本文全程使用 Bigram,因为它小到可以手算,又完整保留了这套方法的全部优点与全部缺陷。
截断历史之后,句子概率可以拆成连乘:整句概率等于逐词条件概率的乘积,每个条件概率只询问前一个词。下一节我们就把这套连乘套到一个六词语料上,亲手算一遍。
手算一遍:六词语料上的 Bigram
理论说完,直接上手。假设语料库只有两句话:
datawhale agent learns
datawhale agent works
现在要计算新句子 datawhale agent learns 出现的概率。按 Bigram 假设,它拆成三个因子相乘: