メインコンテンツまでスキップ
バージョン: User Guides (BYOC)

Decay Ranker の概要

従来のベクトル検索では、結果は純粋にベクトル類似度(数学的空間におけるベクトルの近さ)に基づいてランキングされます。しかし実際のアプリケーションでは、コンテンツの真の関連性は意味的類似度だけではなく、他の要素にも依存することがよくあります。

以下のような日常的なシナリオを考えてみましょう。

  • 昨日のニュース記事が、3年前の類似記事よりも上位に表示されるニュース検索
  • 30分のドライブが必要な店舗よりも、徒歩5分の飲食店を優先するレストラン検索
  • 検索クエリとの類似度がやや低くても、トレンド中の商品を優先表示するECプラットフォーム

これらのシナリオには共通点があります。それは、ベクトル類似度と時間・距離・人気度などの数値的要素をバランスよく考慮する必要があることです。

Zilliz Cloud の Decay ranker は、このニーズに対応するために、数値フィールドの値に基づいて検索結果のランキングを調整します。「新鮮さ(freshness)」や「近接性(nearness)」など、データに含まれる数値的特性とベクトル類似度をバランスさせることで、より直感的で文脈に即した検索体験を実現します。

使用上の注意

  • Decay ranking はグループ化検索とは併用できません。

  • Decay ranking に使用するフィールドは数値型(INT8INT16INT32INT64FLOAT、または DOUBLE)である必要があります。

  • 各 Decay ranker は1つの数値フィールドのみを使用できます。

  • 時間単位の一貫性:時間ベースの decay ranking を使用する場合、originscale、および offset パラメータの単位は、コレクション内のデータで使用されている単位と一致させる必要があります。

    • コレクションがタイムスタンプを単位で保存している場合、すべてのパラメータも秒単位で指定します

    • コレクションがタイムスタンプをミリ秒単位で保存している場合、すべてのパラメータもミリ秒単位で指定します

    • コレクションがタイムスタンプをマイクロ秒単位で保存している場合、すべてのパラメータもマイクロ秒単位で指定します

動作の仕組み

Decay ranking は、時間や地理的距離といった数値的要素をランキング処理に組み込むことで、従来のベクトル検索を強化します。このプロセスは以下のステージで構成されています。

ステージ 1: 正規化された類似度スコアの計算

まず、Zilliz Cloud はベクトル類似度スコアを計算し、一貫した比較が行えるように正規化します。

  • L2 および JACCARD 距離メトリクスの場合(値が小さいほど類似度が高い):

    normalized_score = 1.0 - (2 × arctan(score))/π

    これは、距離を0〜1の類似度スコアに変換し、数値が大きいほど良い結果を示します。

  • IPCOSINE、およびBM25メトリクスの場合(これらのメトリクスでは、すでに高いスコアがより良いマッチを示します):スコアは正規化せずにそのまま使用されます。

ステージ 2: 減衰スコアの計算

次に、Zilliz Cloud は選択した減衰ランカーを使用して、数値フィールドの値(タイムスタンプや距離など)に基づく減衰スコアを計算します。

  • 各減衰ランカーは、生の数値を0〜1の正規化された関連性スコアに変換します

  • 減衰スコアは、「理想的なポイント」からの「距離」に基づいてアイテムの関連性を表します

具体的な計算式は、減衰ランカーのタイプによって異なります。減衰スコアの計算方法の詳細については、それぞれの専用ページをご参照ください:ガウス減衰指数減衰線形減衰

ステージ 3: 最終スコアの算出

最後に、Zilliz Cloud は正規化された類似度スコアと減衰スコアを組み合わせて、最終的なランキングスコアを生成します。

final_score = normalized_similarity_score × decay_score

ハイブリッド検索(複数のベクトルフィールドを組み合わせる)の場合、Zilliz Cloud は検索リクエストの中で最大の正規化済み類似度スコアを採用します。

