前馈神经网络语言模型
N-gram 的稀疏灾难是怎么被绕开的?
N-gram 的死穴:没见过就不会
上两课我们有了两样东西:第 14 课的 N-gram,靠「数数」预测下一个词;第 15 课的词向量,把每个词变成一串能比较远近的数字。 这一课,我们把它们拼到一起——但先要看清,单靠 N-gram 会栽在哪。
N-gram 的做法是查历史统计:要预测下一个词,就看前面 N−1 个词,找它们后面历史上最常跟着的那个词。我们用 N=3,试试这句:
要查的是:「围绕黑洞运转」后面最常出现什么词?于是我们翻遍训练语料,去数这个短语后面跟过的词—— 结果是个尴尬的数字:0 次。「黑洞」本就是个冷僻的专业词,「围绕黑洞运转的」这个完整组合,普通文本里压根没出现过。
查不到统计,N-gram 只能回退:砍掉前文,只看「运转的 ___」,甚至只看「的 ___」。 可「的」后面最常见的是「人」「树」「东西」这种万金油词——于是它一本正经地补出 「围绕黑洞运转的树」。
病根在于:N-gram 眼里每个词都是一个孤立的符号。它不知道「黑洞」和「恒星」有任何关系—— 哪怕语料里「围绕恒星运转的行星」出现过一万次,对「围绕黑洞运转」这条空白记录也一点忙都帮不上。 它只会照搬见过的,对没见过的组合毫无推断能力。
第一步:把上下文词翻译成数字
2003 年,研究员 Bengio 想到的办法朴素得惊人,就三步:
- 查向量:把最近的 N 个词,各自换成它的词向量(一串数字);
- 拼起来:把这几串数字首尾相接,拼成一长串,作为神经网络的输入;
- 过网络:送进一个神经网络,输出词表里每个词「该是下一个词」的概率。
关键的转折就在第 1 步:神经网络的输入从今往后是数字,不再是符号。 这一步看似平平无奇,却正是举一反三的全部秘密所在——下一站会把它算给你看。
先看整体长什么样。真实的模型里每个词向量上百维、上下文好几个词,画不下;下面这张是它的骨架:
图里那个橙色「神经网络」方块不是新东西,而是卷二一整套积木的组合: 过 Wx + b 加激活函数(第 7、8 课),最后用 Softmax 把输出压成「每个词的概率」(第 11 课)。 训练也照搬卷二:真实的下一个词就是标准答案,用交叉熵算预测有多离谱(第 10 课), 再靠反向传播把误差摊回每个权重、连同词向量一起微调(第 13 课)。
手算一遍:数字是怎么流过网络的
骨架看懂了,可「过网络」三个字还是个黑箱。我们把它缩到能手算的尺寸,真刀真枪走一遍。 为了算得清楚,做三处简化(道理和满血版一模一样):
- 上下文只取 2 个词:「围绕」+ 一个待定的词(先用「恒星」);
- 每个词向量只要 2 维。第 1 维我们叫它「天文性」(越大越像天文词),第 2 维是别的语义;
- 候选的下一个词只留 2 个:「行星」和「雨伞」。
查表,得到两个词向量,把它们拼成一串 4 个数的输入:
拼接后的输入 = [0.10, 0.20, 0.90, 0.15]
网络的隐藏层放一个神经元,专门当「天文语境探测器」:它只盯着待定词的「天文性」那一维, 做的还是第 7、8 课那套 (权重 1.5、偏置 −0.8,激活用 tanh):
再接输出层:天文味越浓(h 越大),就越该接「行星」。我们让「行星」的分数 = , 「雨伞」的分数固定为 0,最后用第 11 课的 softmax 把两个分数挤成概率:
softmax:行星 = e1.25 / (e1.25+e0) = 3.49 / 4.49 ≈ 78%,雨伞 ≈ 22%
网络吐出:下一个词有 78% 是「行星」。一串数字,经过「拼接 → 一次加权 + tanh → softmax」, 就变成了一个有理有据的预测。下面这台就是这套缩小版机器,活的——它默认在算「围绕 + 恒星」,数字和上面完全对得上:
见证「举一反三」:把恒星换成黑洞
现在回到第 1 站那个把 N-gram 难住的词——黑洞。假设训练语料里「围绕黑洞」从没出现过, 但词向量那一课已经让「黑洞」的向量和「恒星」挨得极近。我们把上下文第二个词换成黑洞,同一台机器,重算一遍:
h = tanh(1.5×0.85 − 0.8) = tanh(0.475) ≈ 0.44 → 行星分 = 1.10 → 行星 ≈ 75%
78% vs 75%——几乎一模一样。道理很朴素:黑洞的向量和恒星只差一点点, 拼出来的输入就只差一点点,隐藏层是连续函数,输入差一点点、输出也只差一点点。 于是哪怕「围绕黑洞」这个组合网络从没见过,它照样稳稳预测「行星」。这正是 N-gram 怎么也做不到的举一反三。
把三个词排在一起对比,差别一目了然(在互动 16-A 里挨个点一遍,数字会和这张表对上):
和 N-gram 一起放在桌上比较
两者共有的硬伤:上下文窗口是固定大小的。N 通常只设 3~5, 因为窗口一变大,拼出来的输入就变长、网络也跟着变大,训练成本飙升,回报却越来越小。
可看这句:「那只从小被遗弃在废弃工厂里、因为长期挨饿而变得格外暴躁的流浪犬,今天终于被好心人收留了,它___」。 要填最后一个词,得读懂整段的情绪和故事——但 FFNN 只看得见最后 5 个词「它终于___」, 前面那一长串铺垫全被挡在窗口外面,完全不存在。
总结
FFNN 语言模型 = 词向量 + 神经网络。把最近 N 个词的向量拼成一长串, 送进全连接网络预测下一个词。关键进步:相近的词向量 → 相近的网络输入 → 相近的预测, 于是能对没见过的组合举一反三。遗留问题:上下文窗口仍是固定大小,看不到更远处。
这一课你亲手推导了
- N-gram 的死穴:词是孤立符号,没见过的组合 → 回退乱猜,「恒星」的统计借不给「黑洞」。
- 三步法:查向量 → 拼接 → 过网络(Wx+b、tanh、softmax,全是卷二的零件)。
- 手算一遍前向:[0.10,0.20,0.90,0.15] → h≈0.50 → 行星 78%。
- 举一反三:黑洞向量≈恒星 → 输入≈、输出≈(78% vs 75%),哪怕没见过这个组合。
- 新的局限:上下文窗口固定,超出 N 个词的信息完全丢失。
学习小测验
做完这一课,来检测一下核心知识点。选出你的答案后点击「提交」,即可看到正确选项与讲解。
循环神经网络 RNN
不再固定窗口——让网络每读一个词就更新一次「记忆」,理论上能记住整篇文章。