類似検索、パート6:LSHフォレストによるランダム射影

類似検索、パート6:LSHフォレスト

ランダムハイパープレーンを構築してデータのハッシュ化と類似性の反映を理解する

「類似性検索」とは、クエリが与えられた場合、データベース内のすべてのドキュメントの中からそれに最も類似したドキュメントを見つけることを目的とした問題です。

導入

データサイエンスでは、類似性検索はNLP領域、検索エンジン、またはレコメンドシステムなどで頻繁に使用され、クエリに対して最も関連性の高いドキュメントやアイテムを取得する必要があります。大量のデータの検索性能を向上させるためのさまざまな方法が存在します。

前回は、LSHの主なパラダイムである入力ベクトルを低次元のハッシュ値に変換し、類似性に関する情報を保持する方法を見てきました。ハッシュ値(シグネチャ)を取得するためには、minhash関数が使用されました。この記事では、入力データをランダムに射影して類似したバイナリベクトルを得る方法について説明します。

類似性検索、パート5:局所敏感ハッシング(LSH)

類似性情報をハッシュ関数に組み込む方法を探る

towardsdatascience.com

アイデア

高次元空間に存在する一群の点を考えてみましょう。ランダムなハイパープレーンを構築することで、それぞれの点を正と負の2つのサブグループに分けることができます。正の側には「1」が割り当てられ、負の側には「0」が割り当てられます。

3D空間において2つの点を分離するハイパープレーンの例

あるベクトルのハイパープレーンの側はどのように決定されるのでしょうか?内積を使用することで判定できます!線型代数の本質に迫ると、与えられたベクトルとハイパープレーンの法線ベクトルの内積の符号によって、ベクトルがどの側にあるかが決まります。これにより、データセットの各ベクトルは2つの側のいずれかに分離されます。

ベクトルの内積を計算し、ハイパープレーンの法線ベクトルと比較することで、ベクトルがハイパープレーンに対してどの側に位置しているかがわかります

明らかに、データセットの各ベクトルを1つのバイナリ値でエンコードするだけでは不十分です。したがって、複数のランダムハイパープレーンを構築する必要があります。これにより、各ベクトルは特定のハイパープレーンに対する相対的な位置に基づいて、0と1の複数の値でエンコードされます。2つのベクトルが完全に同じバイナリコードを持つ場合、構築されたハイパープレーンのどれもそれらを異なる領域に分離することができなかったことを示しています。したがって、実際には非常に近い可能性があります。

与えられたクエリの最近傍点を見つけるためには、クエリをすべてのハイパープレーンに対して相対的な位置を調べ、0と1でエンコードするだけで十分です。クエリのために見つかったバイナリベクトルは、データセットベクトル用に得られたすべての他のバイナリベクトルと比較することができます。これは、ハミング距離を使用して線形に行うことができます。

2つのベクトル間のハミング距離は、その値が異なる位置の数です。

ハミング距離の計算例。左側の2つのベクトルのハミング距離が小さいため、より似ていると言えます。

クエリに対してハミング距離が最も少ないバイナリベクトルが候補として選ばれ、初期クエリと完全に比較されます。

なぜハイパープレーンはランダムに構築されるのですか?

現時点では、ハイパープレーンがランダムに構築される理由と、データセットのポイントを分離するためのカスタムルールが定義されていない決定論的な意味での方法を要求するのは論理的に思えます。これには2つの主な理由があります:

  • まず第一に、決定論的なアプローチはアルゴリズムを一般化することができず、オーバーフィッティングを引き起こす可能性があります。
  • 第二に、ランダム性により、アルゴリズムのパフォーマンスに関する確率的な声明をすることが可能になります。これは入力データに依存しないからです。決定論的なアプローチでは、これはうまく機能するかもしれませんが、別のデータではパフォーマンスが低下する可能性があります。これについての良い類似例は、決定論的なクイックソートアルゴリズムです。これは平均して O(n * log n) の時間で動作しますが、最悪の場合ではソート済みの配列では O(n²) の時間がかかります。アルゴリズムのワークフローに関する知識がある場合、常に最悪のケースのデータを提供することでシステムの効率を大幅に損なうことができます。そのため、ランダム化されたクイックソートのほうがはるかに好まれます。ランダムハイパープレーンでもまったく同様の状況が発生します。

LSHランダムプロジェクションはなぜ「ツリー」とも呼ばれるのですか?

ランダムプロジェクション法は、時々LSHツリーと呼ばれます。これは、ハッシュコードの割り当てプロセスを現在のハイパープレーンの負の側または正の側にベクトルがあるかどうかの条件を含む意思決定ツリーの形式で表現できるためです。

