4

Lucene 4.0 から 4.1 にアップグレードした後、ソリューションのパフォーマンスが桁違いに低下しました。直接の原因は、格納されたフィールドの無条件の圧縮です。今のところ、私は 4.0 に戻していますが、これは明らかに前に進む方法ではありません。私は自分の解決策への別のアプローチを見つけたいと思っています。

私は Lucene をデータベース インデックスとして使用しています。つまり、格納されているフィールドは非常に短く、せいぜい数語しかありません。

CustomScoreQuerywhereを使用して、CustomScoreProvider#customScoreすべての候補ドキュメントを最終的に読み込み、クエリに対して詳細な単語類似度スコアを実行します。2 つのレベルのヒューリスティックを使用して ( Dice の係数に基づいて) 候補ドキュメント セットを絞り込みましたが、最後のステップで、各クエリ ワードを各ドキュメント ワード (異なる順序である可能性があります) と照合し、合計スコアを計算する必要があります。最適な単語一致の合計に基づいています。

クエリの評価中に圧縮されたフィールドをロードするという落とし穴を回避する方法で、これに別の方法でアプローチし、計算を行うにはどうすればよいでしょうか?

4

2 に答える 2

2

では、インデックスで使用されるストレージ メソッドを定義IndexWriterConfigした を渡すことができます。Codecこれは、IndexWriterが構築されたときにのみ有効になります (つまり、構築後に構成を変更しても効果はありません)。を使用したいと思うでしょうLucene40Codec

何かのようなもの:

//You could also simply pass in Version.LUCENE_40 here, and not worry about the Codec
//(though that will likely affect other things as well)
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_41, analyzer);
config.setCodec(new Lucene40Codec());
IndexWriter writer = new IndexWriter(directory, config);

を直接使用Lucene40StoredFieldsFormatして、圧縮されていない古い保存済みフィールド形式を取得し、それをカスタム Codec 実装から戻すこともできます。からほとんどのコードを取得して、メソッドLucene41Codecを置き換えるだけでよいでしょう。storedFieldFormat()よりターゲットを絞ったアプローチかもしれませんが、少し複雑で、他の問題に遭遇する可能性があるかどうかはわかりません.

カスタム コーデックの作成に関する追加の注意事項。これを達成する必要があることを API が示す方法は、FilterCodec を拡張し、それらの例を少し変更して適合させることです。

public final class CustomCodec extends FilterCodec {

 public CustomCodec() {
   super("CustomCodec", new Lucene41Codec());
 }

 public StoredFieldsFormat storedFieldsFormat() {
   return new Lucene40StoredFieldsFormat();
 }

}


もちろん、頭に浮かぶ他の実装は次のとおりです。

同様に、問題が「最終的にすべての候補ドキュメントをロードする」ことにあることは明らかだと思います。完全な詳細や理解を持っていないスコアリングの実装については、あまり編集しませんが、Lucene のアーキテクチャに対して、あなたが望むようにするために戦っているように思えます。一般に、格納されたフィールドはスコアリングに使用されるべきではありません。また、4.0 の格納されたフィールド形式を使用すると、結果としてパフォーマンスが著しく低下することが予想されますが、程度は多少低くなります。スコアリング アルゴリズムの観点から、またはドキュメント構造の観点から、格納されたフィールドに基づいてドキュメントをスコアリングする必要をなくす、より良い実装があるでしょうか?

于 2013-02-13T17:34:08.870 に答える
0

Lucene 3.x では、次のようになりました。

new CustomScoreQuery(bigramQuery, new FieldScoreQuery("bigram-count", Type.BYTE)) {
  protected CustomScoreProvider getCustomScoreProvider(IndexReader ir) {
    return new CustomScoreProvider(ir) {
      public double customScore(int docnum, float bigramFreq, float docBigramCount) {
         ... calculate Dice's coefficient using bigramFreq and docBigramCount...
         if (diceCoeff >= threshold) {
           String[] stems = ir.document(docnum).getValues("stems");
           ... calculate document similarity score using stems ...
         }
      }
    };
  }
}

floatこのアプローチにより、保存されたフィールドからキャッシュされた値を効率的に取得できました。これを使用して、ドキュメントのバイグラム カウントを取得しました。文字列を取得できなかったため、ドキュメントの類似性スコアを計算するために必要なものを取得するために、ドキュメントをロードする必要がありました。保存されたフィールドを圧縮するように Lucene 4.1 が変更されるまでは、問題なく機能していました。

Lucene 4 の拡張機能を活用する適切な方法は、次のDocValuesように含めることです。

new CustomScoreQuery(bigramQuery) {
  protected CustomScoreProvider getCustomScoreProvider(ReaderContext rc) {
    final AtomicReader ir = ((AtomicReaderContext)rc).reader();
    final ValueSource 
       bgCountSrc = ir.docValues("bigram-count").getSource(),
       stemSrc = ir.docValues("stems").getSource();
    return new CustomScoreProvider(rc) {
      public float customScore(int docnum, float bgFreq, float... fScores) {
        final long bgCount = bgCountSrc.getInt(docnum);
        ... calculate Dice's coefficient using bgFreq and bgCount ...
        if (diceCoeff >= threshold) {
          final String stems = 
             stemSrc.getBytes(docnum, new BytesRef())).utf8ToString();
          ... calculate document similarity score using stems ...
        }
      }
    };
  }
}

これにより、パフォーマンスが 16 ミリ秒 (Lucene 3.x) から 10 ミリ秒 (Lucene 4.x) に向上しました。

于 2013-02-17T15:03:29.700 に答える