介绍N-gram比较清楚的博客

介绍了一种基于统计特征的新词发现算法,通过计算不同长度片段的内部凝固度,采用‘宁放过,勿切错’的原则,有效构建高质量词库。

from: https://www.cnblogs.com/think90/articles/11522978.html

 

无监督构建词库:更快更好的新词发现算法

新词发现是 NLP 的基础任务之一,主要是希望通过无监督发掘一些语言特征(主要是统计特征),来判断一批语料中哪些字符片段可能是一个新词。

“新词发现”是一个比较通俗的叫法,更准确的叫法应该是“无监督构建词库”,因为原则上它能完整地构建一个词库出来,而不仅仅是“新词”。当然,你可以将它跟常用词库进行对比,删掉常见词,就可以得到新词了。

 

分词的目的

分词一般作为文本挖掘的第一步,仿佛是很自然的,但事实上也应该问个为什么:为什么要分词?人本来就是按照字来书写和理解的呀?

当模型的记忆和拟合能力足够强(或者简单点,足够智能)的时候,我们完全可以不用分词的,直接基于字的模型就可以做,比如基于字的文本分类、问答系统等,早已有人在研究。但是,即便这些模型能够成功,也会因为模型复杂而导致效率下降,因此,很多时候(尤其是生产环境中),我们会寻求更简单、更高效的方案。

什么方案最高效?以文本分类为例,估计最简单高效的方案就是“朴素贝叶斯分类器”了,类似的,比较现代的是 FastText,它可以看作是“朴素贝叶斯”的“神经网络版”。要注意,朴素贝叶斯基于一个朴素的假设:特征之间相互独立。这个假设越成立,朴素贝叶斯的效果就越好。然而,对于文本来说,显然上下文紧密联系,这个假设还成立吗?

注意到,当特征之间明显不独立的时候,可以考虑将特征组合之后,使得特征之间的相关性减弱,再用朴素贝叶斯。比如,对于文本,如果以字为特征,则朴素假设显然不成立,如“我喜欢数学”中的“喜”和“欢”、“数”和“学”都明显相关,这时候我们可以考虑将特征进行组合,得到“我/喜欢/数学”,这样三个片段之间的相关性就没有那么强了,因此可以考虑用上述结果。

可以发现,这个过程很像分词,或者反过来说,分词的主要目的之一,就是将句子分为若干个相关性比较弱的部分,便于进一步处理。从这个角度来看,分的可能不一定是“词”,也可能是短语、常用搭配等。

说白了,分词就是为了削弱相关性,降低对词序的依赖,这一点,哪怕在深度学习模型中,都是相当重要的。有些模型,不分词但是用 CNN,也就是把若干个字组合作为特征来看,这也是通过字的组合来减弱特征间的相关性的体现。

 

算法大意

既然分词是为了削弱相关性,那么我们分词,就是在相关性弱的地方切断了。文章《【中文分词系列】 2. 基于切分的新词发现》[1] 其实就是这个意思,只是那里认为,文本的相关性仅由相邻两字(2grams)来决定,这在很多时候都是不合理的,比如“林心如”中的“心如”、“共和国”中的“和国”,凝固度(相关性)都不是很强,容易错切。

因此,本文就是在前文的基础上改进,那里只考虑了相邻字的凝固度,这里同时考虑多字的内部的凝固度(ngrams),比如,定义三字的字符串内部凝固度为:

这个定义其实也就是说,要枚举所有可能的切法,因为一个词应该是处处都很“结实”的,4 字或以上的字符串凝固度类似定义。一般地,我们只需要考虑到 4 字(4grams)就好(但是注意,我们依旧是可以切出 4 字以上的词来的)。

考虑了多字后,我们可以设置比较高的凝固度阈值,同时防止诸如“共和国”之类的词不会被切错,因为考虑三字凝固度,“共和国”就显得相当结实了,所以,这一步就是“宁放过,勿切错”的原则。

