• Milvusについて
  • はじめに
  • 概念
  • ユーザーガイド
    • コレクション
    • スキーマとデータフィールド
    • 挿入と削除
    • 索引
    • 検索
    • 関数およびモデルの推論
    • ストレージの最適化
    • スナップショット
  • データのインポート
  • AIツール
  • 管理ガイド
  • ツール
  • 連携機能
  • チュートリアル
  • よくある質問
  • API Reference

MinHash関数Compatible with Milvus 3.0.x

MinHash関数は、生テキストを、文書間のジャッカード類似度を 近似するバイナリベクトルに変換します。テキストのシンギングと複数のハッシュ関数を適用して固定長のシグネチャベクトルを生成することで、大規模な環境においても、近似重複文書の高速検出と文書重複排除を可能にします。

MinHashは組み込み関数であるため、Milvus内で実行され、外部モデルによる推論や前処理を必要としません。生のテキストを入力するだけで、Milvusが自動的にMinHashシグネチャベクトルを生成します。

制限事項

  • 各MinHashシグネチャは32ビットのハッシュ値であるため、出力フィールドは次元がdim % 32 == 0 を満たすBINARY_VECTOR でなければなりません。

  • バイナリベクトルフィールドのdim は、32 * num_hashes と一致している必要があります。一致しない場合はエラーが発生します。

  • MINHASH_LSH のインデックスをMinHash関数の出力に使用する場合は、mh_element_bit_width を32 に設定する必要があります。

MinHashの仕組み

展開して仕組みを確認

MinHashは、集合間のジャカード類似度を推定する、局所性に敏感なハッシュ手法です。Milvusにおいて、MinHash関数は以下のパイプラインに従います。ユーザーは生のテキストを入力として提供し、Milvusはバイナリベクトルを出力します。中間ステップはすべて内部で処理されます。

全体的なワークフローは、ドキュメントの取り込みとクエリ処理の両方で使用される共通のテキスト処理パイプラインと、それに続く保存および検索のためのフェーズ固有の操作で構成されています。

Iaqkbfeh8oqggsx6nsocfosondo Iaqkbfeh8oqggsx6nsocfosondo

共通のテキスト処理パイプライン

ドキュメントの取り込みとクエリ処理の両方において、生のテキストは同じ4段階の変換処理を経ます:

  1. テキスト分析:テキストはアナライザーによって処理される(token_level が"word" の場合)か、直接使用される(token_level が"char" の場合)。単語レベルのトークン化では、入力フィールドに設定されたアナライザーを適用してテキストを用語に分割します。例えば、"milvus is vector db" は["milvus", "is", "vector", "db"] となります。

  2. シンギング:トークンは、サイズがshingle_size の重なり合うn-グラム(シングル)に分割されます。たとえば、単語レベルで3-グラムを使用する場合、トークン「["information", "retrieval", "is", "a", "field"] 」は「["information retrieval is", "retrieval is a", "is a field"] 」のようなシングルになります。

  3. MinHashシグネチャの生成:複数のハッシュ関数(H1, H2, …, Hn、ここで n =num_hashes )がシングル集合に適用される。 各ハッシュ関数について、すべてのシンブルにわたる最小のハッシュ値が選択されます。これらの最小値の集合が MinHash 署名を形成します。これは、元の文書のジャッカード類似度を近似する固定長の表現です。

  4. バイナリベクトルエンコーディング:各署名値は 32 ビットのハッシュであり、完全な署名は次元32 * num_hashes のBINARY_VECTOR にパックされます。

文書の取り込み

挿入時、共有パイプラインによって生成されたバイナリベクトルは、MINHASH_LSH インデックスに格納されます。このインデックスは、類似したシグネチャを同じバケットにグループ化するLSH(局所性感受性ハッシュ)テーブルを維持しており、クエリ実行時に候補を高速に検索できるようにしています。

クエリ処理

