第一部分 · 预测下一个词

怎样用前几个词预测下一个词?

在大量文本里数一数哪些词常常连着出现,再用这些次数做预测。这就是 n-gram 模型的基本做法。

只看最近几个词,能不能预测下一个词? Lec 2 · Aug 27 · Lec 3 · Sep 1 回顾

假设刚刚读到的词是 want。一个简单的办法是:在训练文本里找出所有 want,数一数后面各接了什么词,再根据这些次数作预测。这样,模型就不必记住前面的整句话。

这就是 n 元语言模型(n-gram model)的基本思路。它运用马尔可夫假设,把注意力限制在一个包含 \(n\) 个词的窗口里。窗口包括当前要预测的词 \(w_i\),因此真正用作上下文的是前 \(n-1\) 个词。

一元模型(unigram):不看前文,独立预测每个词
\[ P(w_1 w_2 \ldots w_n) \approx \prod_i P(w_i) \]
二元模型(bigram):只看前一个词
\[ P(w_i \mid w_1 \ldots w_{i-1}) \approx P(w_i \mid w_{i-1}) \]
k 元模型:看前面的 k−1 个词
\[ P(w_i \mid w_1 \ldots w_{i-1}) \approx P(w_i \mid w_{i-k+1} \ldots w_{i-1}) \]

让模型实际生成一段文本,就能看出差别。一元模型虽然知道哪些词常见,但每次选词都不看之前选了什么。课件给出的例子如下:

多记住一个词,会有什么变化?

一元模型的结果:“fifth, an, of, futures, the, an, incorporated, a, a, the, inflation, most, dollars, quarter, in, is, mass”。每个词都认识,放在一起却没有句子的结构。

二元模型的结果:“texaco, rose, one, in, this, issue, is, pursuing, growth, in, a, boiler, house, said, mr., gurria, mexico, 's, motion, control, proposal, without, permission, from, five, hundred, fifty, five, yen”。相邻的词开始像正常搭配,但整段仍然缺少连贯的意思。

另一个较短的二元模型结果是 “this, would, be, a, record, november”。它说明几次合理的局部选择,有时就能凑出一句像样的话。

还可以继续增加记忆范围,使用三元模型(trigram)、四元模型、五元模型等。每增加一阶,就多看一个上下文词。

有些联系隔得太远,短窗口看不到

看这句话:“The computer which I had just put into the machine room on the fifth floor crashed.” 真正与动词 crashed 相联系的是前面的 computer,中间却隔了很多词。短窗口无法同时保留这两个位置。

句子结构有时还会把读者的第一印象带偏。课件列出了几个花园路径句(garden-path sentence):

  • “The complex houses married and single soldiers and their families.” 这里 complex 是建筑群,houses 是“容纳”的意思,并不是名词“房屋”。
  • “The horse raced past the barn fell.” 意思是那匹被赶着跑过谷仓的马倒下了;句尾的 fell 才是主句的谓语。
  • “The old man the boat.” 这里 the old 指老年人,man 是“操纵、值守”的意思。

这些例子说明,短窗口并不能完整描述语言。不过,在一些具体任务中,较小的 \(n\) 已经足以抓住有用的局部规律。

把相邻词的次数换成概率 Lec 2 · Aug 27

要估计一个词后面接另一个词的概率,先数出这对词出现了多少次,再除以前一个词作为上下文出现的次数。这就是最大似然估计:

这个上下文出现时,有多大比例接了目标词?
\[ P_{\text{MLE}}(w_i \mid w_{i-1}) = \frac{c(w_{i-1}\, w_i)}{c(w_{i-1})} \]

那么 \(i = 1\) 时怎么办?第一个词没有前一个词,我们就加一个特殊的句首标记 <s>。另外,再加句尾标记 </s>,让模型能够预测“这句话到这里结束”。这样,\(P(W)\) 就能描述不同长度的句子;若要让所有有限长度句子的概率加起来为一,还需要模型最终以概率一停下来。

用这三句 Dr. Seuss 文本练习计数
<s> I am Sam </s>
<s> Sam I am </s>
<s> I do not like green eggs and ham </s>

三句话中,两句以 I 开头,一句以 Sam 开头,因此 \(P(\text{I} \mid \text{<s>}) = \tfrac{2}{3}\),\(P(\text{Sam} \mid \text{<s>}) = \tfrac{1}{3}\)。

