中文分词算法介绍

1. 最大匹配法 (正向/逆向)

正向/逆向匹配法思想一样,只是一个从左向右切分,另一个从右向左切分,这里拿逆向匹配法举例子:
输入例句:S1=”计算语言学课程有意思” ;
定义:最大词长MaxLen = 5;S2= ” “;分隔符 = “/”;
假设存在词表:…,计算语言学,课程,意思,…;
最大逆向匹配分词算法过程如下:
 (1)S2=”";S1不为空,从S1右边取出候选子串W=”课程有意思”;
 (2)查词表,W不在词表中,将W最左边一个字去掉,得到W=”程有意思”;
 (3)查词表,W不在词表中,将W最左边一个字去掉,得到W=”有意思”;
 (4)查词表,W不在词表中,将W最左边一个字去掉,得到W=”意思”
 (5)查词表,“意思”在词表中,将W加入到S2中,S2=” 意思/”,并将W从S1中去掉,此时S1=”计算语言学课程有”;
 (6)S1不为空,于是从S1左边取出候选子串W=”言学课程有”;
 (7)查词表,W不在词表中,将W最左边一个字去掉,得到W=”学课程有”;
 (8)查词表,W不在词表中,将W最左边一个字去掉,得到W=”课程有”;
 (9)查词表,W不在词表中,将W最左边一个字去掉,得到W=”程有”;
 (10)查词表,W不在词表中,将W最左边一个字去掉,得到W=”有”,这W是单字,将W加入到S2中,S2=“ /有 /意思”,并将W从S1中去掉,此时S1=”计算语言学课程”;
 (11)S1不为空,于是从S1左边取出候选子串W=”语言学课程”;
 (12)查词表,W不在词表中,将W最左边一个字去掉,得到W=”言学课程”;
 (13)查词表,W不在词表中,将W最左边一个字去掉,得到W=”学课程”;
 (14)查词表,W不在词表中,将W最左边一个字去掉,得到W=”课程”;
 (15)查词表,“意思”在词表中,将W加入到S2中,S2=“ 课程/ 有/ 意思/”,并将W从S1中去掉,此时S1=”计算语言学”;
 (16)S1不为空,于是从S1左边取出候选子串W=”计算语言学”;
 (17)查词表,“计算语言学”在词表中,将W加入到S2中,S2=“计算语言学/ 课程/ 有/ 意思/”,并将W从S1中去掉,此时S1=”";
 (18)S1为空,输出S2作为分词结果,分词过程结束。


1.2 最大匹配法扩展

       事实上,很多学者都基于简单的中文分词匹配法做了扩展,其中比较有名的就是台湾蔡志浩老师1996年写的“MMSEG: A Word Identification System for Mandarin Chinese Text Based on Two Variants of the Maximum Matching Algorithm”,在这篇文章的页面中,不仅介绍了相关的中文分词算法,并且提供了一个C版本的mmseg供研究使用,目前根据该文及其代码移植的mmseg程序版本包括C++版、Java版、Python版及Ruby版,影响甚广。
  此文是英文版本,建议有条件的读者直接读原文。不过国内也有该文的简介文章:《MMSeg分词算法简述》,原文似乎出自“www.solol.org”,但是我一直没打开这个网站,因为Java版的mmesg也是其提供的,不知道是已经关闭了还是被“墙”了。另外,leeing也翻译了全文《MMSEG 中文分词算法》,我粗略的读了一下,感觉翻译的不错。以下我先从自己理解的角度介绍一下该算法。
  MMSEG中文分词系统的可以由一句话总结:The system consisted of a lexicon, two matching algorithms, and four ambiguity resolution rules(该系统包括一个词典,两种匹配算法,以及四种歧义消解规则):
1、 词典(The Lexicon):
  分两种形式,对于单个汉字的汉语词,除了汉字本身外,还包括其统计频率(这个频率属于先验知识,可以来自于已经人工分好词的训练语料库),而对于二字长及以上的汉语词,只要词条本身就可以了。