最初のノードはベクトルが赤いハイパープレーンの相対的な側にあるかどうかをチェックします。2番目のレベルのノードは同じ条件を確認しますが、緑のハイパープレーンの相対的な側に対してです。最後のレベルでは、青いハイパープレーンの相対的な位置をチェックします。これらの3つの条件に基づいて、ベクトルに3ビットのハッシュが割り当てられます。

ハイパープレーンの集合

ハイパープレーンはランダムに構築されます。これにより、データセットのポイントをうまく分離できないシナリオが発生する場合があります。以下の図に示されています。

データセットのポイントを4ビットのバイナリベクトルとして表すために4つのハイパープレーンが構築されます。DとEのポイントは同じハッシュコードを持っているにもかかわらず、実際にはお互いに非常に遠いです(FP)。EとFのペアでは逆の状況が発生し、異なる領域に位置しているにもかかわらず非常に近いです(FN)。ハミング距離を考慮すると、アルゴリズムは通常、ポイントDをポイントEよりもポイントFに近いと予測します。

技術的には、2つのポイントが同じハッシュコードを持ちながら互いに遠くにある場合は大したことではありません。アルゴリズムの次のステップでは、これらのポイントが候補として取り込まれ、完全に比較されます。これにより、誤検出されたケースを除外することができます。誤検出の場合はより複雑です。2つのポイントが異なるハッシュコードを持つが実際には近くにある場合です。

なぜ古典的な機械学習の決定木と同様のアプローチを使用しないのですか?それらはランダムフォレストに組み合わされて、全体的な予測品質を向上させることができます。1つの推定器がエラーを犯した場合、他の推定器がより良い予測を行い、最終的な予測エラーを緩和することができます。このアイデアを利用すると、ランダムハイパープレーンの構築プロセスを独立して繰り返すことができます。結果のハッシュ値は、前の章での最小ハッシュ値の場合と同様に、2つのベクトルのために集約されます:

もしクエリが別のベクトルと少なくとも一度同じハッシュコードを持っている場合、それらは候補とみなされます。

この仕組みを使用すると、誤りの陰性(false negative)の数を減らすことができます。

品質と速度のトレードオフ

データセット上で実行する適切な数のハイパープレーンを選ぶことが重要です。データセットのポイントを分割するために選択されるハイパープレーンが多いほど、衝突が少なくなり、ハッシュコードの計算にかかる時間と保存に必要なメモリが増えます。具体的には、データセットがn個のベクトルで構成され、k個のハイパープレーンで分割する場合、平均的にはすべての可能なハッシュコードがn / 2ᵏ個のベクトルに割り当てられます。

k = 3 results in ²³ = 8 buckets

計算量

トレーニング

LSH Forestのトレーニングフェーズは2つのパートで構成されます:

  1. k個のハイパープレーンの生成。これは比較的高速な手順であり、d次元空間の単一のハイパープレーンを生成するのにO(d)の時間がかかります。
  2. すべてのデータセットベクトルにハッシュコードを割り当てる。特に大規模なデータセットの場合、このステップには時間がかかる場合があります。単一のハッシュコードを取得するにはO(dk)の時間がかかります。データセットがn個のベクトルから構成される場合、合計の計算量はO(ndk)になります。

上記のプロセスは、フォレスト内の各ツリーに対して数回繰り返されます。

Training complexity

推論

LSH Forestの利点の一つは、高速な推論です。推論は次の2つのステップで行われます:

  1. クエリのハッシュコードを取得する。これはk個のスカラー積を計算することに相当し、O(dk)の時間がかかります(dは次元数)。
  2. 同じバケット(同じハッシュコードを持つベクトル)内のクエリに対する最近傍のベクトルを見つけるため、候補までの正確な距離を計算します。距離の計算はO(d)で線形に行われます。平均的に、各バケットにはn / 2ᵏ個のベクトルが含まれます。したがって、すべての候補への距離計算にはO(dn / 2ᵏ)の時間がかかります。

合計の計算量はO(dk + dn / 2ᵏ)です。

通常のように、上記のプロセスはフォレスト内の各ツリーに対して数回繰り返されます。

Inference complexity

ハイパープレーンの数kがn ~ 2ᵏとなるように選ばれる場合(ほとんどの場合可能です)、合計の推論の計算量はO(ldk)となります(lはツリーの数)。基本的には、計算時間はデータセットのサイズに依存しないことを意味します!この微妙さにより、数百万または数十億のベクトルに対する類似性検索の効率的なスケーラビリティが実現されます。

エラーレート

