《解密搜索引擎技术实战:Lucene & Java精华版(第2版)》第4章中文分词原理与实现,本章介绍了分词中的查找词典算法。查词典最早用首字母散列或者散列表实现,然后采用Trie树的方法开始流行,还有采用数组形式的双数组,后来又发展出和AC算法结合的Trie树。本节为大家介绍概率语言模型的分词方法。
作者:罗刚来源:电子工业出版社|2013-12-12 22:37
4.6 概率语言模型的分词方法(1)
从统计思想的角度来看,分词问题的输入是一个字串C=C1,C2,……,Cn,输出是一个词串S=W1,W2,……,Wm,其中m<=n。对于一个特定的字符串C,会有多个切分方案S对应,分词的任务就是在这些S中找出概率最大的一个切分方案,也就是对输入字符串切分出最有可能的词序列。
例如对于输入字符串C"有意见分歧",有S1和S2两种切分可能。
S1:有/ 意见/ 分歧/
S2:有意/ 见/ 分歧/
计算条件概率P(S1|C)和P(S2|C),然后采用概率大的值对应的切分方案。根据贝叶斯公式,有。
其中P(C)是字符串在语料库中出现的概率,只是一个用来归一化的固定值。从词串恢复到汉字串的概率只有唯一的一种方式,所以P(C|S)=1。因此,比较P(S1|C)和P(S2|C)的大小变成比较P(S1)和P(S2)的大小。
概率语言模型分词的任务是:在全切分所得的所有结果中求某个切分方案S,使得P(S)最大。那么,如何来表示P(S)呢?为了容易实现,假设每个词之间的概率是上下文无关的,则:
P(S)一般是通过很多小数值的连乘积算出来的。如果一个数太小,可能会向下溢出变成零。例如 0.000000000000000000000000000001,double类型表示不出如此小的数。因为函数y=log(x),当x增大,y也会增大,所以是单调递增函数。取log后,表示一个小于1的正数的精确度加大了。
这里的∝是正比符号。因为词的概率小于1,所以取log后是负数。最后算 logP(w)。
其中,对于不同的S,m的值是不一样的,一般来说m越大,P(S)会越小。也就是说,分出的词越多,概率越小。这符合实际的观察,如最大长度匹配切分往往会使得m较小。
这个计算P(S)的公式也叫做基于一元概率语言模型的计算公式。这种分词方法简称一元分词。它综合考虑了切分出的词数和词频。一般来说,词数少,词频高的切分方案概率更高。考虑一种特殊的情况:所有词的出现概率相同,则一元分词退化成最少词切分方法。
计算任意一个词出现的概率如下:
因此
如果词概率的对数值事前已经算出来了,则结果直接用加法就可以得到logP(S),而加法比乘法速度更快。
从另外一个角度来看,计算最大概率等于求切分词图的最短路径。但是这里不采用Dijkstra算法,而采用动态规划的方法求解最短路径。
常用的词语概率表如表4-3所示。
表4-3 词语概率表
词语 | 概率 |
… | … |
有 | 0.0180 |
有意 | 0.0005 |
意见 | 0.0010 |
见 | 0.0002 |
分歧 | 0.0001 |
… | … |
P(S1) = P(有) P(意见) P(分歧) = 1.8 × 10-9
P(S2) = P(有意) P(见) P(分歧) = 1×10-11
可得P(S1) > P(S2),所以选择S1对应的切分。
如何尽快找到概率最大的词串?因为假设每个词之间的概率是上下文无关的,因此满足用动态规划求解所要求的最优子结构性质和无后效性。在动态规划求解的过程中并没有先生成所有可能的切分路径Si,而是求出值最大的P(Si)后,利用回溯的方法直接输出Si。
到节点Nodei为止的最大概率称为节点Nodei的概率:
如果Wj的结束节点是Nodei,就称Wj为Nodei的前驱词。这里的prev(Nodei)就是节点i的前驱词集合。
比如上面的例子中,候选词"有"就是节点1的前驱词,"意见"和"见"都是节点3的前驱词。
StartNode(wj)是wj 的开始节点,也是节点i的前驱节点。
因此切分的最大概率max(P(S))就是P(Nodem)=P(节点m的最佳前驱节点) P(节点m的最佳前驱词)。