final_score = max([normalized_score₁, normalized_score₂, ..., normalized_scoreₙ]) × decay_score

たとえば、ハイブリッド検索において、ある研究論文がベクトル類似度で0.82、BM25ベースのテキスト検索で0.91をスコアした場合、Zilliz Cloudは減衰係数を適用する前に0.91を基本類似度スコアとして使用します。

実際の減衰ランキング

実用的なシナリオで減衰ランキングを見てみましょう。ここでは「AI研究論文」を時間に基づく減衰付きで検索します:

📘Notes

この例では、減衰スコアは時間の経過とともに関連性が低下することを反映しています。新しい論文ほど1.0に近いスコアを受け取り、古い論文ほど低いスコアになります。これらの値は特定の減衰ランカーを使用して計算されています。詳細については、適切な減衰ランカーの選択をご参照ください。

論文

ベクトル類似度

正規化済み類似度スコア

公開日

減衰スコア

最終スコア

最終順位

論文 A

0.85 (COSINE)

2週間前

0.80

0.68

2

論文 B

非常に高

0.92 (COSINE)

6か月前

0.45

0.41

3

論文 C

0.75 (COSINE)

1日前

0.98

0.74

1

論文 D

中〜高

0.76 (COSINE)

3週間前

0.70

0.53

4

減衰による再ランキングを行わなければ、論文Bは純粋なベクトル類似度(0.92)により最上位になります。しかし、減衰再ランキングを適用すると:

  • 論文Cは類似度が「中」であるにもかかわらず、非常に新しい(昨日公開)ため1位にジャンプアップします

  • 論文Bは優れた類似度を持つものの比較的古いため、3位にまで下がります

  • 論文DはL2距離(小さいほど良い)を使用しているため、1.2から0.76に正規化された後に減衰が適用されています

適切な減衰ランカーの選択

Zilliz Cloudは、それぞれ異なるユースケース向けに設計されたgaussexplinearの3種類の減衰ランカーを提供しています:

減衰ランカー

特徴

理想的なユースケース

例となるシナリオ

ガウス (gauss)

自然で緩やかな減少傾向を持ち、中程度まで影響が及ぶ

  • バランスの取れた結果が求められる一般検索

  • ユーザーが直感的に距離感を把握できるアプリケーション

  • 中程度の距離であっても結果を厳しくペナルティすべきでない場合

レストラン検索では、3 km離れた高品質な店舗も表示されますが、近くの選択肢よりは順位が下がります

指数 (exp)

最初に急激に減少し、その後も長い尾を引く

  • 新鮮さが極めて重要なニュースフィード

  • 最新コンテンツが支配すべきソーシャルメディア

  • 近接性が強く好まれるが、例外的に遠くても優れたアイテムは表示したい場合

ニュースアプリでは、昨日の記事が1週間前のコンテンツよりもはるかに高い順位となりますが、関連性が非常に高い古い記事も表示されます

線形 (linear)

一貫性があり予測可能な減少傾向を持ち、明確なカットオフがある

  • 自然な境界を持つアプリケーション

  • 距離制限のあるサービス

  • 有効期限や明確な閾値を持つコンテンツ

イベント検索では、2週間以上先のイベントはまったく表示されません

各減衰ランカーがスコアをどのように計算し、どのような減少パターンを持つのかについての詳細は、以下の専用ドキュメントをご参照ください:

実装例

減衰ランカーは、Zilliz Cloudにおける標準的なベクトル検索およびハイブリッド検索の両方に適用できます。以下にこの機能を実装するための主要なコードスニペットを示します。

📘Notes

減衰関数を使用する前に、まず減衰計算に使用するタイムスタンプや距離などの数値フィールドを含むコレクションを作成しておく必要があります。コレクションのセットアップ、スキーマ定義、データ挿入を含む完全な動作例については、チュートリアル: Milvusで時間ベースのランキングを実装するをご参照ください。

減衰ランカーの作成

