メインコンテンツまでスキップ

MinHash 関数

MinHash 関数は、生のテキストを、ドキュメント間の Jaccard 類似度 を近似するバイナリベクトルに変換します。テキストのシングリングと複数のハッシュ関数を適用して固定長の署名ベクトルを生成し、大規模な近似重複検出とドキュメントの重複排除を高速に実行できます。

MinHash は組み込み関数として Zilliz Cloud 内で実行され、外部のモデル推論や前処理は不要です。生のテキストを挿入すると、Zilliz Cloud が MinHash 署名ベクトルを自動的に生成します。

制限​

  • 各 MinHash 署名は 32 ビットのハッシュ値であるため、出力フィールドは、dim % 32 == 0 を満たすディメンションの BINARY_VECTOR である必要があります。

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

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

MinHash の仕組み​

展開して仕組みを表示

MinHash は、集合間の Jaccard 類似度 を推定する局所性鋭敏型ハッシュ手法です。Zilliz Cloud では、MinHash 関数は次のパイプラインに従います。生のテキストを入力として提供すると、Zilliz Cloud がバイナリベクトルを出力として生成し、すべての中間ステップを内部で処理します。

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

IaqkbFEh8oQgGSx6NsocFoSOnDo

共有テキスト処理パイプライン​

ドキュメントの取り込みとクエリ処理はどちらも、生のテキストを同じ 4 段階の変換に通します。

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

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

  3. MinHash 署名の生成: 複数のハッシュ関数(H1、H2、...、Hn。ここで n = num_hashes)を shingle の集合に適用します。各ハッシュ関数について、すべての shingle の中で最小のハッシュ値を選択します。これらの最小値のコレクションが MinHash 署名を形成します。これは、元のドキュメントの Jaccard 類似度を近似する固定長の表現です。

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

ドキュメントの取り込み​

挿入時には、共有パイプラインで生成されたバイナリベクトルが MINHASH_LSH インデックスに保存されます。インデックスは、類似した署名を同じバケットにグループ化する LSH(Locality-Sensitive Hashing)テーブルを維持するため、クエリ時に候補を高速に取得できます。

クエリ処理​

検索時には、クエリテキストが同じ共有パイプラインを通ってバイナリベクトルを生成します。このベクトルは MINHASH_LSH インデックスでの LSH ルックアップに使用され、類似している可能性が高い候補ペアを迅速に特定します。Jaccard リファインメントが無効な場合、Zilliz Cloud は推定 Jaccard 類似度でランク付けされていない LSH 候補を返します。Jaccard リファインメントが有効な場合、Zilliz Cloud は保存された生の MinHash 署名を使用して、推定 Jaccard 類似度で候補をランク付けし、上位 K 件の結果を返します。

両方のパスが同じ変換ロジックを共有するため、内容が大きく重複する 2 つのドキュメントは類似した MinHash 署名を生成します。そのため、ドキュメントの語順、書式、または軽微な表現が異なる場合でも、この関数は近似重複の検出に効果を発揮します。

事前準備​

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

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

    コレクションには、生のテキストを保存する VARCHAR フィールドを含める必要があります。このフィールドは、MinHash 関数への入力として使用されます。

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

    token_level が "word"(デフォルト)に設定されている場合、テキストフィールドでアナライザーを有効にする必要があります。アナライザーは、shingling の前にテキストをトークン化する方法を定義します。デフォルトでは、Zilliz Cloud は standard アナライザーを使用します。別のアナライザーを設定するには、Choose the Right Analyzer for Your Use Case を参照してください。

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

    コレクションには、MinHash 関数で生成されるバイナリベクトルを保存する BINARY_VECTOR フィールドを含める必要があります。ディメンションは 32 * num_hashes と等しい必要があります。

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

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

スキーマフィールドを定義する​

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

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

  • テキストフィールド(VARCHAR):生のテキストドキュメントを保存します。Zilliz Cloud が MinHash 署名の生成のためにテキストを処理できるよう、enable_analyzer=True を設定します。デフォルトでは、Zilliz Cloud はテキスト分析に standard アナライザーを使用します。別のアナライザーを設定するには、Choose the Right Analyzer for Your Use Case を参照してください。

  • バイナリベクトルフィールド(BINARY_VECTOR):MinHash 関数によって自動的に生成されたバイナリベクトルを保存します。ディメンションは 32 * num_hashes と等しい必要があります。

python
from pymilvus import MilvusClient, DataType, Function, FunctionType

client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")

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)

MinHash 関数を定義する​

MinHash 関数は、分析済みのテキストを、ドキュメント間の Jaccard 類似度を近似するバイナリベクトルに変換します。

関数を定義してスキーマに追加します。

python
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)

設定オプション

MinHash 関数の params ディクショナリは、次のパラメーターを受け入れます。すべてのパラメーター名は大文字と小文字を区別しません。

パラメーター

型

デフォルト

説明

num_hashes

int

dim / 32 から算出されます。

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

shingle_size

int

3

shingling に使用する n-gram のサイズです。単語レベルの場合、通常は 1〜3 です。文字レベルの場合、通常は 2〜6 です。

hash_function

str

"xxhash"

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

  • "xxhash"(高速)

  • "sha1"(低速ですが、衝突耐性が高い)。

token_level

str

"word"

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

  • "word":フィールドのアナライザーを使用してトークン化してから、n-gram shingling を適用します。

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

単語レベルはより強いセマンティクスと高い効率を提供しますが、言語固有のトークン化に依存します。文字レベルは言語に依存しませんが、セマンティクスが弱い高次元の shingle を生成します。

seed

int

1234

MinHash 関数の初期化に使用する乱数シードです。

インデックスを設定する​

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

python
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,
},
)

検索で Jaccard リファインメントを使用する場合は、with_raw_data を True に設定します。LSH ルックアップで返された候補の推定 Jaccard 類似度を計算するには、生の MinHash 署名が必要です。

コレクションを作成する​

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

python
client.create_collection(
collection_name="dedup_collection",
schema=schema,
index_params=index_params,
)

ステップ 2: ドキュメントを挿入する​

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

python
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"},
],
)

ステップ 3: MinHash で検索する​

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

python
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']}")

Jaccard リファインメントを有効にするには、mh_search_with_jaccard を True に設定します。refine_k は、リファインメントに使用する候補プールの容量を制御します。Zilliz Cloud は max(refine_k, limit) を容量として使用しますが、LSH ルックアップで返される一致数が少ない場合は、リファインメント対象の候補が少なくなることがあります。refine_k を増やすと、追加の計算コストと引き換えに結果の品質が向上する可能性があります。

次のステップ​

  • Full Text Search: 近似重複検出の代わりに、BM25 を使用して語彙的な関連性ランキングを行います。

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

  • MINHASH_LSH インデックス: 再現率とパフォーマンスのために LSH パラメーターを調整する方法について説明します。