分词后记(一)——自己动手写了一个支持Lucene的简单分词器XinAnalyzer

用lucene的时候,看见了一个叫SmartChineseAnalyzer的支持中文分词,效果不咋的,发现竟然用的HMM分词。

当时一句"我的天",HMM要是都算Smart,我的BiLSTM+CRF那可以是Intelligent了,于是就想自己也写一个。
具体代码可见:https://github.com/1000-7/xinlp/tree/master/src/main/java/lucene/simple
良心建议:如果真的要用lucene支持中文分词,用Hanlp或者Ansj吧还是。

Lucene分词解析

Lucene分词被封装的很严重,可能是因为考虑到线程安全、并行效率什么吧。

Analyzer

最上面一层是Analyzer层,是一个抽象类,就一个抽象方法createComponents,在这个方法里,你需要将一个Tokenizer放到返回的TokenStreamComponents对象里面。

当你传值传进去具体的文本的时候analyzer.tokenStream("content", text),他会找analyzer内部的一个TokenStreamComponents实例,如果找到的为null,就会调用createComponents方法创建。
而且不管找没找到都会将text递给TokenStreamComponents实例内部的ReusableStringReader。

TokenStreamComponents

这是一个Analyzer的内部类,主要是将分词器Tokenizer、各种文本对应的reader呀封装起来。
里面还有一个ReusableStringReader实例,是被transient的,就是为了重复使用去读文本。
上面说会找TokenStreamComponents实例,每找到就创建,等创建好了会进行components.setReader(r);操作,就是把ReusableStringReader给Tokenizer内部的reader里

这个source在构造方法被调用的时候就是Tokenizer类型

Tokenizer

Tokenizer也是一个抽象类,继承了TokenStream这个抽象类,
TokenStream里面有一个incrementToken抽象方法要实现。

而TokenStream抽象类是继承AttributeSource这个非抽象类的。
AttributeSource要做的就是分词的时候对每个词包装一些东西,当然分词肯定要知道每个词的文本,然后才能倒排呀,这时候要把CharTermAttribute类添加到TokenStream里面,你到时候去出来这个CharTermAttribute属性,才能看到分词结果。

根据需要,还有很多类似的可以被添加。

进来的Reader怎么弄


tokenizer内部有两个东西,一个要被用的input和一个用来被上面进行components.setReader(r);操作的inputPending。

所以reset方法就很重要了,继承实现的时候一定要注意调用super.reset();

分词

上面说完reader的流程,我们只要继承Tokenizerpublic class XinTokenizer extends Tokenizer,input就拿到了,所以就考虑怎么分词吧。
分词其实就是要实现incrementToken()这个抽象方法。
大概思路就是上面的input已经拿到要分的text了,不过是个Reader对象在input这个变量里,就用byte[]数组“接水”存起来int n = input.read(buffer, offset, length);就好了。
然后用自己定义的分词器XinHmmSegment segment;去分词,返回一个iterator实例就好了。

然后把返回的Atom返回到TokenStream里面添加的各种Attribute里,就OK了。

要注意的是多个句子可以用分割符去分开后,分别进行分词然后放进next里,这会有一个position的问题。

实现总结

只是用了原来的HMM分词包装进去了,效果很一般,不过能用。
这个里面封装的是真绕,折服,不过静下心来还是能想明白,慢慢体会这封装的好处吧。
过几天有时间的话,把CRF的和BiLSTM+CRF也封装进去,要是可能我也加一个添加停用词功能什么的,至于什么其他太复杂的就算了还是。

HMM是Smart,再吐槽一遍。

“分词后记(一)——自己动手写了一个支持Lucene的简单分词器XinAnalyzer”的一个回复

  1. 您之前写了一基于Socket通信的Java应用的程序,但我下下来之后,不知道应该怎么使用,因为有好几个包,可以分享一下具体的使用过程吗?您的博客内容链接地址如下:https://download.csdn.net/download/u014277388/9569056

发表评论

电子邮件地址不会被公开。