そしてここで、今ここで検索の品質に関する秘密の一つを明らかにし始めます。 これは、バージョン2.0.2-betaで追加された式ランカーと呼ばれる新しいものです(正しいロシア語の翻訳はまだ発明されていません)。これについては、もう少し詳しく説明します。 つまり、 独自のランキング式をオンザフライで設定でき、リクエストごとに個別のランキング式を設定することもできます。 一般的に、4次元のチェスやオペラ歌手と一緒に自分のMatrixNetを構築しようとする機会を全員に与えるデザイナーのようなもの。
すぐに
SphinxQLのデフォルトのランキングモード(構文を使用する拡張クエリモード用)のエミュレーションは、たとえば次のようになります。
SELECT *, WEIGHT() FROM myindex WHERE MATCH('hello world')
OPTION ranker=expr('sum(lcs*user_weight)*1000+bm25')
SphinxAPIを介して、それぞれ:
$client->SetRankingMode(SPH_RANK_EXPR, "sum(lcs*user_weight)*1000+bm25");
仕組み
ランキング式では、「通常の」式のように、ドキュメント属性と数学関数を使用できます。 しかし、ランキング式のそれらに加えて-そしてそれだけで-ランク付けに固有の値と関数がいくつかあります。 つまり、ドキュメントレベルの要素、フィールドレベルの要素、およびフィールドのセットに従ってすべてを集約する関数。 これらの追加要因はすべて、 テキストの要因であり 、それらです。 文書のテキストとリクエストに依存し、その場で計算される特定の数値。 たとえば、現在のフィールドまたはドキュメント全体で一致する一意の単語の数は、単なるテキスト要素になります。 科学では、 非テキスト要因があります 、それら。 テキストに依存しないあらゆる種類の数字。 これは、ページビューの数、製品の価格などのようなものです。 しかし、これは単純に属性に入れて、ランキングの内側と外側の両方で使用できます。 参考のために、因子はシグナルとも呼ばれます 。 それはまったく同じです。
要因は何ですか
ドキュメントレベルの要因は次のとおりです。
- bm25 、ドキュメント全体の統計関数BM25の大まかな(!)迅速な推定。 私の口径は沈黙を保つことができず、最適化のためにすべて粗くした後、実際には正規のBM25よりもBM15の可能性が高いことを通知しません。 他のすべての人にとってより理解しやすい説明:これは、0から999の範囲のある種の魔法の整数であり、ドキュメント内にまれな単語がたくさんある場合は大きくなり、頻繁な単語が多い場合は落ちます。
- max_lcs 、可能な最大値はsum(lcs * user_weight)です。 MATCH_ANYをエミュレートするために使用されますが、一般的には、正規化に役立ちます。
- field_mask 、一致するフィールドの32ビットマスク。
- query_word_count 、クエリに含まれる一意の「含まれる」キーワードの数。 つまり、「除外された」単語に合わせて調整された一意のキーワードの総数。 たとえば、クエリ(1!2)では、1になります。 単語(2)は除外され、一致することはありません。 リクエストの場合(1つ1つ!2つ)も1です。 含まれている一意の(!)単語はまだ1つだけです。 また、リクエスト(1つ2つ3つ)については、したがって、係数の値は3になります。
- doc_word_count 、現在のドキュメントで一致する一意の単語の数。 query_word_countを超えてはならないことは明らかです。
フィールドレベルの要因は次のとおりです。
- lcsは、クエリとフィールド間の「フレーズ一致」の程度を考慮する同じ魔法の要因です。 正式には、クエリおよびドキュメント内の単語の最大共通サブシーケンスの長さ。 フィールドで何も一致しなかった場合、0に等しくなります。 少なくとも何かが一致する場合は1に等しい。 クエリがフィールドに完全に一致する場合、制限内の(含まれる)クエリワードの数に等しくなります。
- user_weight 、それぞれSetFieldWeights()またはOPTION field_weightsを介して割り当てられたフィールドのユーザーの重み。
- hit_count 、一致したキーワードの出現回数。 1つのキーワードで複数のオカレンスを生成できます。 たとえば、クエリ(hello world)がhelloが3回出現し、world 5であるフィールドと一致する場合、hit_countは8になります。ただし、フレーズhello worldがフィールドで正確に1回出現する場合(単語が3および5回)+さらに、リクエストは引用符で囲まれた「hello world」であり、hit_countは2になります。単語の合計出現回数はまだ8ですが、フレーズ一致の2番目のケースでは2のみです。
- word_count 、フィールドで一致する一意の単語の数(オカレンスではありません)。 前の例では、たとえば2に等しいです。
- tf_idf 、一致するすべてのキーワードのTF * IDFの合計。 TFは単なる出現回数(用語頻度)ですが、IDFは単語の「希少性」を考慮に入れるもう1つの魔法の指標です:超頻出単語(すべてのドキュメントに含まれる)の場合は0で、一意の単語(1ドキュメントに1出現する場合)コレクション全体)は1に等しい。
- min_hit_pos 、フィールド内で最初に一致するキーワードの位置。 番号は1から始まります。たとえば、上のフィールドの先頭で一致をランク付けすると便利です。
- min_best_span_pos 、キーワードの「最適な」(最大の)lcsサブセットの最初の位置。 番号はまだ1からです。
- exact_hit 、フィールドが完全に一致した場合にコックされるブールフラグ。 値はそれぞれ0と1です。
現時点での集計関数は1つ、SUMです。 関数内の式はすべてのフィールドに対して計算され、結果が合計されます。 これらの同じSUMは、異なる式を内部に使用して、いくつか実行できます。
明らかな理由から、フィールドレベル係数は集約関数内で厳密に発生する必要があります。 最終的に、特定のフィールドに「リンク」せずに、それぞれ正確に1つの数値を計算する必要があります。このような要因には物理的な意味はありません。 もちろん、ドキュメントレベルの要素と属性は、式のどこでも使用できます。
既存のランカーをエミュレートする方法
実際、既存のすべてのランク付け者は、新しいクールな式の形で非常に単純です。 ランカーごとに最大2つの要因。 リストは次のとおりです。
- SPH_RANK_PROXIMITY_BM25 =合計(lcs * user_weight)* 1000 + bm25
- SPH_RANK_BM25 = bm25
- SPH_RANK_NONE = 1
- SPH_RANK_WORDCOUNT = sum(hit_count * user_weight)
- SPH_RANK_PROXIMITY = sum(lcs * user_weight)
- SPH_RANK_MATCHANY = sum((word_count +(lcs-1)* max_lcs)* user_weight)
- SPH_RANK_FIELDMASK = field_mask
- SPH_RANK_SPH04 =合計((4 * lcs + 2 *(min_hit_pos == 1)+ exact_hit)* user_weight)* 1000 + bm25
もちろん、エミュレーションは組み込みのランカーを使用するよりも遅くなります。 それでも、コンパイルされたコードは式計算機よりも高速です! しかし、私が不思議に思うのを止めることのできないスローダウンは、たいてい重要ではありません。 検索が一致し、数十万、数百万のドキュメントをランク付けする場合でも、「マイクロ」ベンチマークで約30〜50%の差がありました(文字通り、組み込みのランカでは0.4秒、エミュレーションでは約0.5〜0.6秒)。 一致するドキュメントが1〜1万個未満の場合、違いをまったく識別できないと思われます。
次は何だ!?
これらすべてをどうするか? 検索の品質を改善する機会の観点から、非常に多くのことが可能になりました。 実際、今、あなたは好きなようにランキングを完全にひねることができます。 これまで考えられなかった新しい要素がたくさんありますが、今ではその場ですぐにひねることができます。 リクエストに応じて新しいファクターを迅速かつ簡単に追加する技術的な機会がありました-商業顧客のリクエストに応じて、多くのファクターがそのように追加されました。
これは氷山の一角にすぎないことは明らかであり、すぐに多くの質問があります。この「品質」をどのように測定するか、公式をねじる方法などです。 しかし、私はゆっくりと書きますが、すぐに話します。したがって、この投稿をライブで詳細に聞きたい場合は、検索の関連性と品質について2倍に学び、同時に投稿の冒頭で発表された他のすべてについてのいくつかのレポートを聞いてください。 会議 。 (ピーター。12月4日、日曜日。無料ですが、登録が必要です。まだいくつかの空き場所がありますが、今すぐ急ぐ必要があります。)
みなさん、こんにちは、検索品質との戦いで頑張ってください:)