ガウス減衰
ガウス減衰(正規減衰とも呼ばれます)は、検索結果に対して最も自然な調整を行う方法です。距離とともに徐々にぼやけていく人間の視覚のように、ガウス減衰は滑らかなベル型曲線を作り、アイテムが理想的なポイントから離れるにつれて関連性を優しく低下させます。このアプローチは、好ましい範囲の外にあるアイテムに厳しくペナルティを与えない一方で、遠く離れたアイテムの関連性を大幅に低下させるバランスの取れた減衰を望む場合に理想的です。
他の減衰ランカーとは異なり:
-
指数減衰は最初に急激に低下し、より強い初期ペナルティを作ります
-
線形減衰はゼロに達するまで一定の割合で減少し、明確なカットオフを作ります
ガウス減衰は、ユーザーにとって自然に感じるよりバランスの取れた直感的なアプローチを提供します。
ガウス減衰を使用する場合
ガウス減衰は特に以下の場合に効果的です:
使用例 | 例 | ガウスがよく機能する理由 |
|---|---|---|
位置ベースの検索 | レストラン検索、店舗検索 | 距離の関連性に対する自然な人間の知覚を模倣します |
コンテンツのレコメンデーション | 公開日付に基づく記事の提案 | コンテンツが古くなるにつれて関連性が徐々に低下します |
商品リスト | 目標価格に近い商品 | 価格が目標から逸れるにつれて関連性がスムーズに低下します |
専門知識のマッチング | 関連経験を持つ専門家を探す | 経験の関連性のバランスの取れた評価 |
厳しいペナルティや厳格なカットオフなしに、関連性が自然に低下する感覚が必要な場合、ガウス減衰が最適な選択肢になる可能性が高いです。
ベル曲線の原則
ガウス減衰は、理想的なポイントから距離が増加するにつれて関連性を徐々に低下させる滑らかなベル型曲線を作ります。数学者カール・フリードリヒ・ガウスにちなんで名付けられたこの分布は、自然界や統計学で頻繁に現れるため、人間の知覚にとって直感的に感じられます。