2、 匹配算法(Matching Algorithm):
 a) 简单匹配:对于字符串中的汉字Cn,用词典匹配以Cn开头的子串并查找所有可能的匹配;
 b) 复杂匹配:对于字符串中的汉字Cn,查找所有可能以Cn开头的三词chunks,无论第一个汉语词是否有歧义。
3、歧义消解规则(Ambiguity Resolution Rules):
规则一:最大匹配(Maximum matching)
 a) 简单最大匹配算法,也就是我们常说的最大匹配法,不过作者采取的是正向匹配,并且按长度从小到大搜索词典:假设C1,C2,….代表一个字符串中的汉字,首先搜索词典,看 _C1_是否为一个单字组成的词语,然后搜索 _C1C2_来看是否为两个汉字组成的词语,以此类推,直至找到字典中最长的匹配。
 b) 复杂最大匹配算法,由Chen 和Liu(1992)提出,其核心的假设是:The most plausible segmentation is the three-word chunk with maximum length. 请注意three-word chunk,可以将其翻译为“三词语块”,这也是MMSEG中比较核心的一个概念,这个最大匹配规则考虑问题比较全面,在对句子中的某个词进行切分时,如果有歧义拿不定主意,就再向后展望两个汉语词,并且找出所有可能的“三词语块”。例如,对于如下的“三词语块”,请注意括号中是注明的语块长度(以汉语单字为基本单位):
1. _C1_ _C2_ _C3C4_(4)
2. _C1C2_ _C3C4_ _C5_(5)
3. _C1C2_ _C3C4_ _C5C6_(6)
  最大长度的“三词语块”是第3个,所以其第一汉语词_C1C2_将被作为正确的分词形式。以此类推,接下来我们从C3开始,找出所有可能的“三词语块”,重复上述规则,直到句子的最后一个词被划分。直观一点,对于以“眼”开头的如下5个“三词语块”,利用该规则,则“眼看”是正确的词语划分
1.眼看 就要 来了(6)
2.眼看 就要 来(5)
3.眼看 就 要(4)
4.眼 看 就要(4)
5.眼 看 就(3)


规则二:最大平均词长(Largest average word length)
  在句子的末尾,很可能得到的“三词语块”只有一个或两个词(其他位置补空),例如,对于如下两个“三词语块”,他们拥有同样的长度:
1. _C1_ _C2_ _C3_(平均词长=1)
2. _C1C2C3_(平均词长=3)
  这时规则1就无法解决其歧义消解问题,因此引入规则2:最大平均词长,也就是从这些语块中找出平均词长最大的语块,并选取其第一词语作为正确的词语切分形式。这个规则的前提假设是:It is more likely to encounter multi-character words than one-character words(在句子中遇到多字-词语的情况比单字-词语更有可能). 因此,上述两个“三词语块”中第二个_C1C2C3_就是最佳候选。直观一点,对于如下位于句尾三种形式的“三词语块”:
1.国际化(平均词长=3)
2.国际 化(平均词长=1.5)
3.国 际 化(平均词长=1)
  在规则1无法求解的情况下,根据规则2,则“国际化”为最佳候选语块,因此该语块的第一个词“国际化”就是最佳的分词形式。

规则三:最小词长方差(Smallest variance of word lengths)
  还有一些歧义是规则一和规则二无法解决的,例如,如下的两个“三词语块”拥有同样的长度和同样的平均词长:
1. _C1C2_ _C3C4_ _C5C6_
2. _C1C2C3_ _C4_ _C5C6_
  因此引入规则三:最小词长方差,也就是找出词长方差最小的语块,并选取其第一个词语作为正确的词语切分形式。在概率论和统计学中,一个随机变量的方差(Variance)描述的是它的离散程度,也就是该变量离其期望值的距离。因此该规则的前提假设是:Word lengths are usually evenly distributed(句子中的词语长度经常是均匀分布的)。直观来说,对于如下两个“三词语块”:
1.研究 生命 起源
2.研究生 命 起源
其长度为6,平均词长为2,规则一和规则二无能无力,利用规则三:
 语块1的方差 = ((2-2)^2+(2-2)^2+(2-2)^2)/3 = 0
 语块2的方差 = ((3-2)^2+(1-2)^2+(2-2)^2)/3 = 2/3
