【问题标题】:Stemming English words with Lucene使用 Lucene 提取英语单词
【发布时间】:2011-07-20 11:53:12
【问题描述】:

我正在一个 Java 应用程序中处理一些英文文本,我需要对它们进行词干处理。 例如,从文本“amenities/amenity”我需要得到“amenit”。

函数如下:

String stemTerm(String term){
   ...
}

我找到了 Lucene Analyzer,但它看起来太复杂了,无法满足我的需求。 http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/analysis/PorterStemFilter.html

有没有办法在不构建分析器的情况下使用它来词干?我不了解所有 Analyzer 业务...

编辑:我实际上需要词干提取+词形还原。 Lucene 可以做到这一点吗?

【问题讨论】:

  • 为什么你需要自己阻止这些词? Lucene 有一个名为 SnowballAnalyzer 的分析器,您只需使用词干分析器名称对其进行实例化,例如new SnowballAnalyzer("English");.

标签: java lucene stemming porter-stemmer


【解决方案1】:
import org.apache.lucene.analysis.PorterStemmer;
...
String stemTerm (String term) {
    PorterStemmer stemmer = new PorterStemmer();
    return stemmer.stem(term);
}

请参阅here 了解更多详情。如果您只想使用词干提取,那么您应该使用 this 而不是 Lucene。

编辑:您应该在将term 传递给stem() 之前将其小写。

【讨论】:

  • 是否可以将停用词过滤器与词干分析器结合起来?
  • 您想从包含多个单词的字符串中过滤停用词,还是已经标记(分隔)了这些单词并只想检查一个单词?如果它只是像上面这样的一个术语,那么只需创建一个包含所有停用词的 Set 并执行一个 .contains()
  • 从当前版本的 Lucene (3.5) 开始,PorterStemmer 虽然存在,但不是公开的。我不确定谁/什么使用它,但我们不能。
  • PorterStemmer 不再公开(愚蠢地) - 另见stackoverflow.com/questions/15422485/…
【解决方案2】:

您为什么不使用“EnglishAnalyzer”?使用起来很简单,我认为它可以解决您的问题:

EnglishAnalyzer en_an = new EnglishAnalyzer(Version.LUCENE_34);
QueryParser parser = new QueryParser(Version.LUCENE_34, "your_field", en_an);
String str = "amenities";
System.out.println("result: " + parser.parse(str)); //amenit

希望对你有帮助!

【讨论】:

  • 这个“your_field”在做什么?文档中有一个神秘的“查询词的默认字段”。
  • 这将其分解为文字,但不会停止。至少不适合我。
  • 它做了非常基本的词干提取。它不需要开始并改变它开始。
【解决方案3】:

前面的示例将词干应用于搜索查询,因此如果您对全文词干感兴趣,可以尝试以下操作:

import java.io.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.tokenattributes.*;
import org.apache.lucene.analysis.snowball.*;
import org.apache.lucene.util.*;
...
public class Stemmer{
    public static String Stem(String text, String language){
        StringBuffer result = new StringBuffer();
        if (text!=null && text.trim().length()>0){
            StringReader tReader = new StringReader(text);
            Analyzer analyzer = new SnowballAnalyzer(Version.LUCENE_35,language);
            TokenStream tStream = analyzer.tokenStream("contents", tReader);
            TermAttribute term = tStream.addAttribute(TermAttribute.class);

            try {
                while (tStream.incrementToken()){
                    result.append(term.term());
                    result.append(" ");
                }
            } catch (IOException ioe){
                System.out.println("Error: "+ioe.getMessage());
            }
        }

        // If, for some reason, the stemming did not happen, return the original text
        if (result.length()==0)
            result.append(text);
        return result.toString().trim();
    }

    public static void main (String[] args){
        Stemmer.Stem("Michele Bachmann amenities pressed her allegations that the former head of her Iowa presidential bid was bribed by the campaign of rival Ron Paul to endorse him, even as one of her own aides denied the charge.", "English");
    }
}

TermAttribute 类已被弃用,Lucene 4 将不再支持,但文档并不清楚在其位置使用什么。

此外,在第一个示例中,PorterStemmer 不能作为类(隐藏)使用,因此您不能直接使用它。

希望这会有所帮助。

【讨论】:

  • Giancarlo 的回答是正确的,因为 TermAttribute 已被弃用,因此将 TermAttribute 更改为 CharTermAttribute。
【解决方案4】:

Ling pipe 提供了许多分词器。它们可用于词干提取和停用词删除。它是一种简单而有效的词干提取方法。

【讨论】:

    【解决方案5】:

    SnowballAnalyzer 已弃用,您可以改用 Lucene Porter Stemmer:

     PorterStemmer stem = new PorterStemmer();
     stem.setCurrent(word);
     stem.stem();
     String result = stem.getCurrent();
    

    希望对您有所帮助!

    【讨论】:

    【解决方案6】:

    以下是在 JAVA 中使用 Snowball Stemmer 的方法:

    import org.tartarus.snowball.ext.EnglishStemmer;
    
    EnglishStemmer english = new EnglishStemmer();
    String[] words = tokenizer("bank banker banking");
    for(int i = 0; i < words.length; i++){
            english.setCurrent(words[i]);
            english.stem();
            System.out.println(english.getCurrent());
    }
    

    【讨论】:

      【解决方案7】:

      由于 PorterStemmer 不是公开的,我们不能调用 PorterStemmer 的 stem 函数。

      相反,我们可以使用 KStemmer/KStemFilter 将词提取到词根。

      下面是scala代码sn-p,它接受字符串并转换为词干字符串

      导入 org.apache.lucene.analysis.core.WhitespaceTokenizer 导入 org.apache.lucene.analysis.en.KStemFilter

      导入 java.io.StringReader

      对象词干{ def stem(input:String):String={

      val stemmed_string = new StringBuilder()
      
      val inputReader = new StringReader(input.toLowerCase)
      
      val whitespaceTokenizer = new WhitespaceTokenizer()
      whitespaceTokenizer.setReader(inputReader)
      
      val kStemmedTokenStream = new KStemFilter(whitespaceTokenizer)
      import org.apache.lucene.analysis.tokenattributes.CharTermAttribute
      
      val charTermAttribute = kStemmedTokenStream.addAttribute(classOf[CharTermAttribute])
      
      kStemmedTokenStream.reset
      while (kStemmedTokenStream.incrementToken) {
        val term = charTermAttribute.toString
        stemmed_string.append(term+" ")
      }
      stemmed_string.toString().trim.toUpperCase
      

      }

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-23
        • 2010-10-01
        • 1970-01-01
        • 2014-05-19
        • 1970-01-01
        • 2018-11-03
        相关资源
        最近更新 更多