# 一、引言
n-gram 算法通过统计文本中连续 n 个词的序列(或称为 “词组”)出现的频率,为各种 NLP 任务提供了有力的支持。
N-gram 模型的基本原理是基于马尔可夫假设,在训练 N-gram 模型时使用最大似然估计模型参数 —— 条件概率.
# 二、示例
例如,对于 “The cow jumps over the moon” 这句话。如果 N=2(称为二元模型),那么 ngram 将为:
the cow
cow jumps
jumps over
over the
the moon
在这种情况下有 5 个 n 元语法。请注意,从 the->cow
转移到 cow->jumps
到 Jumps->over
等,本质上是向前移动一个单词以生成下一个二元组。
如果 N=3,则 n 元语法将为:
the cow jumps
cow jumps over
jumps over the
over the moon
在这种情况下有 4 个 n 元语法。当 N=1 时,被称为一元语法,本质上是句子中的各个单词。当 N=2 时,称为二元组;当 N=3 时,称为三元组。当 N>3 时,这通常被称为多元组等等。
# 三、n-gram 算法的优缺点
(1)优点
- 简单易实现:n-gram 算法基于统计原理,实现起来相对简单直观。
- 通用性强:n-gram 算法可以应用于多种 NLP 任务,具有广泛的适用性。
- 效果好:在适当的 n 值下,n-gram 算法能够捕捉到文本中的局部统计信息,对于某些任务具有较好的效果。
(2)缺点
- 数据稀疏性:随着 n 的增加,n-gram 的数量急剧增长,导致很多 n-gram 在文本中只出现一次或根本不出现,这使得频率统计变得不可靠。
- 上下文信息有限:n-gram 只考虑了固定长度的上下文信息,无法捕捉更复杂的语义关系。对于较长的句子或篇章,n-gram 可能无法充分表达其整体意义。
- 计算复杂度高:当 n 较大或文本较长时,生成和统计 n-gram 的计算复杂度会显著增加,可能导致性能问题。
# 三、程序实现
import re | |
def generate_ngrams(text,n): | |
# split sentences into tokens | |
tokens=re.split("\\s+",text) | |
ngrams=[] | |
# collect the n-grams | |
for i in range(len(tokens)-n+1): | |
temp=[tokens[j] for j in range(i,i+n)] | |
ngrams.append(" ".join(temp)) | |
return ngrams | |
sentence = '_start_ this is ngram _generation_' | |
my_ngrams = generate_ngrams(sentence.split(), 3) | |
print([w for w in my_ngrams]) |
输出:
['_start_ this is', 'this is ngram', 'is ngram _generation_'] |
或者使用 NLTK 包
from nltk import ngrams | |
sentence = '_start_ this is ngram _generation_' | |
my_ngrams = ngrams(sentence.split(), 3) | |
print([w for w in my_ngrams]) |
输出:
[('_start_', 'this', 'is'), ('this', 'is', 'ngram'), ('is', 'ngram', '_generation_')] |