则语块1为最佳候选,因此该语块的第一个词“研究”为最佳的分词形式。

规则四:最大单字词语语素自由度之和(Largest sum of degree of morphemic freedom of one-character words):
  如下所示,例子中的两个“三词语块”拥有同样的长度、平均词长及方差,因此上述三个规则都无法解决其歧义消解问题:
1. _C1_ _C2_ _C3C4_
2. _C1_ _C2C3_ _C4_
  这两个语块都包括了两个单字(one-character)词语和一个两字(two-character)词语,规则四主要关注其中的单字词语。直观来看,有些汉字很少作为词语出现,而另一些汉字则常常作为词语出现,从统计角度来看,在语料库中出现频率高的汉字就很可能是一个单字词语,反之可能性就小。计算单词词语语素自由度之和的公式是对“三词语块”中的单字词语频率取对数并求和(The formula used to calculate the sum of degree of morphemic freedom is to sum log(frequency) of all one-character word(s) in a chunk.)规则四则选取其中和最大的语块,并将该语块的第一词语作为最佳的词语切分形式。


2. 基于字标注的中文分词方法

  在2002年之前,自动分词方法基本上是基于词(或词典)的,在此基础上可进一步分成基于规则和基于统计的两大类。第一篇基于字标注(Character-based Tagging)的分词论文发表在2002年第一届SIGHAN研讨会上,当时并未引起学界的重视。一年后,Xue在最大熵(Maximum Entropy,ME)模型上实现的基于字的分词系统参加了Bakeoff-2003的评测,在As语料库的封闭测试项目上获得第二名),然而其OOV 召回率Roov(0.729)却位居榜首。Xue还在CityU语料库的封闭测试中获得第三名,其Roov(0.670)仍然是该项比赛中最高的。尽管在Bakeoff2003中各种分词技术的优劣尚难分仲伯,但既然未登录词对分词精度的影响比分词歧义至少大5倍以上,我们自然看好这种能获致最高OOV召回的分词方法。这一预测果然在Bakeoff2005上得到了证实。
  基于字标注的分词系统在Bakeoff-2005上崭露头角。其中Low的系统采用最大熵模型,在四项开放测试中夺得三项冠军(AS,CityU,PKU)和一项亚军(MSRA)。Tseng的系统采用条件随机场模型,在四项封闭测试中取得两项冠军(CityU, MSRA)、一项亚军(PKU)和一项季军(AS)。到了Bakeoff-2006,基于字的分词系统已遍地开花。其中,笔者用条件随机场模型实现的基于字标注的分词系统,在参加的六项分词评测中,夺得四个第一(CityU开放,As开放,As封闭,CTB封闭)和两个第三(CTB开放,CityU封闭)。
  以往的分词方法,无论是基于规则的还是基于统计的,一般都依赖于一个事先编制的词表(词典)。自动分词过程就是通过词表和相关信息来做出词语切分的决策。与此相反,基于字标注的分词方法实际上是构词方法。即把分词过程视为字在字串中的标注问题。由于每个字在构造一个特定的词语时都占据着一个确定的构词位置(即词位),假如规定每个字最多只有四个构词位置:即B(词首),M (词中),E(词尾)和S(单独成词),那么下面句子(甲)的分词结果就可以直接表示成如(乙)所示的逐字标注形式:


  (甲)分词结果:/上海/计划/N/本/世纪/末/实现/人均/国内/生产/总值/五千美元/。
  (乙)字标注形式:上/B海/E计/B划/E N/S 本/s世/B 纪/E 末/S 实/B 现/E 人/B 均/E 国/B 内/E生/B产/E总/B值/E 五/B千/M 美/M 元/E 。/S


  首先需要说明,这里说到的“字”不只限于汉字。考虑到中文真实文本中不可避免地会包含一定数量的非汉字字符,本文所说的“字”,也包括外文字母、阿拉伯数字和标点符号等字符。所有这些字符都是构词的基本单元。当然,汉字依然是这个单元集合中数量最多的一类字符。
  把分词过程视为字的标注问题的一个重要优势在于,它能够平衡地看待词表词和未登录词的识别问题。在这种分词技术中,文本中的词表词和未登录词都是用统一的字标注过程来实现的。在学习架构上,既可以不必专门强调词表词信息,也不用专门设计特定的未登录词(如人名、地名、机构名)识别模块。这使得分词系统的设计大大简化。在字标注过程中,所有的字根据预定义的特征进行词位特性的学习,获得一个概率模型。然后,在待分字串上,根据字与字之间的结合紧密程度,得到一个词位的标注结果。最后,根据词位定义直接获得最终的分词结果。总而言之,在这样一个分词过程中,分词成为字重组的简单过程。然而这一简单处理带来的分词结果却是令人满意的。