検索時には、クエリテキストが同じ共有パイプラインを通過してバイナリベクトルが生成されます。このベクトルを使用してMINHASH_LSH インデックス内でLSH検索が行われ、類似している可能性が高い候補ペアが迅速に特定されます。ジャカード精緻化が有効になっていない場合、Milvusは推定ジャカード類似度によるランク付けが行われていないLSH候補を返します。 ジャカード精緻化が有効になっている場合、Milvusは保存された生のMinHashシグネチャを使用して、推定ジャカード類似度に基づいて候補をランク付けし、上位K件の結果を返します。

どちらの処理経路も同一の変換ロジックを共有しているため、内容が高度に重複している2つのドキュメントは、類似したMinHashシグネチャを生成します。これにより、ドキュメント間の語順、書式、あるいは些細な表現の違いがあっても、ニアダブレートを効果的に検出することが可能になります。

開始する前に

MinHash 関数を使用する前に、コレクションスキーマに以下の項目を含めるよう計画してください:

  • 生コンテンツ用のテキストフィールド

    コレクションには、生のテキストを格納するためのVARCHAR フィールドが含まれている必要があります。このフィールドは、MinHash関数の入力として機能します。

  • テキストフィールド用のアナライザー(単語レベルのトークン化を使用する場合)

    token_level が"word" (デフォルト)に設定されている場合、テキストフィールドにはアナライザーが有効になっている必要があります。アナライザーは、シンギングの前にテキストがどのようにトークン化されるかを定義します。デフォルトでは、Milvusはstandard アナライザーを使用します。別のアナライザーを設定するには、「ユースケースに適したアナライザーの選択」を参照してください。

  • MinHash出力用のバイナリベクトルフィールド

    コレクションには、MinHash関数によって生成されたバイナリベクトルを格納するためのBINARY_VECTOR フィールドが含まれている必要があります。そのディメンションは32 * num_hashes と一致している必要があります。

ステップ 1: MinHash 関数を含むコレクションを作成する

MinHash関数を使用するには、コレクションの作成時にその関数を定義します。この関数はコレクションスキーマの一部となり、データの挿入や検索の際に自動的に適用されます。

スキーマフィールドの定義

コレクションスキーマには、少なくとも以下の3つのフィールドを含める必要があります。

  • プライマリフィールド:コレクション内の各エンティティを一意に識別します。

  • テキストフィールド(VARCHAR): 生のテキストドキュメントを格納します。MilvusがMinHashシグネチャ生成のためにテキストを処理できるよう、enable_analyzer=True を設定してください。デフォルトでは、Milvusはテキスト分析にstandard アナライザを使用します。別のアナライザを設定するには、「ユースケースに適したアナライザの選択」を参照してください。

  • バイナリベクトルフィールド(BINARY_VECTOR): MinHash関数によって自動的に生成されたバイナリベクトルを格納します。次元は32 * num_hashes と一致している必要があります。

from pymilvus import MilvusClient, DataType, Function, FunctionType

client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")

schema = client.create_schema()

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(field_name="document_content", datatype=DataType.VARCHAR, max_length=9000, enable_analyzer=True)
schema.add_field(field_name="binary_vector", datatype=DataType.BINARY_VECTOR, dim=8192)
// java
// nodejs
// go
# restful

MinHash関数の定義

MinHash関数は、分析されたテキストを、ドキュメント間のジャカード類似度を近似するバイナリベクトルに変換します。

関数を定義し、スキーマに追加します:

minhash_function = Function(
    name="minhash_function",
    input_field_names=["document_content"], # Name of the VARCHAR field containing raw text
    output_field_names=["binary_vector"], # Name of the BINARY_VECTOR field for generated signatures
    function_type=FunctionType.MINHASH,
    params={
        "num_hashes": 256, # Number of hash functions; produces dim = 32 * 256 = 8192
        "shingle_size": 3, # N-gram size for shingling
    }
)

schema.add_function(minhash_function)
// java
// nodejs
// go
# restful

設定オプション

MinHash関数のparams 辞書は、以下のパラメータを受け付けます。すべてのパラメータ名は大文字小文字を区別しません。

パラメータ

型

デフォルト

説明

num_hashes

int

由来dim / 32

署名生成に使用するハッシュ関数の数。出力バイナリベクトルの次元は、32 * num_hashes となります。値を大きくすると、類似度推定における分散は減少しますが、計算量は増加します。推奨値:256 (dim = 8192)。

