6

私は自分自身を構築したいと思います-ここではどちらかがわかりません-トークナイザー(Luceneの観点から)または私自身のアナライザー。私はすでに自分のドキュメントを単語でトークン化するコードを書いています(リスト<文字列>またはリスト<単語>として、Wordは3つのパブリック文字列を持つ一種のコンテナのみを持つクラスです:word、pos、lemma-posは品詞を表します-品詞タグ)。

何にインデックスを付けるのかわからない。おそらく「Word.lemma」または「Word.lemma+'#' + Word.pos」のようなものだけだろう。おそらく、品詞に基づいてストップワードリストからフィルタリングを行うだろう。 -品詞。

ところで、ここに私の誤解があります:私はLuceneAPIにどこに接続すべきかわかりません、

自分のトークナイザーを新しいトークナイザー内にラップする必要がありますか?TokenStreamを書き直す必要がありますか?これはトークナイザーではなくアナライザーの仕事であると考えるべきですか?または、すべてをバイパスして、IndexWriter、Fieldableなどを使用して、インデックス内に単語を直接追加して、インデックスを直接作成する必要がありますか?(もしそうなら、分析プロセスをバイパスするときに独自のインデックスを最初から作成する方法に関するドキュメントを知っていますか)

よろしくお願いします

編集:最も簡単な方法は、個人のトークナイザー/アナライザーの出口にスペースを入れてWord -sにorg.apache.commons.lang.StringUtils.joinし、Lucene(およびその他の従来のフィルター)にフィードするためにWhiteSpaceTokenizerに依存することです。 )?

編集:それで、私はLarsmansによって指摘されたEnglishLemmaTokenizerを読みまし...しかし、私がまだ混乱しているのは、完全な* List <Word> *(Word class wrapping.form /で自分の分析/トークン化プロセスを終了するという事実です。 pos / .lemma)、このプロセスは、Javaでラップした外部バイナリに依存しています(これは必須です/そうでない場合はできません-消費者の観点ではなく、結果として完全なリストを取得します)そして、通常のLucene分析プロセスに戻るために、どのように再度ラップする必要があるのか​​まだわかりません。

また、スコアリングのようにTF.IDFでTermVector機能を使用します(自分自身を再定義する可能性があります)。また、近接検索に興味があるかもしれません。したがって、Luceneに提供する前に品詞からいくつかの単語を破棄します。組み込みのトークナイザーまたは内部アナライザーは悪い考えに思えるかもしれません。そして、Word.form / Word.pos / Word.lemma(または他のWord.anyOtherUnterestingAttribute)をLuceneの方法にラップする「適切な」方法を考えるのは困難です。

編集: ところで、これは私が@Larsmansの1つに触発されて書いたコードの一部です:

class MyLuceneTokenizer extends TokenStream {

    private PositionIncrementAttribute posIncrement;
    private CharTermAttribute termAttribute;

    private List<TaggedWord> tagged;
    private int position;

    public MyLuceneTokenizer(Reader input, String language, String pathToExternalBinary) {
        super();

        posIncrement = addAttribute(PositionIncrementAttribute.class);
        termAttribute = addAttribute(CharTermAttribute.class); // TermAttribute is deprecated!

        // import com.google.common.io.CharStreams;            
        text = CharStreams.toString(input); //see http://stackoverflow.com/questions/309424/in-java-how-do-i-read-convert-an-inputstream-to-a-string
        tagged = MyTaggerWrapper.doTagging(text, language, pathToExternalBinary);
        position = 0;
    }

    public final boolean incrementToken()
            throws IOException {
        if (position > tagged.size() -1) {
            return false;
        }

        int increment = 1; // will probably be changed later depending upon any POS filtering or insertion @ same place...
        String form = (tagged.get(position)).word;
        String pos = (tagged.get(position)).pos;
        String lemma = (tagged.get(position)).lemma;

        // logic filtering should be here...
        // BTW we have broken the idea behing the Lucene nested filters or analyzers! 
        String kept = lemma;

        if (kept != null) {
            posIncrement.setPositionIncrement(increment);
            char[] asCharArray = kept.toCharArray();
            termAttribute.copyBuffer(asCharArray, 0, asCharArray.length);
            //termAttribute.setTermBuffer(kept);
            position++;
        }

        return true;
    }
}

class MyLuceneAnalyzer extends Analyzer {
    private String language;
    private String pathToExternalBinary;

    public MyLuceneAnalyzer(String language, String pathToExternalBinary) {
        this.language = language;
        this.pathToExternalBinary = pathToExternalBinary;
    }

    @Override
    public TokenStream tokenStream(String fieldname, Reader input) {
        return new MyLuceneTokenizer(input, language, pathToExternalBinary);
    }
}
4

2 に答える 2

1

ここにはさまざまなオプションがありますが、Lucene で POS タガーをラップしようとしたとき、new を実装し、それを newTokenStream内にラップするAnalyzerのが最も簡単なオプションであることがわかりました。いずれにせよ、IndexWriter直接いじるのは悪い考えのようです。私のコードは私の GitHub にあります。

于 2012-05-18T09:02:36.663 に答える
1

UIMA を使用する場合は、Salmon Run にがあります。しかし、Lucene contrib モジュール内に UIMA ワークフローを含めるための取り組みがあります。こちらこちらを参照してください。

于 2012-09-10T07:38:06.400 に答える