N-Gram(有时也称为N元模型)是天然语言处理中一个很是重要的概念,一般在NLP中,人们基于必定的语料库,能够利用N-Gram来预计或者评估一个句子是否合理。另一方面,N-Gram的另一个做用是用来评估两个字符串之间的差别程度。这是模糊匹配中经常使用的一种手段。本文将今后开始,进而向读者展现N-Gram在天然语言处理中的各类powerful的应用。java
欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、天然语言处理。算法
在天然语言处理时,最经常使用也最基础的一个操做是就是“模式匹配”,或者称为“字符串查找”。而模式匹配(字符串查找)又分为精确匹配和模糊匹配两种。apache
所谓精确匹配,你们应该并不陌生,好比咱们要统计一篇文章中关键词 “information” 出现的次数,这时所使用的方法就是精确的模式匹配。这方面的算法也比较多,并且应该是计算机相关专业必修的基础课中都会涉及到的内容,例如KMP算法、BM算法和BMH算法等等。markdown
另一种匹配就是所谓的模糊匹配,它的应用也随处可见。例如,通常的文字处理软件(例如,Microsoft Word等)都会提供拼写检查功能。当你输入一个错误的单词,例如 “ informtaion” 时,系统会提示你是否要输入的词实际上是 “information” 。将一个可能错拼单词映射到一个推荐的正确拼写上所采用的技术就是模糊匹配。数据结构
模糊匹配的关键在于如何衡量两个长得很像的单词(或字符串)之间的“差别”。这种差别一般又称为“距离”。这方面的具体算法有不少,例如基于编辑距离的概念,人们设计出了 Smith-Waterman 算法和Needleman-Wunsch 算法,其中后者仍是历史上最先的应用动态规划思想设计的算法之一。如今Smith-Waterman 算法和Needleman-Wunsch 算法在生物信息学领域也有重要应用,研究人员经常用它们来计算两个DNA序列片断之间的“差别”(或称“距离”)。甚至于在LeetCode上也有一道“No.72 Edit Distance”,其本质就是在考察上述两种算法的实现。可见相关问题离咱们并不遥远。机器学习
事实上,笔者在新出版的《算法之美——隐匿在数据结构背后的原理》一书中已经详细介绍了包括Needleman-Wunsch算法、Smith-Waterman算法、N-Gram算法、Soundex算法、Phonix算法等在内的多种距离定义算法(或模糊匹配算法)。而今天为了引出N-Gram模型在NLP中的其余应用,咱们首先来介绍一下如何利用N-Gram来定义字符串之间的距离。函数
咱们除了能够定义两个字符串之间的编辑距离(一般利用Needleman-Wunsch算法或Smith-Waterman算法)以外,还能够定义它们之间的N-Gram距离。N-Gram(有时也称为N元模型)是天然语言处理中一个很是重要的概念。假设有一个字符串 ss,那么该字符串的N-Gram就表示按长度 N 切分原词获得的词段,也就是 ss 中全部长度为 N 的子字符串。设想若是有两个字符串,而后分别求它们的N-Gram,那么就能够从它们的共有子串的数量这个角度去定义两个字符串间的N-Gram距离。可是仅仅是简单地对共有子串进行计数显然也存在不足,这种方案显然忽略了两个字符串长度差别可能致使的问题。好比字符串 girl 和 girlfriend,两者所拥有的公共子串数量显然与 girl 和其自身所拥有的公共子串数量相等,可是咱们并不能据此认为 girl 和girlfriend 是两个等同的匹配。工具
为了解决该问题,有学者便提出以非重复的N-Gram分词为基础来定义 N-Gram距离这一律念,能够用下面的公式来表述: post
在《算法之美——隐匿在数据结构背后的原理》一书中,咱们给出了在C++下实现的计算两个字符串间N-Gram距离的函数,鉴于全书代码已经在本博客中发布,这里再也不重复列出。事实上,不少语言的函数库或者工具箱中都已经提供了封装好的计算 N-Gram 距离的函数,下面这个例子演示了在Java中使用N-Gram 距离的方法。学习
针对这个例子,这里须要说明的是:
import org.apache.lucene.search.spell.*; public class NGram_distance { public static void main(String[] args) { NGramDistance ng = new NGramDistance(); float score1 = ng.getDistance("Gorbachev", "Gorbechyov"); System.out.println(score1); float score2 = ng.getDistance("girl", "girlfriend"); System.out.println(score2); } }
有兴趣的读者能够在引用相关JAR包以后在Eclipse中执行上述Java程序,你会发现,和咱们预期的同样,字符串Gorbachev和Gorbechyov所得之距离评分较高(=0.7),说明两者很接近;而girl和girlfriend所得之距离评分并不高(=0.3999),说明两者并不很接近。
从如今开始,咱们所讨论的N-Gram模型跟前面讲过N-Gram模型从外在来看已经大不相同,可是请注意它们内在的联系(或者说本质上它们仍然是统一的概念)。
为了引入N-Gram的这个应用,咱们从几个例子开始。
首先,从统计的角度来看,天然语言中的一个句子 ss 能够由任何词串构成,不过几率 P(s)P(s) 有大有小。例如:
显然,对于中文而言 s1s1 是一个通顺而有意义的句子,而s2s2 则不是,因此对于中文来讲,P(s1)>P(s2)P(s1)>P(s2) 。但不一样语言来讲,这两个几率值的大小可能会反转。
其次,另一个例子是,若是咱们给出了某个句子的一个节选,咱们其实能够可以猜想后续的词应该是什么,例如
显然,若是咱们知道这个句子片断更多前面的内容的状况下,咱们会获得一个更加准确的答案。这就告诉咱们,前面的(历史)信息越多,对后面未知信息的约束就越强。
若是咱们有一个由 mm 个词组成的序列(或者说一个句子),咱们但愿算得几率 P(w1,w2,⋯,wm)P(w1,w2,⋯,wm) ,根据链式规则,可得
来看一个具体的例子,假设咱们如今有一个语料库以下,其中<s1><s2><s1><s2> 是句首标记,</s2></s1></s2></s1> 是句尾标记:
再举一个来自文献[1]的例子,假设如今有一个语料库,咱们统计了下面一些词出现的数量
有研究人员用150万词的训练语料来训练 trigram 模型,而后用一样来源的测试语料来作验证,结果发现23%的 trigram 没有在训练语料中出现过。这其实就意味着上一节咱们所计算的那些几率有空为 0,这就致使了数据稀疏的可能性,咱们的表3中也确实有些为0的状况。对语言而言,因为数据稀疏的存在,极大似然法不是一种很好的参数估计办法。
这时的解决办法,咱们称之为“平滑技术”(Smoothing)或者 “减值” (Discounting)。其主要策略是把在训练样本中出现过的事件的几率适当减少,而后把减少获得的几率密度分配给训练语料中没有出现过的事件。实际中平滑算法有不少种,例如:
▸ Laplacian (add-one) smoothing
▸ Add-k smoothing
▸ Jelinek-Mercer interpolation
▸ Katz backoff
▸ Absolute discounting
▸ Kneser-Ney
对于这些算法的详细介绍,咱们将在后续的文章中结合一些实例再来进行讨论。
若是你能从前面那些繁冗、复杂的概念和公式中挺过来,恭喜你,你对N-Gram模型已经有所认识了。尽管,咱们还没来得及探讨平滑算法(但它即将出如今个人下一篇博文里,若是你以为还未过瘾的话),可是其实你已经掌握了一个相对powerful的工具。你能够能会问,在实践中N-Gram模型有哪些具体应用,做为本文的结束,主页君便在此补充几个你曾见过的或者曾经好奇它是如何实现的例子。
Eg.1
搜索引擎(Google或者Baidu)、或者输入法的猜测或者提示。你在用百度时,输入一个或几个词,搜索框一般会如下拉菜单的形式给出几个像下图同样的备选,这些备选实际上是在猜测你想要搜索的那个词串。再者,当你用输入法输入一个汉字的时候,输入法一般能够联系出一个完整的词,例如我输入一个“刘”字,一般输入法会提示我是否要输入的是“刘备”。经过上面的介绍,你应该可以很敏锐的发觉,这实际上是以N-Gram模型为基础来实现的,若是你能有这种觉悟或者想法,那我不得不恭喜你,都学会抢答了!
Eg.2
某某做家或者语料库风格的文本自动生成。这是一个至关有趣的话题。来看下面这段话(该例子取材自文献【1】):
“You are uniformly charming!” cried he, with a smile of associating and now and then I bowed and they perceived a chaise and four to wish for.
你应该尚未感受到它有什么异样吧。但事实上这并非由人类写出的句子,而是计算机根据Jane Austen的语料库利用trigram模型自动生成的文段。(Jane Austen是英国著名女做家,表明做有《傲慢与偏见》等)
再来看两个例子,你是否能看出它们是按照哪位文豪(或者语料库)的风格生成的吗?
答案是第一个是莎士比亚,第二个是华尔街日报。最后一个问题留给读者思考,你以为上面两个文段所运用的n-gram模型中,n应该等于多少?
[1] Speech and Language Processing. Daniel Jurafsky & James H. Martin, 3rd. Chapter 4
[2] 本文中的一些例子和描述来自 北京大学 常宝宝 以及 The University of Melbourne “Web Search and Text Analysis” 课程的幻灯片素材