问题:
我试验了一下文章中提到的 stemming 和 lemmatization
- 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。
- 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization。
试验没有成功
代码如下:
public class TestNorms { public void createIndex() throws IOException { Directory d = new SimpleFSDirectory(new File("d:/falconTest/lucene3/norms")); IndexWriter writer = new IndexWriter(d, new StandardAnalyzer(Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED); Field field = new Field("desc", "", Field.Store.YES, Field.Index.ANALYZED); Document doc = new Document(); field.setValue("Hello students was drive"); doc.add(field); writer.addDocument(doc); writer.optimize(); writer.close(); } public void search() throws IOException { Directory d = new SimpleFSDirectory(new File("d:/falconTest/lucene3/norms")); IndexReader reader = IndexReader.open(d); IndexSearcher searcher = new IndexSearcher(reader); TopDocs docs = searcher.search(new TermQuery(new Term("desc","drove")), 10); System.out.println(docs.totalHits); } public static void main(String[] args) throws IOException { TestNorms test= new TestNorms(); test.createIndex(); test.search(); } }
|
不管是单复数,还是单词的变化,都是没有体现的
不知道是不是分词器的原因?
回答:
的确是分词器的问题,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 { @Override public TokenStream tokenStream(String fieldName, Reader reader) { return new PorterStemFilter(new LowerCaseTokenizer(reader)); } }
|
把此分词器用在你的程序中,就能够识别单复数和规则的词型变化了。
public void createIndex() throws IOException { Directory d = new SimpleFSDirectory(new File("d:/falconTest/lucene3/norms")); IndexWriter writer = new IndexWriter(d, new PorterStemAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);
Field field = new Field("desc", "", Field.Store.YES, Field.Index.ANALYZED); Document doc = new Document(); field.setValue("Hello students was driving cars professionally"); doc.add(field);
writer.addDocument(doc); writer.optimize(); writer.close(); }
public void search() throws IOException { Directory d = new SimpleFSDirectory(new File("d:/falconTest/lucene3/norms")); IndexReader reader = IndexReader.open(d); IndexSearcher searcher = new IndexSearcher(reader); TopDocs docs = searcher.search(new TermQuery(new Term("desc", "car")), 10); System.out.println(docs.totalHits); docs = searcher.search(new TermQuery(new Term("desc", "drive")), 10); System.out.println(docs.totalHits); docs = searcher.search(new TermQuery(new Term("desc", "profession")), 10); System.out.println(docs.totalHits); }
|
(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 install
After 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 install
Next 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> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <turglem/lemmatizer.h> #include <turglem/lemmatizer.hpp> #include <turglem/english/charset_adapters.hpp>
int main(int argc, char **argv) { char in_s_buf[1024]; char *nl_ptr;
tl::lemmatizer lem;
if(argc != 4) { printf("Usage: %s words.dic predict.dic flexias.bin\n", argv[0]); return -1; }
lem.load_lemmatizer(argv[1], argv[3], argv[2]);
while (!feof(stdin)) { fgets(in_s_buf, 1024, stdin); nl_ptr = strchr(in_s_buf, '\n'); if (nl_ptr) *nl_ptr = 0; nl_ptr = strchr(in_s_buf, '\r'); if (nl_ptr) *nl_ptr = 0;
if (in_s_buf[0]) { printf("processing %s\n", in_s_buf); tl::lem_result pars; size_t pcnt = lem.lemmatize<english_utf8_adapter>(in_s_buf, pars); printf("%d\n", pcnt); for (size_t i = 0; i < pcnt; i++) { std::string s; u_int32_t src_form = lem.get_src_form(pars, i); s = lem.get_text<english_utf8_adapter>(pars, i, 0); printf("PARADIGM %d: normal form '%s'\n", (unsigned int)i, s.c_str()); printf("\tpart of speech:%d\n", lem.get_part_of_speech(pars, (unsigned int)i, src_form)); } } }
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 processing drove 3 PARADIGM 0: normal form 'DROVE' part of speech:0 PARADIGM 1: normal form 'DROVE' part of speech:2 PARADIGM 2: normal form 'DRIVE' part of speech:2
was processing was 3 PARADIGM 0: normal form 'BE' part of speech:3 PARADIGM 1: normal form 'BE' part of speech:3 PARADIGM 2: normal form 'BE' part of speech:3
|
分享到:
相关推荐
这个过程包括分词(Tokenization)、词干提取(Stemming)和词性还原(Lemmatization)等,目的是提高搜索速度和准确性。 2. **文档(Document)**:在Lucene中,每个文档代表要索引的信息单元,可以是一个网页、...
- Stemming和Lemmatization的区别及其在全文检索中的应用。 - 向量空间模型与Lucene的打分机制之间的联系。 - 影响Lucene文档评分的多种因素。 - Lucene中的TooManyClauses异常及其解决方法。 通过上述内容的学习,...
2. **词干提取(Stemming)与词形还原(Lemmatization)的区别**:词干提取旨在减少词汇的变体形式到其基本形式,而词形还原则是将词汇还原为其字典形式,通常更准确但也更复杂。 3. **向量空间模型与 Lucene 的...
同时,它还会执行其他预处理操作,如去除停用词(Stopwords)、词干提取(Stemming)和词形还原(Lemmatization)。 3. **建立倒排索引**:每个词被分配一个唯一的ID,然后记录这个词在哪些文档中出现,以及在这些...
在本文中,我们将探讨如何使用Lucene建立数据库索引,并分享一些在实践过程中的经验和教训。Lucene是一个高性能、全文本搜索库,广泛用于构建搜索引擎。在创建索引时,需要注意以下关键点: 1. **资料的准确性**:...
1. 文档分析与预处理:Lucene首先对输入的文本进行分词(Tokenization),然后去除停用词(Stopword Removal)和标点符号,进行词干提取(Stemming)和词形还原(Lemmatization),以便减少词汇变化对搜索的影响。...
令牌修改阶段包括了各种过滤操作,如词形还原(Lemmatization)、停用词去除(Stop Word Removal)、词干提取(Stemming)等。这些操作旨在减少索引的大小,提高搜索效率,并增强查询的相关性。词形还原将词还原到其基本...
它包括分词(Tokenization)、去除停用词(Stop Word Removal)、词干提取(Stemming)和词形还原(Lemmatization)等。分词是将句子拆分成单个词汇;去除停用词是为了减少无意义的词对搜索结果的影响;词干提取和词...
通过Lucene,开发者可以轻松地在大量数据中快速定位到相关信息。 Heritrix是另一个开源项目,它是一个网络抓取器,用于爬取互联网上的网页,收集数据以供后续处理,如搜索引擎的索引构建。Heritrix提供了一种可配置...
另外,stemming(词干提取)和lemmatization(词形还原)是两种不同的文本预处理方式,它们影响查询的精度和召回率。在构建实时索引时,为了保持系统的响应速度,需要对索引策略进行优化,以达到快速更新索引的目的...
这通常包括分词(Tokenization)、去除停用词(Stopword Removal)、词干提取(Stemming)和词形还原(Lemmatization)。例如,在 LuceneDemo1 中,我们可能会看到一个定制的 Analyzer 类,用于处理特定语言或领域的...
这一步可能包括去除停用词(如“the”, “and”等)、词干提取(stemming)、词形还原(lemmatization)等操作,以减少词项数量并提高检索效率。 **第四步:索引组件(Indexer)** 经过处理后的词项被传送给索引...
此外,Lucene的分词策略(stemming和lemmatization)和文档打分机制也会影响最终的搜索结果。为了解决这些问题,需要深入理解Lucene的内部工作机制,并对索引过程和查询策略进行适当调整。 综上所述,全文检索技术...
3. **文本预处理**:包括去除停用词(如“的”、“和”等常见词汇)、词干提取(Stemming)和词形还原(Lemmatization),目的是减少词汇变体,提高搜索准确性。 4. **查询解析(Query Parsing)**:将用户的输入...
5. **文本分析和预处理**:包括去除停用词(Stop Words)、词干提取(Stemming)和词形还原(Lemmatization)等文本处理技术。 6. **性能优化**:如何通过调整索引策略、查询优化和硬件配置来提升检索速度和效率。 ...
标签"stem_ja"可能是指这个程序是针对英文("ja"可能是指“Java”或“Japanese”,但描述中明确指出是英文处理)的,并且与词干提取(Stemming)有关。Java作为一种多平台的、面向对象的编程语言,提供了丰富的库和...
在探讨搜索引擎中的分词技术和查找机制之前,我们首先需要理解几个基本概念:分词(Tokenization)、词干提取(Stemming)和词形还原(Lemmatization)。这些技术是构建高效、准确搜索引擎的核心。 #### 一、分词...