範囲検索

範囲検索は、返されるエンティティの距離またはスコアを特定の範囲内に制限することで、検索結果の関連性を向上させます。このページでは、範囲検索とは何か、範囲検索を行う手順について説明します。

概要

Milvusは範囲検索のリクエストを実行する際、ANN検索の結果からクエリベクトルに最も類似したベクトルを中心として、検索リクエストで指定された半径を外側の円の半径、range_filterを内側の円の半径として、2つの同心円を描きます。この2つの同心円で形成される環状領域内に入る類似度スコアを持つすべてのベクトルが返されます。ここでrange_filter0 に設定すると、指定した類似度スコア(半径)内のすべてのエンティティが返される。

Range Search 範囲検索

上の図は、範囲検索要求がradiusrange_filter という2つのパラメータを持つことを示している。範囲検索リクエストを受け取ると、Milvusは以下の処理を行います:

  • 指定されたメトリックタイプ(COSINE)を使用して、クエリベクトルに最も近いすべてのベクトル埋め込みを検索する。

  • クエリベクトルとの距離またはスコアが radiusおよびrange_filterパラメータで指定された範囲内にある埋め込みベクトルをフィルタリングする。

  • フィルタリングされたエンティティから上位K個のエンティティを返す。

radiusと range_filterの設定方法は、検索のメトリックタイプによって異なる。次の表は、メトリック・タイプの違いによるこれら2つのパラメータの設定条件を示している。

メトリックタイプ

表記

radiusとrange_filterの設定条件

L2

L2距離が小さいほど類似度が高いことを示す。

最も類似したベクトル埋め込みを無視するには

range_filter <= 距離 <radius

IP

IP距離が大きいほど類似度が高い。

最も類似したベクトル埋め込みを無視するには

radius < 距離 <=range_filter

COSINE

COSINE距離が大きいほど,類似度が高いことを示す.

最も類似したベクトル埋め込みを無視するには

radius < 距離 <=range_filter

JACCARD

Jaccard距離が小さいほど類似度が高いことを示す。

最も類似したベクトル埋め込みを無視するには

range_filter <= 距離 <radius

HAMMING

ハミング距離が小さいほど類似度が高いことを示します。

最も類似したベクトル埋め込みを無視するには

range_filter <= 距離 <radius

例題

このセクションでは、範囲検索の方法を示します。以下のコードスニペットの検索リクエストはメトリックタイプを持たず、デフォルトのメトリックタイプCOSINEが適用されることを示しています。この場合、radius値がrange_filter値より小さいことを確認してください。

以下のコードスニペットでは、milvusがクエリベクトルとの距離またはスコアが0.40.6に収まるすべてのエンティティを返すように、radius0.4 に、range_filter0.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={
        "params": {
            "radius": 0.4,
            "range_filter": 0.6
        }
    }
)

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("my_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)
import (
    "context"
    "fmt"
    
    "github.com/milvus-io/milvus/client/v2/index"
    "github.com/milvus-io/milvus/client/v2/entity"
    "github.com/milvus-io/milvus/client/v2/milvusclient"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address: milvusAddr,
})
if err != nil {
    fmt.Println(err.Error())
    // handle error
}
defer client.Close(ctx)

queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}

annParam := index.NewCustomAnnParam()
annParam.WithRadius(0.4)
annParam.WithRangeFilter(0.6)
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
    "my_collection", // collectionName
    5,               // limit
    []entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
    WithANNSField("vector").
    WithAnnParam(annParam))
if err != nil {
    fmt.Println(err.Error())
    // handle error
}

for _, resultSet := range resultSets {
    fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
    fmt.Println("Scores: ", resultSet.Scores)
}
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: "my_collection",
    data: [query_vector],
    limit: 5,
    params: {
        "radius": 0.4,
        "range_filter": 0.6
    }
})
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" \
--header "Request-Timeout: 10" \
-d '{
    "collectionName": "my_collection",
    "data": [
        [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
    ],
    "annsField": "vector",
    "limit": 5,
    "searchParams": {
        "params": {
            "radius": 0.4,
            "range_filter": 0.6
        }
    }
}'
# {"code":0,"cost":0,"data":[]}

クエリベクターがすでにターゲットコレクションに存在する場合は、検索前にそれらを取得する代わりにids 。詳細はプライマリ・キー検索を参照。

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
フィードバック

このページは役に立ちましたか ?