4

私はfieldNorm、(インデックス時に)計算され、クエリ時にどのように使用されるか(そして明らかに再計算されるか)を理解しようとしています。

すべての例で、ストップワードなしでStandardAnalyzerを使用しています。

DefaultSimilarityインデックスを作成しているときに'sメソッドを削除するcomputeNormと、2つの特定のドキュメントに対して次のように返されることに気付きました。

  • ドキュメントAの場合は0.5(フィールドに4つのトークンがあります)
  • ドキュメントBの場合は0.70710677(フィールドに2つのトークンがあります)

これは、次の式を使用して行います。

state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)));

ここで、ブーストは常に1です。

その後、これらのドキュメントをクエリすると、クエリの説明で次のようになります。

  • 0.5 = fieldNorm(field=titre, doc=0)ドキュメントAの場合
  • 0.625 = fieldNorm(field=titre, doc=1)ドキュメントBの場合

これはすでに奇妙です(私にとって、何かが欠けているのは私だと確信しています)。インデックス時に計算された値と同じフィールドノルムの値を取得しないのはなぜですか?これは実際の「クエリの正規化」のことですか?もしそうなら、それはどのように機能しますか?

ただし、2つのクエリ時のfieldNormは、インデックス時に計算されたものと同じ順序になるため、これは多かれ少なかれ問題ありません(どちらの場合も、値が短いフィールドほどfieldNormが高くなります)。

次に、次のようにcomputeNormsメソッドを実装した独自のSimilarityクラスを作成しました。

public float computeNorm(String pField, FieldInvertState state) {
    norm = (float) (state.getBoost() + (1.0d / Math.sqrt(state.getLength())));
    return norm;
}

インデックス時に、次のようになります。

  • ドキュメントAの場合は1.5(フィールドに4つのトークンがあります)
  • ドキュメントBの場合は1.7071068(フィールドに2つのトークンがあります)

ただし、これらのドキュメントをクエリすると、explain関数によって報告されたものと同じフィールドノルムが両方にあることがわかります。

  • 1.5 = fieldNorm(field=titre, doc=0)ドキュメントAの場合
  • 1.5 = fieldNorm(field=titre, doc=1)ドキュメントBの場合

私にとって、これは本当に奇妙なことです。インデックス時にfieldNormを計算するために明らかに良い類似性を使用すると、トークンの数に比例する適切な値が得られ、後でクエリ時にすべてが失われ、クエリは、両方のドキュメントが同じフィールドノルムを持っていると言いますか?

だから私の質問は:

  • 類似性のcomputeNormメソッドによって報告されたインデックス時間fieldNormが、クエリの説明によって報告されたものと同じままにならないのはなぜですか?
  • なぜ、インデックス時に(類似性computeNormを介して)取得された2つの異なるfieldNorm値に対して、クエリ時に同一のfieldNorm値を取得するのですか?

==更新

わかりました。Luceneのドキュメントで、私の質問の一部を明確にするものを見つけましたが、すべてではありません。

ただし、結果のノルム値は、保存される前に1バイトとしてエンコードされます。検索時に、ノルムバイト値がインデックスディレクトリから読み取られ、floatノルム値にデコードされます。このエンコード/デコードは、インデックスサイズを縮小しますが、精度が低下するという代償を伴います。decode(encode(x))=xであるとは限りません。たとえば、decode(encode(0.89))=0.75です。

どのくらいの精度の損失がありますか?精度損失の再計算後も値が異なるままになるように、異なる値の間に配置する必要のある最小のギャップはありますか?

4

1 に答える 1

4

encodeNormValueのドキュメントでは、エンコード手順(精度が失われる場所)、特に値の最終的な表現について説明しています。

エンコーディングでは、3ビットの仮数、5ビットの指数、および15のゼロ指数ポイントを使用するため、約7x10^9から2x10^-9までの値を、小数点以下1桁の精度で表します。ゼロも表されます。負の数はゼロに切り上げられます。大きすぎて表現できない値は、表現可能な最大値に切り捨てられます。小さすぎて表現できない正の値は、正の表現可能な最小値に切り上げられます。

仮数がわずか3ビットであることを理解するための最も関連性の高い部分。つまり、精度は小数点以下1桁程度です。

理論的根拠に関する重要な注意点は、引用が終わった後、Luceneのドキュメントに次のように書かれている数文です。

ノルム値のこのような不可逆圧縮をサポートする理論的根拠は、ユーザーがクエリによって真の情報の必要性を表現するのが困難(および不正確)であることを考えると、大きな違いだけが重要であるということです。

于 2013-02-28T19:24:47.667 に答える