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

MinHash 関数

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

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

制限​

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

  • バイナリベクトルフィールドの 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(シングル)に分割されます。たとえば、単語レベルで 3-gram を使用する場合、トークン ["information", "retrieval", "is", "a", "field"] は ["information retrieval is", "retrieval is a", "is a field"] のようなシングルになります。

  3. MinHash シグネチャの生成: 複数のハッシュ関数(H1、H2、...、Hn。ここで n = num_hashes)がシングルセットに適用されます。各ハッシュ関数について、すべてのシングルの中から最小のハッシュ値が選択されます。これらの最小値のコレクションが 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"(デフォルト)に設定されている場合、テキストフィールドでアナライザーを有効にする必要があります。アナライザーは、シングリングの前にテキストをトークン化する方法を定義します。デフォルトでは、Zilliz Cloud は standard アナライザーを使用します。別のアナライザーを設定するには、ユースケースに適したアナライザーの選択 を参照してください。

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

    コレクションには、MinHash 関数によって生成されたバイナリベクトルを格納する BINARY_VECTOR フィールドを含める必要があります。次元は 32 * num_hashes と等しくなければなりません。

ステップ 1: MinHash 関数を使用したコレクションの作成​

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

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

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

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

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

  • バイナリベクトルフィールド(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

シングリングに使用する 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 です。

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 を字句関連性のランキングに使用します。

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

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