LSHに関する前半の記事では、2つのベクトルが候補として選ばれる確率を、シグネチャの類似性に基づいて求める方法について説明しました。ここでは、ほぼ同じロジックを使用してLSH Forestの式を求めます。

Let s be the probability that two vectors have the same bit at the same position of their hash values (s will be estimated later)
The probability that hash codes of length k of two vectors are equal
2つのベクトルのハッシュコードの長さkが異なる(または少なくとも1ビットが異なる)確率
2つのベクトルのすべてのl個(lハイパープレーン)のハッシュコードが異なる確率
2つのベクトルのl個のハッシュコードのうち少なくとも1つが等しい確率、つまりベクトルが候補になる確率

これまでに、2つのベクトルが候補である確率を推定するための式をほぼ得ることができました。唯一残っているのは、式中の変数sの値を推定することです。クラシックなLSHアルゴリズムでは、sは2つのベクトルのジャカード指数またはシグネチャ類似度と等しいです。一方、LSHフォレストでは、線形代数理論を使用してsを推定します。

正直に言うと、sは2つのベクトルaとbが同じビットを持つ確率です。この確率は、ランダムなハイパープレーンがこれらのベクトルを同じ側に分離する確率と同等です。これを可視化してみましょう:

ベクトルaとbは青いハイパープレーンによって分離されます。緑のハイパープレーンはそれらを分離しません。

図から明らかなように、ハイパープレーンがベクトルaとbを分離し、異なる側に配置するのは、それらの間を通過する場合のみです。このような確率qは、簡単に計算できるベクトル間の角度に比例します:

ランダムなハイパープレーンが2つのベクトルを分離する(つまり、異なるビットを持つ)確率
ランダムなハイパープレーンが2つのベクトルを分離しない(つまり、同じビットを持つ)確率

この式を先程得られた式に代入すると、最終的な式になります:

ハイパープレーンの数kとLSHツリーの数lに基づく、2つのベクトルが少なくとも1つの対応するハッシュ値を持つ確率(つまり、候補になる確率)

可視化

最後に得られた式を使用して、異なるハイパープレーンの数kおよびツリーの数lに基づいて、2つのベクトルが候補である確率をコサイン類似度に基づいて可視化してみましょう。

ツリーの数lを調整する
ハイパープレーンの数kの調整

プロットに基づいていくつかの有用な観察ができます:

  • コサイン類似度が1のベクトルのペアは常に候補になります。
  • コサイン類似度が0のベクトルのペアは決して候補になりません。
  • ハイパープレーンの数kが減少するか、LSHツリーの数lが増加すると、2つのベクトルが候補になる確率Pが増加します(つまり、偽陽性が増加します)。逆の主張も真です。

まとめると、LSHは非常に柔軟なアルゴリズムです:与えられた問題に基づいて異なる値kとlを調整し、問題の要件を満たす確率曲線を取得することが可能です。

次の例を見てみましょう。l = 5つのツリーがk = 10のハイパープレーンで構築されています。それ以外にも、コサイン類似度が0.8の2つのベクトルがあります。ほとんどのシステムでは、このようなコサイン類似度は、ベクトルが実際に非常に近いことを示しています。前のセクションの結果に基づくと、この確率はわずか2.5%です!明らかに、このような高いコサイン類似度に対しては非常に低い結果です。l = 5およびk = 10のこれらのパラメータを使用すると、非常に多くの偽陰性が発生します!以下の緑色の線は、この場合の確率を表しています。

2つのベクトルのコサイン類似度に基づく確率曲線

この問題は、より適切なkとlの値を調整することで解決できます。

例えば、kを3に減らすと(赤い線)、コサイン0.8の同じ値は以前よりも優れた68%の確率に対応します。初めに見ると、赤い線の方が緑の線よりも適しているように思えますが、赤い線のように小さなkの値を使用することは、非常に多くの衝突を引き起こします。そのため、2番目のパラメータであるツリーの数lを調整することを好む場合もあります。

kとは異なり、同様の線形状を得るには非常に高い数のツリーlが必要です。図では、青い線は緑の線からlの値を10から500に変更することで得られます。青い線は明らかに緑の線よりも適していますが、まだ完璧とは言えません:コサイン類似度が0.3-0.5の範囲で確率がほぼ0になるため、0.3-0.5のドキュメント類似度に対するこの小さな確率は好ましくありません。このような場合、実際の生活では0.3-0.5のドキュメント類似度の確率は通常よりも高くなるべきです。

最後の例に基づいて、非常に多くのツリー(多くの計算を必要とする)を使用しても、まだ多くの偽陰性が発生することが明らかです!これがランダムプロジェクション法の主な欠点です:

