语言模型通俗的将就是判断一句话是不是正常人说出来的。统计语言模型是所有 NLP的基础,被广泛应用与语音识别、机器翻译、分词、词性标注和信息检索等任务。传统的统计语言模型是表示语言基本单位(一般为句子)的概率分布函数,这个概率分布也是该语言的生成模型。通俗的讲,如果一句话没有在语料库中出现,可以模拟句子的生成的方式,生成句子在语料库中的概率。一般语言模型可以使用各个词语条件概率的形式表示:
p ( w 1 n ) = p ( w 1 , w 2 , … , w n ) = ∏ i = 1 n p ( w i ∣ C o n t e x t ) p(w_1^n) = p(w_1,w_2,\ldots,w_n) = \prod_{i=1}^n p(w_i|Context) p(w1n)=p(w1,w2,…,wn)=i=1∏np(wi∣Context)
其中,Context 为 w_i 的上下文表示。根据 Context 的表示差异,统计语言模型又可以分为不同的类别,其中最具代表性的有 n-gram 语言模型及 nn 语言模型
通常在 NLP 中,人们基于一定的语料库,可以利用 N-gram 来做以下几类事情:
统计语言模型实际上是一个概率模型,所以常见的概率模型都可以用于求解这些参数常见的概率模型有:N-gram 模型、决策树、最大熵模型、隐马尔可夫模型、条件随机场、神经网络等
目前常用于语言模型的是 N-gram 模型和神经语言模型
概率模型的缺陷: 观察如下句子 我-今天-要-去-学NLP
将其表示为概率模型
p ( S ) = p ( w 1 , w 2 , … , w n ) = p ( w 1 ) p ( w 2 ∣ w 1 ) p ( w 3 ∣ w 1 , w 2 ) … p ( w n ∣ w 1 , … , w n − 1 ) p(S) = p(w_1,w_2,\ldots,w_n) = p(w_1)p(w_2|w_1)p(w_3|w_1,w_2)\ldots p(w_n|w_1,\ldots,w_{n-1}) p(S)=p(w1,w2,…,wn)=p(w1)p(w2∣w1)p(w3∣w1,w2)…p(wn∣w1,…,wn−1)
而条件概率
p ( w i ∣ w 1 , w 2 , … , w i − 1 ) = p ( w 1 , w 2 , … , w i ) p ( w 1 , w 2 , … , w i − 1 ) p(w_i|w_1,w_2,\ldots,w_{i-1}) = \frac{p(w_1,w_2,\ldots,w_i)}{p(w_1,w_2,\ldots,w_{i-1})} p(wi∣w1,w2,…,wi−1)=p(w1,w2,…,wi−1)p(w1,w2,…,wi)
由于要计算 w i w_i wi 出现的概率,就要去统计前 i − 1 i-1 i−1 词出现的情况,假设词库中有 n n n 个词,就有
n ( i − 1 ) n^(i-1) n(i−1)种可能,这样每增加一个单词,模型的计算成本都指数倍的增长。
总的来说,概率模型的缺陷就是
为了减少计算成本, 增加了马尔科夫假设
基于马尔可夫假设,N-gram 语言模型认为一个词出现的概率只与它前面的 n-1 个词相关,假设下一个词的出现依赖它前面的一个词:
p ( S ) = p ( w 1 , w 2 , … , w n ) = p ( w 1 ) p ( w 2 ∣ w 1 ) p ( w 3 ∣ w 2 ) … p ( w n ∣ w n − 1 ) p(S) = p(w_1,w_2,\ldots,w_n) = p(w_1)p(w_2|w_1)p(w_3|w_2)\ldots p(w_n|w_{n-1}) p(S)=p(w1,w2,…,wn)=p(w1)p(w2∣w1)p(w3∣w2)…p(wn∣wn−1)
通常情况下,我们管这样的叫 n-gram 模型
理论上,n 越大越好,但在经验上看,trigram 用的最多,尽管如此,原则上,能用 bigram 解决,绝不使用 trigram。
早期因为计算性能的限制,一般最大取到 n=4;如今,即使 n>10 也没有问题,但是,随着 n 的增大,模型的性能增大却不显著,这里涉及了可靠性与可区别性的问题参数越多,模型的可区别性越好,但是可靠性却在下降——因为语料的规模是有限的,导致 count(W) 的实例数量不够,从而降低了可靠性
一元单词分布表
词 | i | want | to | eat | chinese | food | lunch | spend |
---|---|---|---|---|---|---|---|---|
频率 | 2533 | 927 | 2417 | 746 | 158 | 1093 | 341 | 278 |
二元单词分布表
词 | i | want | to | eat | chinese | food | lunch | spend |
---|---|---|---|---|---|---|---|---|
i | 5 | 827 | 0 | 9 | 0 | 0 | 0 | 2 |
want | 2 | 0 | 608 | 1 | 6 | 6 | 5 | 1 |
to | 2 | 0 | 4 | 686 | 2 | 0 | 6 | 211 |
eat | 0 | 0 | 2 | 0 | 16 | 2 | 42 | 0 |
chinese | 1 | 0 | 0 | 0 | 0 | 82 | 1 | 0 |
food | 15 | 0 | 15 | 0 | 1 | 4 | 0 | 0 |
lunch | 2 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
spend | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
第一行、第二列表示给定前一个词为i
的时候,当前词的want
的情况一共出现了827次
进而可以得出频率分布表
以i want
为例,其频率值为 p ( w a n t ∣ i ) = n ( i , w a n t ) n ( i ) = 827 2533 = 0.3265 p(want|i) = \frac{n(i,want)}{n(i)} = \frac{827}{2533} = 0.3265 p(want∣i)=n(i)n(i,want)=2533827=0.3265, 以频率作为概率那么进而也能得到一句话的概率,以I want chinese food
为例
P ( I w a n t c h i n e s e f o o d ) = P ( w a n t ∣ I ) P ( c h i n e s e ∣ w a n t ) P ( f o o d ∣ c h i n e s e ) P(I\quad want\quad chinese\quad food) = P(want|I)P(chinese|want)P(food|chinese) P(Iwantchinesefood)=P(want∣I)P(chinese∣want)P(food∣chinese)
观察上表,出现了很多零,这就是稀疏问题,当一句话中,包含了其中为0的一个条件概率,那么连乘的结果就为0
OOV 即 Out Of Vocabulary,也就是序列中出现了词表外词,或称为未登录词或者说在测试集和验证集上出现了训练集中没有过的词
一般解决方案:
该语言模型只看当前词的前 n-1 个词对当前词的影响。所有该模型的优势为:
该模型也有很多缺陷:
NPLM说的是: 只要你给我一个词,给我上下文,我就能计算出这个词在给定上下文下的条件概率
P ( w ∣ c o n t e x t ( w ) ) = g ( i w , V c o n t e x t ) P(w|context(w)) = g(i_w,V_{context}) P(w∣context(w))=g(iw,Vcontext)
这是一个经典的神经概率语言模型,它沿用了 N-gram 模型中的思路,将 w w w 的前 n − 1 n-1 n−1 个
词作为 w w w 的上下文 c o n t e x t ( w ) context(w) context(w),而 V c o n t e x t V_{context} Vcontext 由这 n − 1 n-1 n−1 个词的词向量拼接而成,即
P ( w k ∣ w k − n − 1 k − 1 ) = g ( i w k , [ C ( w k − n + 1 ) , … , C ( w k − 1 ) ] ) P(w_k|w_{k-n-1}^{k-1}) = g(i_{w_k},[C(w_{k-n+1}),\ldots,C(w_{k-1})]) P(wk∣wk−n−1k−1)=g(iwk,[C(wk−n+1),…,C(wk−1)])
其中 m , n , h m,n,h m,n,h为超参数,视训练集规模而定,也可以人为设置阈值
单词之间的相似性可以通过词向量来体现
( t h e c a t s a t o n t h e m a t ) = ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 ) \begin{pmatrix} the \\ cat \\ sat \\ on \\ the \\ mat \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 \\ \end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛thecatsatonthemat⎠⎟⎟⎟⎟⎟⎟⎞=⎝⎜⎜⎜⎜⎜⎜⎛100010010000001000000100000001⎠⎟⎟⎟⎟⎟⎟⎞
计算机是无法直接处理文本信息的,所以,在我们构建神经网络之前,要对文本进行一定的处理。
虽然one-hot编码可以构建词向量,但是表示文本的矩阵会非常的稀疏,极大得浪费了空间,而且这样一个矩阵放入神经网络训练也会耗费相当多的时间(而且还可能不收敛)。
为此,提出了词向量模型(Word2Vec)。词向量模型是一种将词的语义映射到向量空间的技术,说白了就是用向量来表示词,但是会比用独热编码用的空间小,而且词与词之间可以通过计算余弦相似度来看两个词的语义是否相近,显然 King 和 Man 两个单词语义更加接近,而且通过实验我们知道 King-Man+Woman=Queen
Distributed representation:通过训练将每一个词都映射为一个 K 维的浮点数向量
而W矩阵也叫做look up table(因为第k单词的词向量就是W矩阵第k行的向量),用one hot的词向量与W相乘得到稠密的词向量通常称为Word embedding
注意
这里的hidden layer只是像隐藏层,但是不是真正的隐藏层,因为没有激活函数
Continuous Bag-of-Word Model(连续词袋模型)和 skip-gram model(跳字模型),分别对应了词向量的两种训练方法:利用 context 预测中心词以及利用中心词去预测context。对于连续词袋模型(CBOW)来说,一般的做法是先对每个单词进行 one-of-N编码(one-hot encoded),作为训练网络的输入,接着构建一层 hidden layer,最后构建输出层,这一层是一个 softmax 层,每个 context 单词到中心单词的事件都被认为是独立的,所以将这些事件发生的概率相乘(似然函数) ,最后构建损失函数,即:将输出概率分布和实际选中的词概率分布进行 Corss Entropy 计算,接下来使用 SGD 对参数进行更新。这里,hidden layer 的训练结果就是最终的 word vector 了。
根据当前这个词来预测上下文:
Skip-gram 的具体训练过程如下,蓝色代表输入的词,图的框框代表滑动窗口,用来截取蓝色词的上下文,蓝色词的上下文作为输出,然后形成训练标本(Training Samples),这样我们就得到了{输入和输出},将他们放入{输入层-隐藏层-输出层}的神经网络训练,我们就能得到 Skip-gram 模型。因为神经网络不能直接处理文本,因此所有的词都用 one-hot encode 表示。
但输出层并不是我们关心的,我们去掉模型的输出层,才是我们想要的词向量模型,我们通过隐藏层的权重来表示我们的词。
因为最终分类的时候只用Softmax,万一有10万个词,那么要计算的参数就会特别多,Hierarchical Softmax与Negative Sampling就是优化softmax层参数计算量过多的方法
哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树
二叉树每一个分裂都是一个条件判断,相当于二分类,sigmoid 函数来判断走左边还是右边
分层Softmax是由二分类sigmoid组成的类似决策树多分类模型
这样做的好处就是,原本做softmax要用 N N N组 θ \theta θ( N N N是词库的单词量, θ \theta θ长度为 M M M),而这里只需要用 log N \log N logN组 θ \theta θ即可得到最终的目标(正向传播时,反向传播也类似)
其对数似然及反向传播推导如下
Skip-gram 模型与 CBOW 模型的推导过程大同小异,对于层次 SoftMax 的 skip-gram 模型,已知的是当前词 w,需要对其上下文 Context(w)中的词进行预测,故,其目标函数为:
因为要预测的是一个上下文,所以似然中多了一个加和符号,表示的是C个上下文
Negative sampling(NEG)可以视为对层次 SoftMax 的一种代替,它不再使用(复杂的)Huffman 树,而是利用(相对简单的)随机负采样,其目的也是用来提高训练速度并改善所得词向量的质量
通常的softmax往往得出的是一个正例与 N − 1 N-1 N−1个负例,而NEG采用的方法为选择一个正例,加上 k k k个负例(论文中是5,小样本5-20,大样本2-5)。 然后在更新 w ′ w' w′矩阵的时候只需要更新 k + 1 k+1 k+1组 θ \theta θ即可。 (因为在随机选择了 k k k个负例,而不是所有负例,如果仍然使用softmax,那么加和的结果就不是1,所以这里的激活函数是sigmoid)
Word2vec 采用带权采样法:词典 D 中的词在语料 C 中出现的次数有高有底,对于那些高频词,被选为负样本的概率就应该比较大,而低频词出现的概率应该比较小。Word2vec源码中使用下面的公式设置每个词的权重:
W e i g h t ( w ) = c o u n t e r ( w ) 0 . 75 ∑ w ∈ D c o u n t e r ( w ) 0 . 75 Weight(w) = \frac{counter(w)^0.75}{\sum_{w\in D}counter(w)^0.75} Weight(w)=∑w∈Dcounter(w)0.75counter(w)0.75
在 CBOW 模型中,已知词 w 的上下文 Context(w),需要预测 w,因此,对于给定的上下文 Context(w),词 w 就是一个正样本,其他的词就是负样本。负样本太多了,因此我们一般通过上述方法选取适量的负样本,记为 N E G ( w ) NEG(w) NEG(w)