減衰ランキングを実装するには、まず適切な設定でFunctionオブジェクトを定義します:

from pymilvus import Function, FunctionType

# Create a decay function for timestamp-based decay
# Note: All time parameters must use the same unit as your collection data
rerank = Function(
name="time_decay", # Function identifier
input_field_names=["timestamp"], # Numeric field to use for decay
function_type=FunctionType.RERANK, # Must be set to RERANK for decay rankers
params={
"reranker": "decay", # Specify decay reranker. Must be "decay"
"function": "gauss", # Choose decay function type: "gauss", "exp", or "linear"
"origin": int(datetime.datetime(2025, 1, 15).timestamp()), # Reference point (seconds)
"scale": 7 * 24 * 60 * 60, # 7 days in seconds (must match collection data unit)
"offset": 24 * 60 * 60, # 1 day no-decay zone (must match collection data unit)
"decay": 0.5 # Half score at scale distance
}
)

パラメータ

必須?

説明

値/例

name

はい

検索実行時に使用される関数の識別子です。ユースケースに関連したわかりやすい名前を指定してください。

"time_decay"

input_field_names

はい

減衰スコア計算に使用する数値フィールドです。減衰計算に使用するデータ属性(例:時間ベースの減衰にはタイムスタンプ、位置ベースの減衰には座標)を決定します。

コレクション内に存在し、関連する数値を含むフィールドである必要があります。INT8/16/32/64、FLOAT、DOUBLE をサポートしています。

["timestamp"]

function_type

はい

作成する関数のタイプを指定します。

すべての減衰ランカーに対して RERANK に設定する必要があります。

FunctionType.RERANK

params.reranker

はい

使用するリランキング手法を指定します。

減衰ランキング機能を有効にするには、"decay" に設定する必要があります。

"decay"

params.function

はい

適用する数学的減衰ランカーを指定します。関連性の低下カーブの形状を決定します。

適切な関数の選択については、適切な減衰ランカーの選択セクションをご参照ください。

"gauss""exp"、または "linear"

params.origin

はい

減衰スコアの計算基準となる参照点です。この値を持つアイテムは最大の関連性スコアを受け取ります。

時間ベースの減衰の場合、時間単位はコレクションのデータと一致している必要があります。

  • タイムスタンプの場合:現在時刻(例:int(time.time())

  • ジオロケーションの場合:ユーザーの現在地座標

params.scale

はい

decay 値となる距離または時間です。関連性がどの程度速く低下するかを制御します。

時間ベースの減衰の場合、時間単位はコレクションのデータと一致している必要があります。

大きな値は関連性の緩やかな低下を、小さな値は急激な低下をもたらします。

  • 時間の場合:秒単位の期間(例:7 * 24 * 60 * 60 で7日間)

  • 距離の場合:メートル(例:5000 で5km)

params.offset

いいえ

origin の周囲に「減衰なしゾーン」を作成し、その範囲内のアイテムは完全なスコア(減衰スコア = 1.0)を維持します。

時間ベースの減衰の場合、時間単位はコレクションのデータと一致している必要があります。

origin からこの範囲内にあるアイテムは最大の関連性を維持します。

  • 時間の場合:秒単位の期間(例:24 * 60 * 60 で1日)

  • 距離の場合:メートル(例:500 で500m)

params.decay

いいえ

scale 距離におけるスコア値で、カーブの急峻さを制御します。低い値は急激な低下カーブを、高い値は緩やかな低下カーブを生成します。

0 から 1 の間である必要があります。

0.5(デフォルト)

減衰ランカーを定義した後、検索操作時に ranker パラメータに渡すことで適用できます:

# Use the decay function in standard vector search
results = milvus_client.search(
collection_name,
data=[your_query_vector], # Replace with your query vector
anns_field="vector_field",
limit=10,
output_fields=["document", "timestamp"], # Include the decay field in outputs to see values
ranker=rerank, # Apply the decay ranker here
consistency_level="Strong"
)