shingle_size

int

3

シンギング用のN-gramサイズ。単語レベル:通常は1~3。文字レベル:通常は2~6。

hash_function

str

"xxhash"

使用するハッシュ関数。オプション:

  • "xxhash" (高速)

  • "sha1" (処理速度は遅くなるが、衝突耐性が高い)。

token_level

str

"word"

トークン化レベル。オプション:

  • "word": トークン化にフィールドのアナライザを使用し、その後 n-gram シンギリングを適用します。

  • "char" /"character": 生の文字に対して直接 n-gram シンギングを適用します(アナライザは使用しません)。

    単語レベルはより強力な意味論と高い効率を提供しますが、言語固有のトークン化に依存します。文字レベルは言語に依存しませんが、より高次元のシンギングを生成し、意味論は弱くなります。

seed

int

1234

MinHash関数の初期化に使用するランダムシード。

インデックスの設定

MinHash バイナリベクトルに推奨されるインデックス型は `MINHASH_LSH` で、メトリック型は `MHJACCARD` です。

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="binary_vector",
    index_type="MINHASH_LSH",
    metric_type="MHJACCARD",
    params={
        "mh_lsh_band": 128,
        "mh_element_bit_width": 32,
        "with_raw_data": True,
    },
)
// java
// nodejs
// go
# restful

検索でジャッカード精緻化を使用する場合は、with_raw_data をTrue に設定してください。LSH検索によって返された候補に対する推定ジャッカード類似度を計算するには、生のMinHashシグネチャが必要です。

コレクションの作成

上記で定義したスキーマおよびインデックスパラメータを使用してコレクションを作成します:

client.create_collection(
    collection_name="dedup_collection",
    schema=schema,
    index_params=index_params,
)
// java
// nodejs
// go
# restful

ステップ 2: ドキュメントの挿入

コレクションの設定が完了したら、テキストデータを挿入します。必要なのは生のテキストのみです。MinHash関数が各ドキュメントのバイナリベクトルを自動的に生成します。

client.insert(
    "dedup_collection",
    [
        {"document_content": "information retrieval is a field of study that helps users find relevant information in large datasets"},
        {"document_content": "information retrieval is a research field focused on helping users find relevant data in large collections"},
        {"document_content": "information retrieval is a field of research helping users search for relevant information in large datasets"},
    ],
)
// java
// nodejs
// go
# restful

ステップ 3: MinHash を使用した検索

データの挿入が完了したら、生のテキストクエリを指定して、近似重複ドキュメントを検索します。Milvusは各クエリを自動的にMinHashバイナリベクトルに変換します。Jaccard精緻化を有効にすると、推定されたJaccard類似度に基づいてLSH候補をランク付けできます。

search_params = {
    "metric_type": "MHJACCARD",
    "params": {
        "mh_search_with_jaccard": True,
        "refine_k": 3,
    },
}

results = client.search(
    collection_name="dedup_collection",
    data=["information retrieval is a research field focused on helping users find relevant data in large collections"],
    anns_field="binary_vector",
    limit=3,
    output_fields=["document_content"],
    search_params=search_params,
)

for hits in results:
    for hit in hits:
        print(f"ID: {hit['id']}, Distance: {hit['distance']}")
        print(f"Document: {hit['entity']['document_content']}")
// java
// nodejs
// go
# restful

mh_search_with_jaccard をTrue に設定すると、ジャッカード精緻化が有効になります。refine_k は、精緻化に使用される候補プールの容量を制御します。Milvusはmax(refine_k, limit) を容量として使用しますが、LSH検索で一致する候補が少ない場合は、精緻化の対象となる候補数が少なくなる場合があります。refine_k の値を大きくすると、計算負荷は増えますが、結果の品質を向上させることができます。

今後の展望

  • 全文検索:近似重複の検出ではなく、語彙的関連性のランキングにBM25を使用します。

  • アナライザーの概要:テキストのトークン化用にカスタムアナライザーを設定します。

  • MINHASH_LSH インデックス:リコール率とパフォーマンス向上のための LSH パラメータの調整について学ぶ。