但是,“各项”和“项目”这两个词,它们的内部凝固度都很大,因为前面一步是“宁放过,勿切错”,因此这样会导致“各项目”也成词,类似的例子还有“支撑着”、“球队员”、“珠海港”等很多例子。但这些案例在 3grams 中来看,凝固度是很低的,所以,我们要有一个“回溯”的过程,在前述步骤得到词表后,再过滤一遍词表,过滤的规则就是,如果里边的 n 字词,不在原来的高凝固度的 ngrams 中,那么就得“出局”。

所以,考虑 ngrams 的好处就是,可以较大的互信息阈值情况下,不错切词,同时又排除模凌两可的词。就比如“共和国”,三字互信息很强,两字就很弱了(主要还是因为“和国”不够结实),但是又能保证像“的情况”这种不会被切出来,因为阈值大一点,“的情”和“的情况”都不结实了。

 

详细的算法

 

完整的算法步骤如下:

 

第一步,统计:选取某个固定的 n,统计 2grams、3grams、…、ngrams,计算它们的内部凝固度,只保留高于某个阈值的片段,构成一个集合 G;这一步,可以为 2grams、3grams、…、ngrams 设置不同的阈值,不一定要相同,因为字数越大,一般来说统计就越不充分,越有可能偏高,所以字数越大,阈值要越高;

 

第二步,切分:用上述 grams 对语料进行切分(粗糙的分词),并统计频率。切分的规则是,只有一个片段出现在前一步得到的集合 G 中,这个片段就不切分,比如“各项目”,只要“各项”和“项目”都在 G 中,这时候就算“各项目”不在 G 中,那么“各项目”还是不切分,保留下来;

 

第三步,回溯:经过第二步,“各项目”会被切出来(因为第二步保证宁放过,不切错)。回溯就是检查,如果它是一个小于等于 n 字的词,那么检测它在不在 G 中,不在就出局;如果它是一个大于 n 字的词,那个检测它每个 n 字片段是不是在 G 中,只要有一个片段不在,就出局。还是以“各项目”为例,回溯就是看看,“各项目”在不在 3gram中,不在的话,就得出局。

 

每一步的补充说明:

 

1. 较高的凝固度,但综合考虑多字,是为了更准,比如两字的“共和”不会出现在高凝固度集合中,所以会切开(比如“我一共和三个人去玩”,“共和”就切开了),但三字“共和国”出现在高凝固度集合中,所以“中华人民共和国”的“共和”不会切开;

 

2. 第二步就是根据第一步筛选出来的集合,对句子进行切分(你可以理解为粗糙的分词),然后把“粗糙的分词结果”做统计,注意现在是统计分词结果,跟第一步的凝固度集合筛选没有交集,我们认为虽然这样的分词比较粗糙,但高频的部分还是靠谱的,所以筛选出高频部分;

 

3. 第三步,例如因为“各项”和“项目”都出现高凝固度的片段中,所以第二步我们也不会把“各项目”切开,但我们不希望“各项目”成词,因为“各”跟“项目”的凝固度不高(“各”跟“项”的凝固度高,不代表“各”跟“项目”的凝固度高),所以通过回溯,把“各项目”移除(只需要看一下“各项目”在不在原来统计的高凝固度集合中即可,所以这步计算量是很小的)。

 

 

代码实现

本次开源地址位于:

 https://github.com/bojone/word-discovery

 

 

