近日研究 Ansj 分词,准备吃透它,在此记录每日学习、查询资料所得,用来备忘。
详细的思维导图请参见资源:http://download.csdn.net/download/huoxue_2012/10129605
绝大部分资料都是来源于网络,其中主要是一些国内外大学的论文、吴军先生的《数学之美》、码农网站等,最终在这篇博客中把从中获取的知识用我自己的话写了出来,如果有不合时宜的引用,请留言指出,谢谢。
一、Ansj 所用的 CRF分词模型,数据结构为双数组的 Trie 树,有用到隐含马尔可夫模型和最大熵模型。
1、先谈谈什么是Trie 树吧。
如图,词典的中的词语在 Trie 中保存如图所示,Root为根节点,对应Ansj中的Forest,其它的节点对应Ansj的 branch,图中紫色部分为起始节点,不能算作词语,在Ansj中设置为Status=1;蓝色部分为中间节点,表示即可以作为一个词的结尾,也可以是另一个词的中间的字,在Ansj中设置为Status=2;红色部分为结束节点,表示是词语,并且到此结束,在Ansj中设置为Status=3。
另外,Ansj中还有 Status=4 和 Status=5的情况。Status=4 表示 圆半角英文字母及';Status=5表示 数字、小数点、百分号。
查询和插入的逻辑都是二分查找,即从上往下遍历,分词做查询时会找最长的词语。如在本例中,会找到“中国人民”,而不是“中国”和“中国人”。所以说 Trie 分词并不是很准确。
删除时,比较取巧,直接将该词的结束节点(红色)改为起始节点(紫色),这样从上往下就找不到这个词了。
2、再谈谈什么是双数组的 Trie树吧
打开 Ansj 的 core.dic 中可以看见如图所示的 6 个参数:
先看 term,它并不是一个词,而是词的当前状态,如“一举一”是“一举一动”的前缀而不是一个词
status 为词的状态,如上面 Trie所述,status=1代表继续,status=2代表是个词语但是还可以继续向下,status=3代表是个词语并且结束。
index 和 base 我还没有完全区分清楚,先在此记录当前我的理解。最初单个字的 index为它的 Unicode码,如“动”的 Unicode 码为 21160,而多个字符的 index就为每个组成他的Unicode码相加
,即 index(一举一动)= index(一)+index(举)+index(一)+index(动);check为上一前缀的 index,如图中,“一举一动”的check为“一举一”的index值。也就是说 index(一举一动) =
check(一举一动) + index(动),即check(一举一动) = index(一举一),在图中:86697 = 65536+21160 。