上のグラフは、ガウス減衰がモバイル検索アプリでのレストランランキングにどのように影響するかを示しています:
-
origin(0km):関連性が最大(1.0)になる現在地。 -
offset(±300m):あなたの周りの「完全スコアゾーン」—300メートル以内のすべてのレストランは完全な関連性スコア(1.0)を維持し、非常に近いオプションがわずかな距離の違いで不必要にペナルティを受けないようにします。 -
scale(±2km):関連性が減衰値まで低下する距離—正確に2キロメートル離れたレストランの関連性スコアは半分(0.5)になります。 -
decay(0.5):スケール距離でのスコア—このパラメータは基本的に距離とともにスコアがどの程度速く低下するかを制御します。
曲線からわかるように、2kmを超えるレストランは関連性がさらに低下しますが、決してゼロにはなりません。4〜5km離れたレストランでも最小限の関連性を維持し、優れていても遠く離れたレストランが結果に表示される可能性( albeit 低いランクで)を残します。
この動作は、人々が距離の関連性について自然に考える方法を模倣しています—近場の場所が好まれますが、特別なオプションのためにさらに遠くまで行く意欲があります。
式
ガウス減衰スコアを計算するための数学的式は以下の通りです:
S(doc) = \exp\left( -\frac\{\left( \max\left(0, \left|fieldvalue_{doc} - origin\right| - offset \right) \right)^2}\{2\sigma^2} \right)ただし:
\sigma^2 = -\frac{scale^2}\{2 \cdot \ln(decay)}平易な言葉で分解すると:
-
フィールド値が原点からどれだけ離れているかを計算します:
-
オフセット(存在する場合)を引きますが、ゼロを下回ることはありません:
-
この調整された距離を2乗します:
-
(スケールと減衰パラメータから計算されます)で割ります
-
負の指数を取り、0〜1の値を得ます:
の計算は、スケールと減衰パラメータをガウス分布の標準偏差の2乗に変換します。これが関数に特徴的なベル型を与えるものです。
ガウス減衰の使用
ガウス減衰は、Zilliz Cloudの標準ベクトル検索およびハイブリッド検索操作の両方に適用できます。以下は、この機能を実装するための主要なコードスニペットです。
減衰関数を使用する前に、減衰計算に使用される適切な数値フィールド(タイムスタンプ、距離など)を持つコレクションを作成する必要があります。コレクションのセットアップ、スキーマ定義、およびデータ挿入を含む完全な作業例については、チュートリアル:Milvusでの時間ベースのランク付けの実装を参照してください。
減衰ランカーの作成
数値フィールドでコレクションのセットアップが完了した後(この例では、ユーザーからの距離をメートル単位で表すdistance)、ガウス減衰ランカーを作成します:
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import Function, FunctionType
# 位置ベースのレストラン検索のためのガウス減衰ランカーを作成
ranker = Function(
name="restaurant_distance_decay", # 関数識別子
input_field_names=["distance"], # メートル単位の距離用数値フィールド
function_type=FunctionType.RERANK, # 関数タイプ。RERANKでなければなりません
params={
"reranker": "decay", # 減衰再ランカーを指定
"function": "gauss", # ガウス減衰を選択
"origin": 0, # 現在地(0メートル)
"offset": 300, # 300m 減衰なしゾーン
"decay": 0.5, # 一定距離での半分のスコア
"scale": 2000 # 2km スケール(2000メートル)
}
)
import io.milvus.v2.service.vector.request.ranker.DecayRanker;
DecayRanker ranker = DecayRanker.builder()
.name("restaurant_distance_decay")
.inputFieldNames(Collections.singletonList("distance"))
.function("gauss")
.origin(0)
.offset(300)
.decay(0.5)
.scale(2000)
.build();
import { FunctionType } from "@zilliz/milvus2-sdk-node";
const ranker = {
name: "restaurant_distance_decay",
input_field_names: ["distance"],
function_type: FunctionType.RERANK,
params: {
reranker: "decay",
function: "gauss",
origin: 0,
offset: 300,
decay: 0.5,
scale: 2000,
},
};
// go
# restful
標準ベクトル検索への適用
減衰ランカーを定義した後、検索操作中にrankerパラメータに渡すことで適用できます:
- Python
- Java
- NodeJS
- Go
- cURL
# 減衰ランカーをレストランのベクトル検索に適用
result = milvus_client.search(
collection_name,
data=[your_query_vector], # クエリーベクトルに置き換えてください
anns_field="dense", # 検索するベクトルフィールド
limit=10, # 結果の数
output_fields=["name", "cuisine", "distance"], # 戻すフィールド
ranker=ranker, # 減衰ランカーを適用
consistency_level="Strong"
)
import io.milvus.v2.common.ConsistencyLevel;
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
import io.milvus.v2.service.vector.request.data.EmbeddedText;
SearchReq searchReq = SearchReq.builder()
.collectionName(COLLECTION_NAME)
.data(Collections.singletonList(new EmbeddedText("italian restaurants")))
.annsField("vector_field")
.limit(10)
.outputFields(Arrays.asList("name", "cuisine", "distance"))
.functionScore(FunctionScore.builder()
.addFunction(ranker)
.build())
.consistencyLevel(ConsistencyLevel.STRONG)
.build();
SearchResp searchResp = client.search(searchReq);
const result = await milvusClient.search({
collection_name: "collection_name",
data: [your_query_vector], // クエリーベクトルに置き換えてください
anns_field: "dense",
limit: 10,
output_fields: ["name", "cuisine", "distance"],
rerank: ranker,
consistency_level: "Strong",
});
// go
# restful
ハイブリッド検索への適用
減衰ランカーは、複数のベクトルフィールドを組み合わせるハイブリッド検索操作にも適用できます:
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import AnnSearchRequest
# 密ベクトル検索リクエストを定義
dense = AnnSearchRequest(
data=[your_query_vector_1], # クエリーベクトルに置き換えてください
anns_field="dense",
param={},
limit=10
)
# スパースベクトル検索リクエストを定義
sparse = AnnSearchRequest(
data=[your_query_vector_2], # クエリーベクトルに置き換えてください
anns_field="sparse_vector",
param={},
limit=10
)
# 減衰ランカーをレストランハイブリッド検索に適用
hybrid_results = milvus_client.hybrid_search(
collection_name,
[dense, sparse], # 複数の検索リクエスト
ranker=ranker, # 同じ減衰ランカー
limit=10,
output_fields=["name", "cuisine", "distance"]
)
import io.milvus.v2.service.vector.request.AnnSearchReq;
import io.milvus.v2.service.vector.request.HybridSearchReq;
import io.milvus.v2.service.vector.request.data.EmbeddedText;
import io.milvus.v2.service.vector.request.data.FloatVec;
List<AnnSearchReq> searchRequests = new ArrayList<>();
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("dense_vector")
.vectors(Collections.singletonList(new FloatVec(embedding)))
.limit(10)
.build());
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("sparse_vector")
.vectors(Collections.singletonList(new EmbeddedText("italian restaurants")))
.limit(10)
.build());
HybridSearchReq hybridSearchReq = HybridSearchReq.builder()
.collectionName(COLLECTION_NAME)
.searchRequests(searchRequests)
.ranker(ranker)
.limit(10)
.outputFields(Arrays.asList("name", "cuisine", "distance"))
.build();
SearchResp searchResp = client.hybridSearch(hybridSearchReq);
const denseRequest = {
data: [your_query_vector_1], # クエリーベクトルに置き換えてください
anns_field: "dense",
param: {},
limit: 10,
};
const sparseRequest = {
data: [your_query_vector_2], # クエリーベクトルに置き換えてください
anns_field: "sparse_vector",
param: {},
limit: 10,
};
const hybridResults = await milvusClient.search({
collection_name: "collection_name",
data: [denseRequest, sparseRequest],
rerank: ranker,
limit: 10,
output_fields: ["name", "cuisine", "distance"],
});
// go
# restful
ハイブリッド検索操作の詳細については、複数ベクトルハイブリッド検索を参照してください。