重み付けランカー
Weighted Rankerは、複数の検索パスから得られた結果をインテリジェントに組み合わせ、それぞれに異なる重要度のウェイトを割り当てることで優先順位を付けます。熟練したシェフが完璧な料理を作るために複数の食材のバランスを取るのと同様に、Weighted Rankerは最も関連性の高い組み合わせの結果を提供するために、異なる検索結果のバランスを取ります。このアプローチは、複数のベクトル分野やモダリティにまたがる検索で、特定の分野が他の分野よりも最終的なランキングに大きく貢献する場合に理想的です。
Weighted Rankerを使用する場合
Weighted Rankerは、複数のベクトル検索パスからの結果を組み合わせる必要があるハイブリッド検索シナリオのために特別に設計されています。特に以下のような場合に有効です:
使用例 |
使用例 |
Weighted Rankerが有効な理由 |
|---|---|---|
Eコマース検索 |
画像の類似性とテキストの説明を組み合わせた商品検索 |
ファッション商品では視覚的な類似性を優先し、技術的な商品ではテキストの説明を重視することができます。 |
メディアコンテンツ検索 |
視覚的特徴と音声トランスクリプトの両方を使用したビデオ検索 |
クエリの意図に基づき、ビジュアルコンテンツと音声対話の重要性のバランスをとる。 |
文書検索 |
異なるセクションに対して複数のエンベッディングを使用したエンタープライズ文書検索 |
全文エンベッディングを考慮しつつ、タイトルと抄録エンベッディングに高いウェイトを与える。 |
ハイブリッド検索アプリケーションで、複数の検索パスを組み合わせ、それらの相対的な重要度をコントロールする必要がある場合、Weighted Rankerは理想的な選択です。
Weighted Rankerのメカニズム
WeightedRanker戦略の主なワークフローは以下の通りです:
検索スコアを集める:ベクトル検索の各パスの結果とスコアを集める(score_1, score_2)。
スコアの正規化:各検索は異なる類似度メトリックを使用する可能性があり、その結果スコア分布は異なる。例えば、類似性のタイプとして内積(IP)を使用すると、スコアは[-∞,+∞]の範囲になり、ユークリッド距離(L2)を使用すると、スコアは[0,+∞]の範囲になる。異なる検索からのスコア範囲は様々であり、直接比較することができないため、各検索パスからのスコアを正規化する必要がある。通常、
arctan関数を適用して、スコアを [0, 1] の間の範囲に変換する(score_1_normalized, score_2_normalized)。スコアが1に近いほど類似性が高いことを示す。重みを割り当てる:異なるベクトル場に割り当てられた重要度に基づいて、重み(wi)が正規化スコア(score_1_normalized, score_2_normalized)に割り当てられる。各パスの重みは[0,1]の範囲とする。得られた重み付きスコアは score_1_weighted と score_2_weighted となる。
スコアのマージ:重み付きスコア(score_1_weighted, score_2_weighted)を高いものから低いものへとランク付けし、最終的なスコア(score_final)を生成する。
加重ランカー
重み付けランカーの例
この例では画像とテキストを含むマルチモーダルハイブリッド検索(topK=5)を示し、WeightedRanker戦略が2つのANN検索の結果をどのようにランク付けし直すかを説明する。
画像に対するANN検索結果(topK=5)::画像
ID
スコア(画像)
101
0.92
203
0.88
150
0.85
198
0.83
175
0.8
テキスト(topK=5)に対するANN検索結果
ID
スコア(テキスト)
198
0.91
101
0.87
110
0.85
175
0.82
250
0.78
WeightedRankerを使用して、画像とテキストの検索結果に重みを割り当てる。画像ANN検索の重みを0.6、テキスト検索の重みを0.4とする。
ID
スコア(画像)
スコア(テキスト)
重み付けスコア
101
0.92
0.87
0.6×0.92+0.4×0.87=0.90
203
0.88
該当なし
0.6×0.88+0.4×0=0.528
150
0.85
該当なし
0.6×0.85+0.4×0=0.51
198
0.83
0.91
0.6×0.83+0.4×0.91=0.86
175
0.80
0.82
0.6×0.80+0.4×0.82=0.81
110
画像にない
0.85
0.6×0+0.4×0.85=0.34
250
画像にない
0.78
0.6×0+0.4×0.78=0.312
再ランク付け後の最終結果(topK=5):以下の通り。
順位
ID
最終スコア
1
101
0.90
2
198
0.86
3
175
0.81
4
203
0.528
5
150
0.51
重み付きランカーの使用法
WeightedRankerストラテジーを使用する場合、重み値を入力する必要がある。入力する重み値の数は、ハイブリッド検索における基本ANN検索要求の数に対応させる必要がある。入力する重み値は[0,1]の範囲にあるべきで、1に近いほど重要度が高いことを示す。
重み付きランカーの作成
例えば、ハイブリッド検索にテキスト検索と画像検索の2つの基本ANN検索リクエストがあるとする。テキスト検索がより重要であると考えられる場合、より大きなウェイトが割り当てられるはずです。
Milvus 2.6.x以降では、Function APIを介して直接リランキング戦略を設定することができます。それ以前のリリース(v2.6.0以前)を使用している場合は、Rerankingのドキュメントを参照して設定を行ってください。
from pymilvus import Function, FunctionType
rerank = Function(
name="weight",
input_field_names=[], # Must be an empty list
function_type=FunctionType.RERANK,
params={
"reranker": "weighted",
"weights": [0.1, 0.9],
"norm_score": True # Optional
}
)
import io.milvus.common.clientenum.FunctionType;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
CreateCollectionReq.Function rerank = CreateCollectionReq.Function.builder()
.name("weight")
.functionType(FunctionType.RERANK)
.param("reranker", "weighted")
.param("weights", "[0.1, 0.9]")
.param("norm_score", "true")
.build();
import { FunctionType } from '@zilliz/milvus2-sdk-node';
const rerank = {
name: "weight",
input_field_names: [],
function_type: FunctionType.RERANK,
params: {
reranker: "weighted",
weights: [0.1, 0.9],
norm_score: true
}
};
// Go
# Restful
パラメータ |
必須か? |
説明 |
値/例 |
|---|---|---|---|
|
はい |
このファンクションの一意な識別子 |
|
|
はい |
関数を適用するベクトルフィールドのリスト(Weighted Rankerの場合は空でなければならない) |
[] |
|
はい |
呼び出すFunctionのタイプ。リランキング戦略を指定するには |
|
|
はい |
使用するリランキング法を指定する。 Weighted Rankerを使用するには |
|
|
Yes |
各探索経路に対応する重みの配列。 詳細はWeighted Ranker の仕組みを参照。 |
|
|
いいえ |
重み付けの前に生のスコアを正規化するかどうか(arctanを使用)。 詳細はWeighted Ranker の仕組みを参照。 |
|
ハイブリッド検索への適用
Weighted Rankerは、複数のベクトル場を組み合わせたハイブリッド検索操作に特化して設計されている。ハイブリッド検索を行う際には、各検索パスの重みを指定する必要がある:
from pymilvus import MilvusClient, AnnSearchRequest
# Connect to Milvus server
milvus_client = MilvusClient(uri="http://localhost:19530")
# Assume you have a collection setup
# Define text vector search request
text_search = AnnSearchRequest(
data=["modern dining table"],
anns_field="text_vector",
param={},
limit=10
)
# Define image vector search request
image_search = AnnSearchRequest(
data=[image_embedding], # Image embedding vector
anns_field="image_vector",
param={},
limit=10
)
# Apply Weighted Ranker to product hybrid search
# Text search has 0.8 weight, image search has 0.3 weight
hybrid_results = milvus_client.hybrid_search(
collection_name,
[text_search, image_search], # Multiple search requests
ranker=rerank, # Apply the weighted ranker
limit=10,
output_fields=["product_name", "price", "category"]
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.AnnSearchReq;
import io.milvus.v2.service.vector.request.HybridSearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
import io.milvus.v2.service.vector.request.data.EmbeddedText;
import io.milvus.v2.service.vector.request.data.FloatVec;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
List<AnnSearchReq> searchRequests = new ArrayList<>();
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("text_vector")
.vectors(Collections.singletonList(new EmbeddedText("\"modern dining table\"")))
.limit(10)
.build());
searchRequests.add(AnnSearchReq.builder()
.vectorFieldName("image_vector")
.vectors(Collections.singletonList(new FloatVec(imageEmbedding)))
.limit(10)
.build());
HybridSearchReq hybridSearchReq = HybridSearchReq.builder()
.collectionName(COLLECTION_NAME)
.searchRequests(searchRequests)
.ranker(ranker)
.limit(10)
.outputFields(Arrays.asList("product_name", "price", "category"))
.build();
SearchResp searchResp = client.hybridSearch(hybridSearchReq);
import { MilvusClient, FunctionType } from "@zilliz/milvus2-sdk-node";
const milvusClient = new MilvusClient({ address: "http://localhost:19530" });
const text_search = {
data: ["modern dining table"],
anns_field: "text_vector",
param: {},
limit: 10,
};
const image_search = {
data: [image_embedding],
anns_field: "image_vector",
param: {},
limit: 10,
};
const rerank = {
name: "weight",
input_field_names: [],
function_type: FunctionType.RERANK,
params: {
reranker: "weighted",
weights: [0.1, 0.9],
norm_score: true,
},
};
const search = await milvusClient.search({
collection_name: collection_name,
limit: 10,
data: [text_search, image_search],
rerank: rerank,
output_fields = ["product_name", "price", "category"],
});
// go
# restful
ハイブリッド検索の詳細については、マルチベクター・ハイブリッド検索を参照。