範囲検索
範囲検索は、返されるエンティティの距離またはスコアを特定の範囲内に制限することで、検索結果の関連性を向上させます。このページでは、範囲検索とは何か、範囲検索を行う手順について説明します。
概要
Milvusは範囲検索のリクエストを実行する際、ANN検索の結果からクエリベクトルに最も類似したベクトルを中心として、検索リクエストで指定された半径を外側の円の半径、range_filterを内側の円の半径として、2つの同心円を描きます。この2つの同心円で形成される環状領域内に入る類似度スコアを持つすべてのベクトルが返されます。ここでrange_filterを0 に設定すると、指定した類似度スコア(半径)内のすべてのエンティティが返される。
範囲検索
上の図は、範囲検索要求が radius とrange_filter という2つのパラメータを持つことを示している。範囲検索リクエストを受け取ると、Milvusは以下の処理を行います。
指定されたメトリックタイプ(COSINE)を使用して、クエリベクトルに最も類似したすべてのベクトル埋め込みを検索する。
クエリベクトルとの距離またはスコアが radiusおよびrange_filterパラメータで指定された範囲内にある埋め込みベクトルをフィルタリングする。
フィルタリングされたエンティティから上位K個のエンティティを返す。
radiusとrange_filterの設定方法は、検索のメトリックタイプによって異なる。次の表に、メトリックの種類別にこれら2つのパラメータの設定条件を示す。
メトリックタイプ | 表記 | radiusとrange_filterの設定条件 |
---|---|---|
| L2距離が小さいほど類似度が高いことを示す。 | 最も類似したベクトル埋め込みを無視するには
|
| IP距離が大きいほど,類似度が高いことを示す. | 最も類似したベクトル埋め込みを無視するには
|
| COSINE 距離が大きいほど,類似度が高いことを示す. | 最も類似したベクトル埋め込みを無視するには
|
| Jaccard 距離が小さいほど,類似度が高いことを示します. | 最も類似したベクトル埋め込みを無視するには
|
| ハミング距離が小さいほど、類似度が高いことを示します。 | 最も類似したベクトル埋め込みを無視するには
|
例
このセクションでは、範囲検索の方法を示します。以下のコードスニペットの検索リクエストはメトリックタイプを持たないので、デフォルトのメトリックタイプCOSINEが適用されます。この場合、radius値がrange_filter値よりも小さいことを確認してください。
以下のコードスニペットでは、milvusがクエリベクトルとの距離またはスコアが0.4から 0.6の範囲内にあるすべてのエンティティを返すように、radius
を0.4
に、range_filter
を0.6
に設定します。
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="my_collection",
data=[query_vector],
limit=3,
search_params={
# highlight-start
"params": {
"radius": 0.4,
"range_filter": 0.6
}
# highlight-end
}
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
io.milvus.v2.service.vector.request.SearchReq
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
Map<String,Object> extraParams = new HashMap<>();
extraParams.put("radius", 0.4);
extraParams.put("range_filter", 0.6);
SearchReq searchReq = SearchReq.builder()
.collectionName("range_search_collection")
.data(Collections.singletonList(queryVector))
.topK(5)
.searchParams(extraParams)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.5975797, id=4)
// SearchResp.SearchResult(entity={}, score=0.46704385, id=5)
// TODO
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = await client.search({
collection_name: "range_search_collection",
data: [query_vector],
limit: 5,
// highlight-start
params: {
"radius": 0.4,
"range_filter": 0.6
}
// highlight-end
})
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"filter": "color like \"red%\" and likes > 50",
"limit": 3,
"searchParams": {
"params": {
"radius": 0.4,
"range_filter": 0.6
}
}
}'
# {"code":0,"cost":0,"data":[]}