I 一共出现三次,其中两次后面接 am,所以 \(P(\text{am} \mid \text{I}) = \tfrac{2}{3}\)。剩下一次接 do,所以 \(P(\text{do} \mid \text{I}) = \tfrac{1}{3}\)。

Sam 出现两次,其中一次后面是句尾,因此 \(P(\text{</s>} \mid \text{Sam}) = \tfrac{1}{2}\)。Am 也出现两次,其中一次接 Sam,因此 \(P(\text{Sam} \mid \text{am}) = \tfrac{1}{2}\)。

把方法用到餐馆查询语料上 Lec 2 · Aug 27 · Lec 3 · Sep 1 回顾

Berkeley Restaurant Corpus 收集了 9,222 句餐馆查询。里面的问题包括:

  • “can you tell me about any good cantonese restaurants close by”
  • “mid priced thai food is what i'm looking for”
  • “tell me about chez panisse”
  • “i'm looking for a good place to eat breakfast”
  • “when is caffe venezia open during the day”

课件分三步演示:先数单个词,再数相邻词对,最后用词对次数除以上下文次数。课件选出的八个词,单词计数如下:

词iwanttoeatchinesefoodlunchspend
次数253392724177461581093341278

在相邻词对的计数表中,行表示前一个词 \(w_{i-1}\),列表示下一个词 \(w_i\)。其中一些格子的数值是:

词对次数词对次数词对次数
i want827want to608to eat686
chinese food82eat lunch42want chinese6
want food6eat to2lunch spend0

完整表格里的大多数格子都是零,因为大多数可能的词组从未出现在训练文本中。对于出现过的词对,除以行首词的计数就能得到概率。按课件保留小数后的数值,\(P(\text{want} \mid \text{i}) = 827/2533 = 0.33\),\(P(\text{to} \mid \text{want}) = 0.66\),\(P(\text{eat} \mid \text{to}) = 0.28\),\(P(\text{food} \mid \text{chinese}) = 0.52\)。

逐步相乘,得到整句话的概率

“i want english food”的计算过程

\(P(\text{<s> i want english food </s>}) = P(\text{i}\mid\text{<s>}) \, P(\text{want}\mid\text{i}) \, P(\text{english}\mid\text{want}) \, P(\text{food}\mid\text{english}) \, P(\text{</s>}\mid\text{food})\) \(= 0.25 \times 0.33 \times 0.0011 \times 0.5 \times 0.68 \approx 0.000031\)

这个乘积包括:以 i 开头、依次选出后面的词,以及在 food 后结束。最后得到的数很小很正常,因为概率需要分给大量可能的句子。

这些计数反映了什么?

模型只数了相邻的词,却已经抓住了几类规律:

  • 语料讨论的主题:\(P(\text{english} \mid \text{want}) = 0.0011\),而 \(P(\text{chinese} \mid \text{want}) = 0.0065\)。这批查询里,问中餐的人更多。
  • 语法搭配:\(P(\text{to} \mid \text{want}) = 0.66\),\(P(\text{eat} \mid \text{to}) = 0.28\),\(P(\text{food} \mid \text{to}) = 0\)。常见的语法搭配得到较高概率,但计数为零并不能单独证明某种搭配绝不可能出现。
  • 提问的表达习惯:\(P(\text{i} \mid \text{<s>}) = 0.25\)。这些查询经常以 “I” 开头,体现了简单的话语组织规律。

用对数计算,避免小概率变成零 Lec 2 · Aug 27

许多小概率连续相乘,结果可能小到超出计算机能够表示的范围,最终被舍入成零。这叫数值下溢(underflow)。解决办法是保存概率的对数,并把乘法改成加法:

\[ \log(p_1 \cdot p_2 \cdot p_3 \cdot p_4) = \log p_1 + \log p_2 + \log p_3 + \log p_4 \]
  • 原来的乘积即使极小,对数之和仍可以保持在可表示的数值范围内。
  • 预先得到对数概率后,计算句子分数只需要累加,不必反复相乘。课件也提到这种计算上的便利;最主要的好处仍是避免数值下溢。
本页要记住什么
  • 把链式法则与包含 \(n\) 个词的短窗口结合,就得到 n 元语言模型。每一步的概率用词组次数除以上下文次数来估计。
  • <s> 给首词提供上下文,</s> 让模型知道何时结束。
  • 相邻词对已经能反映主题、语法和提问习惯,但短窗口看不到远处的联系。
  • 实际计算使用对数概率。没见过的词组还需要额外处理,详见零计数带来的问题和平滑方法。