完璧な確率曲線を得ることは理論的に可能ですが、多くの計算が必要になるか、多くの衝突が発生します。そうでない場合、高い偽陰性率になります。

Faissの実装

Faiss(Facebook AI Search Similarity)は、最適化された類似検索に使用されるC++で書かれたPythonライブラリです。このライブラリは、データを効率的に格納し、クエリを実行するために使用されるデータ構造であるインデックスの異なるタイプを提供します。

Faissのドキュメントからの情報に基づいて、LSHインデックスの構築方法を調べます。

ランダムプロジェクションのアルゴリズムは、FaissのIndexLSHクラスの中で実装されています。Faissの作者は「ランダム回転」と呼ばれるわずかに異なる技術を使用していますが、これはこの記事で説明されているものと類似しています。このクラスは単一のLSHツリーのみを実装しています。LSHフォレストを使用したい場合は、単に複数のLSHツリーを作成し、その結果を集計するだけで十分です。

IndexLSHクラスのコンストラクタには2つの引数があります:

  • d: 次元数
  • nbits: 1つのベクトルをエンコードするのに必要なビット数(可能なバケットの数は2ⁿᵇᶦᵗˢと等しい)

search() メソッドで返される距離は、クエリベクトルまでのハミング距離です。

FaissのIndexLSHの実装

さらに、Faissでは、faiss.vector_to_array(index.codes) メソッドを呼び出すことで、各データセットベクトルのエンコードされたハッシュ値を調査することができます。

すべてのデータセットベクトルはnbitsのバイナリ値によってエンコードされるため、1つのベクトルを格納するのに必要なバイト数は次の式で計算できます:

Johnson-Lindenstraussの補題

Johnson-Lindenstraussの補題は、次元削減に関連する素晴らしい補題です。元の文言を完全に理解することは難しいかもしれませんが、簡単な言葉で表現すると次のようになります:

ランダムなサブセットを選び、元のデータをそれに射影することで、各点間の相対的な距離をほぼ保存することができます。

より正確に言うと、n個の点からなるデータセットがある場合、それらをO(logn)次元の新しい空間で表現することができます。このとき、点間の相対的な距離はほぼ保存されます。ベクトルがLSH法で約lognビットでエンコードされている場合、この補題を適用することができます。さらに、LSHは補題が要求するようにランダムな方法でハイパープレーンを作成します。

Johnson-Lindenstraussの補題の素晴らしい点の1つは、新しいデータセットの次元数が元のデータセットの次元数に依存しないという事実です!実際には、この補題は非常に小さい次元にはうまく機能しません。

結論

類似性検索のための強力なアルゴリズムを紹介しました。ランダムなハイパープレーンによる点の分離というシンプルなアイデアに基づいているため、大規模なデータセットでのパフォーマンスもスケーリングも非常に優れています。さらに、適切なハイパープレーンの数や木の選択を可能にする柔軟性も備えています。

Johnson-Lindenstraussの補題から得られる理論的な結果は、ランダム射影アプローチの使用を補強しています。

参考文献

  • LSH Forest: 類似性検索のための自己チューニングインデックス
  • Johnson-Lindenstraussの補題
  • Faissドキュメント
  • Faissリポジトリ
  • Faissインデックスの概要

特記以外のすべての画像は著者のものです。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

AIテクノロジー

「Voicemod AIで自分自身のAIボイスを作成しましょう」

自分自身と会話できる世界を想像してみてください。実際には、あなたの声はあなたが望むものになることができます。それは、V...

機械学習

「AIガバナンスの12のコア原則」

ベテランのAI開発者であるサラは、道徳的な十字路に立たされた一つのアルゴリズムは効率を最大化する一方で、プライバシーの...

AIニュース

「ChatGPTは人間の創造性テストでトップ1%のスコアを獲得」

人工知能(AI)は、モンタナ大学とそのパートナーによる研究によれば、新たな高みに達しました。この研究では、チャットGPTが...

人工知能

「AI時代における組織の価値を引き出す」

「AIはAIに脅かされるのではなく、より能力を高め、自主性を増し、強い関係を築くことによって、個人の自己決定力を向上させ...

機械学習

「ステーブル拡散」は実際にどのように機能するのでしょうか?直感的な説明

この短い記事では、初心者に対して安定した拡散(Stable Diffusion)が直感的にどのように機能するかを説明していますこれは...

AIニュース

フォートペック族のメンバーとグーグラーが集まり、社会的な利益をもたらす技術について学び、祝福し、支援するために出会います

「責任あるイノベーションに重点を置くGoogleチームが、モンタナ州のフォートペック族を訪れ、関係構築と双方向の学びを行い...