n-gram语言模型——句子概率分布计算与平滑
- 前言
- 语言模型
- 等价假设
- n元语法
- 句子概率分布计算方式
- 数据平滑
- Lidstone平滑(1-gram)
- Laplace平滑(1-gram)
- 附上两种平滑在1-gram下代码
- Lidstone平滑与Laplace平滑(2-gram)
- 附上两种平滑在2-gram下代码
前言
语言模型(Language Model, LM)在自然语言处理(NLP)领域扮演着核心角色,特别是在统计模型驱动的汉语自动分词和句法分析等领域。目前,广泛采用的是N-gram语法模型,这种模型以其构建的简便性和直观性而著称,但同时也因数据稀疏性问题而不得不使用平滑(Smoothing)技术。
N-gram模型由于计算和实现简单,非常适合于计算资源有限的场景。但是在理解和生成自然语言的复杂结构方面性能比较差。
神经网络方法适用于资源充足的情况。最新的NLP模型,如BERT、GPT和其他基于Transformer的模型,已经在很多语言任务中取得了非常好的效果,这些模型能够更加有效地捕捉语言的深层次语义,并处理长距离的依赖关系。
尽管如此,N-gram模型仍然在某些特定的简单任务中有其应用价值。本篇博客将介绍N-gram的基础理论。
语言模型
,其中反映的是字符串作为一个句子出现的频率。例如,在一个口语化的语言模型中(这句话可以理解为‘在一个语料库下’、‘在一个数据集下’),"Okay"一词在每100个句子中大约出现一次,因此p(“Okay”)≈0.01。
,其概率可以用如下公式计算:
,这个词序列被称为历史。随着历史长度的增加,有可能的历史组合数呈指数级增长。这样的话,我们也不可能算出来一个长句子的概率。
等价假设
由于历史在训练数据中的出现可能性极低,我们几乎无法直接从训练数据中准确估计出模型的参数。实际情况是,许多历史事件可能根本不会在训练数据中出现。为了克服这一问题,我们可以采用将历史映射到等价类的方法,其中等价类的数量远少于历史的数量。如果假设
和映射到同一个等价类,当且仅当这两个历史的最近的n−1个词是相同的。
n元语法
符合上述条件的语言模型被称为n-gram或n-gram文法。通常情况下,n的取值不会太大,否则会造成等价类数量繁多,自由参数过多的问题仍旧存在。在实际应用中,通常采用n等于3的模型。当n为1时,即第i个词的出现独立于它之前的历史,此时的模型称为unigram
;当n为2时,即第i个词的出现仅与其前一个词有关,此模型称为bigram
,也就是一阶马尔可夫链;当n为3时,即第i个词的出现仅与其前两个词有关,此模型称为trigram
,也就是二阶马尔可夫链。
以bigram
为例,可以近似认为一个词的出现概率仅依赖于它前面的一个词:
在i为1时有意义,我们通常会在句子开头添加一个开始标记(BOS),并在句子结尾添加一个结束标记(EOS),以此包含在概率计算中。例如,要计算Mark wrote a book
的概率,我们会这样计算:
,可以简单地计算在某一文本中单词w的频率,然后对其进行归一化。若用c表示在给定文本中的出现次数,我们可以使用如下公式:
上述公式即为最大似然估计(Maximum Likelihood Estimation, MLE)。对于更高阶的n-gram模型,这一公式同样适用。
句子概率分布计算方式
下面这段代码是使用jieba
进行中文分词和nltk
计算bigrams(二元语法)的频率分布的简单例子,然后再用这个模型来计算另一个测试文本的联合概率。
使用nltk.ngrams
函数把分词后的词语生成二元语法序列。nltk.ngrams
传入词语列表和n的值,返回一个字典,包含所有的n-grams序列。
创建ConditionalFreqDist
实例cfd
,将bigrams作为输入。ConditionalFreqDist
类是用来计算每个条件(在bigrams中是第一个词)对应的事件(第二个词)的频率分布。上述代码中cfd
值如下:
最后算得这个测试句子的概率是0.5。但是这段代码有个假设: 没有考虑bigram出现次数为0的情况,这在实际应用中可能会导致概率为0。所以我们要使用平滑技术来处理这个问题。
举个具体例子:由于语料库中’哈哈’后面没有出现过’真’,所以在计算含’哈哈真’序列的句子时会报错。
数据平滑
这里给大家演示nltk
库提供的Lidstone
和Laplace
平滑。
上文说过,在统计语言模型中,如果一个n-gram在训练数据中从未出现过,它的概率将是零。这是不理想的,因为这意味着整个句子的概率也将是零,即使这个句子在现实中是可能出现的。Lidstone
和Laplace
平滑通过向计数中添加一个小的非零值来解决这个问题。
Lidstone平滑(1-gram)
Lidstone平滑是一种给每个计数添加一个小正数γ的方法。假设我们有一个词汇表V,大小为|V|,对于任何n-gram的计数c,平滑后的概率计算如下:
其中:
- 是词w的Lidstone平滑后的概率。
- 是训练集中所有词的总计数。
- 是词汇表的大小。
- 是一个介于0和1之间的平滑参数。
Laplace平滑(1-gram)
Laplace平滑(又称为加一平滑)是Lidstone平滑的一个特例,其中γ=1。这意味着我们向每个n-gram的计数添加1,以避免任何n-gram的概率为零。平滑后的概率计算如下:
在Laplace平滑中,向分母中添加整个词汇表的大小,以确保总概率和为1。
Laplace平滑假设所有未见的n-gram都有相同的概率,而Lidstone平滑则允许通过选择不同的γ值给未见的n-gram分配不同的概率。当γ趋近于0时,Lidstone平滑可以逼近未平滑的模型,而当γ增大时,可以逼近Laplace平滑。通过调整γ的值,Lidstone平滑提供了比Laplace平滑更多的灵活性。
附上两种平滑在1-gram下代码
下词的概率,而不是1元语法词的独立概率。所以要说到这两种平滑的2元语法形式。
说白了,1元是概率分布,2元以及更高是条件频率分布。
Lidstone平滑与Laplace平滑(2-gram)
Lidstone和Laplace平滑都可以用于任何n-gram模型,不仅限于1-gram(unigrams)。对于2-grams(bigrams)、3-grams(trigrams)或更高阶的n-grams,原理是相同的。区别在于你要如何定义条件和事件的关系。
,其中 是第一个词, 是第二个词。在未平滑的情况下,我们通常会计算 在 之后出现的次数,然后除以 出现的总次数来估计概率。但是,如果某个bigram在训练数据中从未出现过,就会遇到零概率问题。
对于Laplace平滑,bigram的概率则是:
在这里:
- 是
- 是第一个词 在训练集中的原始计数。
)都有自己的频率分布。当应用Lidstone或Laplace平滑时,会分别更新这些条件分布中的每个概率。
附上两种平滑在2-gram下代码
输出如下:
可以看到在训练语料下,句子一概率更高,说明更合理一些。
变量lidstone_cfd的内容如下:
比较值得注意的一点就是,语料里面没有出现过’你哈哈不是’这样的序列,但是使用了平滑技术之后,我们的代码不会报错,而且最终概率也不为零了。平滑通过向计数中添加一个小的非零值来解决这个问题。