<think>好的,用户想了解n-gram的概念及其详细用法,还有应用实例。首先,我需要回忆一下n-gram的基础知识。n-gram是自然语言处理中常用的模型,用来捕捉文本中的序列信息。n代表窗口大小,比如二元组就是前后两个词的组合。 接下来,用户可能需要知道n-gram的数学定义。比如,一个句子的概率可以分解为各个n-gram的条件概率乘积。公式的话,应该用独立公式格式,也就是$$...$$,比如$$P(w_1, w_2, ..., w_m) = \prod_{i=1}^m P(w_i | w_{i-n+1}, ..., w_{i-1})$$,但要注意实际应用中n不能超过i-1,所以可能需要调整。 然后,用户可能想了解不同的n取值有什么不同。比如unigram是单个词,不考虑顺序;bigram考虑前一个词,trigram则考虑前两个词。需要举例说明,比如“我爱自然语言处理”分解成不同的n-gram形式。 应用实例方面,引用里提到了N-Gram的应用,比如文本生成、搜索建议、拼写纠错。需要具体说明每个应用是如何使用n-gram的,比如文本生成如何通过概率选择下一个词。 另外,用户可能对平滑算法感兴趣,但根据引用内容,平滑算法会在下一篇博客讨论,所以这里可能不需要深入,但可以提到它的重要性。同时,结合引用中的信息,比如引用1提到应用实例,引用3提到不同n-gram模型的联系,需要确保回答中涵盖这些点。 还要注意生成相关问题,可能需要包括n-gram的优缺点、平滑方法、与其他模型如Word2Vec的区别,以及具体应用场景的问题。 最后,检查LaTeX格式是否正确,所有行内公式用$...$,独立公式用$$...$$并单独成段,确保引用标识正确添加,比如在文本生成部分末尾加上[^1]。</think>### N-Gram模型详解及其应用实例 #### 一、核心概念 1. **定义** N-Gram是一种基于统计的语言模型,通过连续$n$个词的序列(称为**n元组**)捕捉文本中的局部规律。其核心思想是:一个词出现的概率仅依赖于它前面的$n-1$个词。数学表示为: $$P(w_1, w_2, ..., w_m) = \prod_{i=1}^m P(w_i | w_{i-n+1}, ..., w_{i-1})$$ 2. **常见类型** - **Unigram (1-Gram)**: 单个词独立出现,如$P(\text{语言})$ - **Bigram (2-Gram)**: 依赖前一个词,如$P(\text{处理} | \text{语言})$ - **Trigram (3-Gram)**: 依赖前两个词,如$P(\text{模型} | \text{语言, 处理})$ 例如句子“我爱自然语言处理”的Bigram分解为:`[我 爱]`, `[爱 自然]`, `[自然 语言]`, `[语言 处理]`。 --- #### 二、关键技术原理 1. **概率计算** 通过语料库统计词频,例如Bigram概率: $$P(w_i | w_{i-1}) = \frac{\text{Count}(w_{i-1}, w_i)}{\text{Count}(w_{i-1})}$$ 若语料中“自然语言”共现100次,“自然”单独出现200次,则$P(\text{语言} | \text{自然}) = 100/200 = 0.5$。 2. **平滑算法** 解决零概率问题(如未登录词组合),常用方法包括拉普拉斯平滑(加1平滑)和Katz回退,例如: $$P_{\text{smooth}}(w_i | w_{i-1}) = \frac{\text{Count}(w_{i-1}, w_i) + 1}{\text{Count}(w_{i-1}) + V}$$ 其中$V$为词汇表大小[^3]。 --- #### 三、应用实例 1. **文本生成** 根据历史词序列预测下一个词,例如输入“自然语言”,模型可能生成“处理”或“模型”。 ```python def generate_text(seed, n=2, max_length=10): context = seed.split()[-n+1:] for _ in range(max_length): next_word = predict_next_word(context) seed += " " + next_word context = context[1:] + [next_word] return seed ``` 2. **搜索建议** 输入“深度学习”,系统推荐高频后续词如“框架”“算法”等。 3. **拼写纠错** 检测非常见n-gram组合,例如“吃苹果”比“吃苹”概率更高,从而纠正错别字。 --- #### 四、对比其他模型 | 特性 | N-Gram | Word2Vec/GloVe[^2] | |-------------|----------------------------|-----------------------------| | **数据依赖** | 依赖局部共现统计 | 捕捉全局语义关系 | | **稀疏性** | 高(需平滑处理) | 低(稠密向量表示) | | **扩展性** | 计算复杂度随$n$指数增长 | 线性复杂度 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值