问题:
我试验了一下文章中提到的 stemming 和 lemmatization
- 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。
- 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization。
试验没有成功
代码如下:
public class TestNorms { |
不管是单复数,还是单词的变化,都是没有体现的
不知道是不是分词器的原因?
回答:
的确是分词器的问题,StandardAnalyzer并不能进行stemming和lemmatization,因而不能够区分单复数和词型。
文章中讲述的是全文检索的基本原理,理解了他,有利于更好的理解Lucene,但不代表Lucene是完全按照此基本流程进行的。
(1) 有关stemming
作为stemming,一个著名的算法是The Porter Stemming Algorithm,其主页为http://tartarus.org/~martin/PorterStemmer/,也可查看其论文http://tartarus.org/~martin/PorterStemmer/def.txt。
通过以下网页可以进行简单的测试:Porter's Stemming Algorithm Online[http://facweb.cs.depaul.edu/mobasher/classes/csc575/porter.html]
cars –> car
driving –> drive
tokenization –> token
然而
drove –> drove
可见stemming是通过规则缩减为词根的,而不能识别词型的变化。
在最新的Lucene 3.0中,已经有了PorterStemFilter这个类来实现上述算法,只可惜没有Analyzer向匹配,不过不要紧,我们可以简单实现:
public class PorterStemAnalyzer extends Analyzer |
把此分词器用在你的程序中,就能够识别单复数和规则的词型变化了。
public void createIndex() throws IOException { Field field = new Field("desc", "", Field.Store.YES, Field.Index.ANALYZED); writer.addDocument(doc); public void search() throws IOException { |
(2) 有关lemmatization
至于lemmatization,一般是有字典的,方能够由"drove"对应到"drive".
在网上搜了一下,找到European languages lemmatizer[http://lemmatizer.org/],只不过是在linux下面C++开发的,有兴趣可以试验一下。
首先按照网站的说明下载,编译,安装:
libMAFSA is the core of the lemmatizer. All other libraries depend on it. Download the last version from the following page, unpack it and compile: # tar xzf libMAFSA-0.2.tar.gz # cd libMAFSA-0.2/ # cmake . # make # sudo make installAfter this you should install libturglem. You can download it at the same place. # tar xzf libturglem-0.2.tar.gz # cd libturglem-0.2 # cmake . # make # sudo make installNext you should install english dictionaries with some additional features to work with. # tar xzf turglem-english-0.2.tar.gz # cd turglem-english-0.2 # cmake . # make # sudo make install |
安装完毕后:
- /usr/local/include/turglem是头文件,用于编译自己编写的代码
- /usr/local/share/turglem/english是字典文件,其中lemmas.xml中我们可以看到"drove"和"drive"的对应,"was"和"be"的对应。
- /usr/local/lib中的libMAFSA.a libturglem.a libturglem-english.a libtxml.a是用于生成应用程序的静态库
<l id="DRIVE" p="6" /> <l id="DROVE" p="6" /> <l id="DRIVING" p="6" /> |
在turglem-english-0.2目录下有例子测试程序test_utf8.cpp
#include <stdio.h> int main(int argc, char **argv) tl::lemmatizer lem; if(argc != 4) lem.load_lemmatizer(argv[1], argv[3], argv[2]); while (!feof(stdin)) if (in_s_buf[0]) return 0; |
编译此文件,并且链接静态库:注意链接顺序,否则可能出错。
g++ -g -o output test_utf8.cpp -L/usr/local/lib/ -lturglem-english -lturglem -lMAFSA –ltxml |
运行编译好的程序:
./output /usr/local/share/turglem/english/dict_english.auto /usr/local/share/turglem/english/prediction_english.auto /usr/local/share/turglem/english/paradigms_english.bin |
做测试,虽然对其机制尚不甚了解,但是可以看到lemmatization的作用:
drove was |