梯子出现之前
犹如生命的诞生之初,混沌而原始。在 word2vec 诞生之前,NLP 中并没有一个统一的方法去表示一段文本,各位前辈和大师们发明了许多的方法:从 one-hot 表示一个词到用 bag-of-words 来表示一段文本,从 k-shingles 把一段文本切分成一些文字片段,到汉语中用各种序列标注方法将文本按语义进行分割,从 tf-idf 中用频率的手段来表征词语的重要性,到 text-rank 中借鉴 page-rank 的方法来表征词语的权重,从基于 SVD 纯数学分解词文档矩阵的 LSA,到 pLSA 中用概率手段来表征文档形成过程并将词文档矩阵的求解结果赋予概率含义,再到 LDA 中引入两个共轭分布从而完美引入先验......
1. 语言模型
而以上这些都是相对比较传统的方法,在介绍基于深度学习的方法之前,先来看看语言模型。实际上,语言模型的本质是对一段自然语言的文本进行预测概率的大小,即如果文本用 Si 来表示,那么语言模型就是要求 P(Si) 的大小,如果按照大数定律中频率对于概率无限逼近的思想,求这个概率大小,自然要用这个文本在所有人类历史上产生过的所有文本集合中,先求这个文本的频率 P(Si) ,而后便可以通过如下公式来求得:
这个公式足够简单,但问题是全人类所有历史的语料这种统计显然无法实现,因此为了将这个不可能的统计任务变得可能,有人将文本不当做一个整体,而是把它拆散成一个个的词,通过每个词之间的概率关系,从而求得整个文本的概率大小。假定句子长度为 T,词用 x 表示,即:
然而,这个式子的计算依然过于复杂,我们一般都会引入马尔科夫假设:假定一个句子中的词只与它前面的 n 个词相关,特别地,当 n=1 的时候,句子的概率计算公式最为简洁:
并且把词频的统计用来估计这个语言模型中的条件概率,如下:
这样一来,语言模型的计算终于变得可行。然而,这种基于统计的语言模型却存在很多问题:
第一,很多情况下
的计算会遇到特别多零值,尤其在 n 取值较大时,这种数据稀疏导致的计算为 0 的现象变得特别严重。所以统计语言模型中一个很重要的方向便是设计各种平滑方法来处理这种情况。
第二, 另一个更为严重的问题是,基于统计的语言模型无法把 n 取得很大,一般来说在 3-gram 比较常见,再大的话,计算复杂度会指数上升。这个问题的存在导致统计语言模型无法建模语言中上下文较长的依赖关系。
第三,统计语言模型无法表征词语之间的相似性。
2. NNLM
这些缺点的存在,迫使 2003 年 Bengio 在他的经典论文 A Neural Probabilistic Language Model 中,首次将深度学习的思想融入到语言模型中,并发现将训练得到的 NNLM(Neural Net Language Model,神经网络语言模型)模型的第一层参数当做词的分布式表征时,能够很好地获取词语之间的相似度。
撇去正则化项,NNLM 的极大目标函数对数似然函数,其本质上是个 N-Gram 的语言模型,如下所示:
其中,归一化之前的概率大小(也就是 logits)为:
x 实际上就是将每个词映射为 m 维的向量,然后将这 n-1 个词的向量 concat 起来,组合成一个 (n-1)*m 维的向量。
这里可以将 NNLM 的网络结构拆分为三个部分:
- 第一部分,从词到词向量的映射,通过 C 矩阵完成映射,参数个数为 |V| * m;
- 第二部分,从 x 到隐藏层的映射,通过矩阵 H,这里的参数个数为 |H| * m * (n-1);
- 第三部分,从隐藏层到输出层的映射,通过矩阵 U,参数个数为 |V| * |H|;
- 第四部分,从 x 到输出层的映射,通过矩阵 W,参数个数为 |V| * m * (n-1)。
因此,如果算上偏置项的参数个数(其中输出层为 |V|,输入层到隐藏层为 |H|)的话,NNLM 的参数个数为:
可见 NNLM 的参数个数是所取窗口大小 n 的线性函数,这便可以让 NNLM 能对更长的依赖关系进行建模。不过 NNLM 的最主要贡献是非常有创见性地将模型的第一层特征映射矩阵当做词的分布式表示,从而可以将一个词表征为一个向量形式,这直接启发了后来的 word2vec 的工作。
这许多的方法和模型正如动荡的春秋战国,诸子百家群星闪耀,然而却也谁都未能有绝对的实力统一当时的学术界。即便到了秦始皇,虽武力空前强大,踏平六国,也有车同轨书同文的壮举,却依然未能把春秋以降的五彩缤纷的思想学术界统一起来。直到历史再历一百年,汉武帝终于完成了这个空前绝后的大手笔,“罢黜百家独尊儒术”,这也直接成为了华夏文化的核心基础。不禁要问,如果把 NNLM 当做文化统一前的“书同文”苗头,那 NLP 中的“独尊儒术”在哪里?