3. 统计语言模型

算法:对于所有的候选切分, 选择P(first) × P(remaining) 乘积最高的那一个作为最佳切分。事实上它里面包括了递归调用,最终返回的是最佳的分词短语。

      《Beautiful Data》中的标准解释是“The Naive Bayes probability of a sequence of words”,既“单词序列的朴素贝叶斯(Naive Bayes,简称NB)概率“,朴素贝叶斯概率的核心在于它假设向量的所有分量之间是独立的,这里的向量是单词序列,故假设的是所有单词之间是独立的,这也是我们利用一元语言模型的一个前提假设。回顾’wheninrome’这个分词例子,它有很多候选分词短语,譬如“when in rome”,利用一元语言模型,只需计算P(when) × P(in) × P(rome)。
       首先我们从一元语言模型的文件里读取单词及其计数,如果一个单词在语料库中出现,它的概率就是Count(word)/N,这里N是语料库的单词数目的规模。事实上,相对于使用完整的1千3百万单词(词型)的一元语言模型,Peter Norvig大牛对这个一元语言模型进行了简化:(a) 创建了一个更通用的词汇表,并且其中的单词是大小写不敏感(不区分)的,故“the”,”The”以及“THE”的计数是加在一起作为“the”的计数的;(b)只有由字母(letter)组合的单词才被计入其中,而对于其他包含数字或者标点的“单词”则被过滤,故“+170.002”以及“can’t”都不会被计入;(c)只列出其中最常用的1百万单词中的前1/3,也就是333333个单词。

      即使是一个trillion-word的语料库,某些单词也不一定能被其单词列表包括,这对于Pw来说也是一个问题,因为我们不能让它返回一个0概率,事实上,这就是统计语言模型中非常重要的平滑问题。

  对于一个语料库中未出现的单词来说,如果不能返回0概率,那应该返回多少?Google语料库中的词例(token)数目N大约有1万亿个(a trillion),在简化了的一元语言模型中,最小的常见单词的计数是12,711个。所以,一个未知单词的概率应该介于0到12,710/N之间。 所有的未知词概率都一样也不大可能:一个20个字母组成的随机序列(单词)的概率就很可能比6个字母组成的随机序列(单词)的概率要小。
  我们将定义一个概率分布的类Pdist,它将加载类似(key, count)形式数据文件。缺省的情况,对于未知的单词,其概率均为1/N,但是对于每一个实例,Pdist均提供一个函数重载这个缺省值。为了避免过长的单词拥有过高的概率,我们从概率10/N出发,对于候选单词的每一个字母都除以10。

      对于一个包含n个字符的单词来说,利用语言模型进行分词的前提是首先枚举出所有的候选切分,而segment函数中:
  candidates = ( [first] + segment( rem ) for first, rem in splits( text ) )
的作用正是如此,它包含了递归调用,因此能枚举出所有的候选切分。那么,这个函数的时间复杂度是多少呢?一个包含n个字符的字符串有2^(n-1)种不同的分词方案(在字符之间有n-1个位置,每一个位置既可以作为单词边界也可以不作为边界),因此segment函数的时间复杂度为O(2^n),难怪之前的测试当字符串比较长时就跑不出结果了!
  那么,我们应该如何来改进这个递归的分词程序呢?如果你了解一些算法知识,大概会想到动态规划算法:
  动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。
  动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值