私はブルームフィルターについて読んでいますが、それらはただばかげているようです。ブルームフィルターを使用して達成できることは、少ないスペースで、より効率的に、複数ではなく単一のハッシュ関数を使用して達成することができます。ブルームフィルターを使用する理由とその有用性
から ウィキペディア :
ブルームフィルターは、自己分散バイナリ検索ツリー、試行、ハッシュテーブル、またはエントリの単純な配列またはリンクリストなど、セットを表すために他のデータ構造よりも空間的に強力な利点があります。これらのほとんどは、少なくともデータ項目自体を保存する必要があり、小さな整数の場合は少数のビットから文字列などの任意の数のビットまでのいずれかを必要とする場合があります(試行は例外です。プレフィックスが等しい要素)。リンクされた構造には、ポインターの追加の線形スペースオーバーヘッドが発生します。一方、エラーが1%で最適値がkのブルームフィルターでは、要素のサイズに関係なく、要素ごとに約9.6ビットしか必要ありません。この利点は、そのコンパクトさ、配列から継承された部分、およびその確率論的な性質に一部起因しています。 1%の誤検出率が高すぎると思われる場合は、要素ごとに約4.8ビットを追加するたびに、10倍減少します。
私にはかなり明確です。
ブルームフィルターは要素自体を保存しません。これは重要なポイントです。ブルームフィルターを使用して要素が存在するかどうかをテストするのではなく、それが確実にnot存在するかどうかをテストするために使用します。ネガ。これにより、セットに存在しない要素(disk IOを検索するなど)に対して余分な作業を行う必要がなくなります。
そして、すべてがハッシュテーブル(大規模なデータセットの場合はディスク上に部分的に存在する可能性が高い)のようなものよりも大幅に少ないスペースで。ブルームフィルターをハッシュテーブルのような構造と組み合わせて使用することもできますが、要素が存在する可能性があることを確認したら、.
したがって、使用パターンの例は次のとおりです。
ディスク上には大量のデータがあります-mの値を規定するエラーバインド(1%など)を決定します。次に、最適なkが決定されます(記事で与えられた式から)。このディスクにバインドされたデータからフィルターを1回作成します。
これで、RAMにフィルターができました。何らかの要素を処理する必要がある場合、フィルターを照会して、データセットに存在する可能性があるかどうかを確認します。そうでない場合、追加の作業は行われません。ディスクの読み取りなどはありません(ハッシュまたはツリーなどである場合に実行する必要があるもの)。
それ以外の場合、フィルターに「はい、そこにあります」と表示されている場合、1%の確率で間違っている可能性があるため、必要な作業を行って見つけます。 99%の時間、それは本当に存在するので、仕事は無駄ではありませんでした。
アレックスはそれを非常によく説明しました。それでもまだ理解していない人のために、この例を参考にしてください:
ChromeチームでGoogleに勤務しており、入力したURLが悪意のあるURLであるかどうかをユーザーに通知する機能をブラウザーに追加したいとします。約100万の悪意のあるURLのデータセット、このファイルのサイズは約25MBです。サイズは非常に大きいため(ブラウザー自体のサイズと比較して)、このデータをリモートサーバーに保存します。
ケース1:ハッシュテーブルでハッシュ関数を使用します。効率的なハッシュ関数を決定し、ハッシュ関数を介して100万のURLをすべて実行して、ハッシュキーを取得します。次に、ハッシュテーブル(配列)を作成します。ハッシュキーは、そのURLを配置するためのインデックスを提供します。そのため、ハッシュテーブルをハッシュして埋めたら、そのサイズを確認します。 100万個すべてのURLをキーとともにハッシュテーブルに保存しました。したがって、サイズは少なくとも25 MBです。このハッシュテーブルは、サイズが原因でリモートサーバーに保存されます。ユーザーがやって来て、アドレスバーにURLを入力したら、悪意があるかどうかを確認する必要があります。したがって、ハッシュ関数を介してURLを実行し(ブラウザー自体がこれを実行できます)、そのURLのハッシュキーを取得します。その特定のキーを持つハッシュテーブルの特定のURLがユーザーが入力したものと同じかどうかを確認するために、そのハッシュキーを使用してリモートサーバーに要求を行う必要があります。 「はい」の場合、悪意があり、「いいえ」の場合、悪意はありません。したがって、ユーザーがURLを入力するたびに、リモートサーバーへの要求を作成して、それが悪意のあるURLであるかどうかを確認する必要があります。これには多くの時間がかかるため、ブラウザが遅くなります。
ケース2:ブルームフィルターを使用します。 100万のURLのリスト全体が、複数のハッシュ関数を使用してブルームフィルターを通過し、それぞれの位置が0の巨大な配列で1としてマークされます。ブルームフィルター計算機( http://hur.st/bloomfilter?n=1000000&p=0.01 )を使用して、1%の偽陽性率が必要だとしましょう。ブルームフィルターのサイズを取得します。わずか1.13 MBとして必要です。この小さなサイズは、配列のサイズが巨大であるにもかかわらず、ハッシュテーブルの場合のようにURLではなく1または0のみを格納しているため、この配列はビット配列として扱われます。つまり、1と0の2つの値しかないため、バイトではなく個々のビットを設定できます。これにより、必要なスペースが8倍削減されます。この1.13 MBブルームフィルターは、サイズが小さいため、Webブラウザー自体に保存できます!!したがって、ユーザーが来てURLを入力すると、必要なハッシュ関数(ブラウザー自体)を適用し、ブルームフィルター(ブラウザーに格納されている)のすべての位置を確認します。いずれかの位置の値が0の場合、このURLは悪意のあるURLのリストに絶対に含まれていないため、ユーザーは自由に進むことができます。したがって、サーバーへの呼び出しを行わなかったため、時間を節約できました。値1は、URLが悪意のあるURLのリストに含まれていることを示しています。これらの場合、リモートサーバーへの呼び出しを行い、最初の場合のように、いくつかのハッシュテーブルで他のハッシュ関数を使用して、URLが実際に存在するかどうかを取得および確認できます。ほとんどの場合、URLは悪意のあるURLではない可能性が高いため、ブラウザーの小さなブルームフィルターはそれを把握し、リモートサーバーへの呼び出しを回避することで時間を節約します。場合によってのみ、ブルームフィルターがURL MIGHTが悪意があることを示している場合、そのような場合のみ、サーバーを呼び出します。その「MIGHT」は99%正しいです。
したがって、ブラウザーで小さなブルームフィルターを使用することで、入力されたすべてのURLに対してサーバー呼び出しを行う必要がないため、多くの時間を節約できました。
単一のハッシュ関数を持つハッシュテーブルが、ブルームフィルターとはまったく異なる目的に使用されていることがわかります。うまくいけば、これであなたの疑念が解消されるでしょう:)
Pythonでの悪意のあるURLテストのタスクにブルームフィルターを実装しました。コードはここにあります- https://github.com/tarunsharma1/Bloom-Filter コードは非常に理解しやすく、詳細な説明はreadmeファイルに記載されています。
ブルームフィルターとは何か、それができることとできないこと、なぜそれが必要なのか、それがどのように機能するのかを直感的に説明し、役立つ場合の例を挙げて説明します。
標準ブルームフィルター は 確率的データ構造 thatcan*:
definitely not in the set
_または_possibly in the set
_を指定して、要素がセット内にあるかどうかを確認しますこの_possibly in the set
_は、まさに確率論と呼ばれる理由です。スマートワードを使用すると、 false positive は可能ですが(要素が正であると誤って判断する場合もあります)、false negativeは不可能です。
しかし、それはできない *:
*このcan/ca n'tのセットは、基本的なブルームフィルター用です。ずっと前に作成された有用なデータ構造であるため、人々は augment を他の seful 機能とともに使用する方法を見つけました。
しかし、ちょっと待ってください。曖昧な「可能性」なく、すべての制限なしにすべてを解決できるデータ構造を既に知っています(削除できず、すべてを表示できません)。そして、それは set と呼ばれます。そして、ここにブルームフィルターの主な利点があります:それは空間効率と空間定数です。
これは、そこにいくつの要素を格納するかは問題ではなく、スペースは同じであることを意味します。はい、_10^6
_要素を持つブルームフィルター(不要なブルームフィルター)は、_10^20
_要素を持つブルームフィルターと同じ量のスペースを取り、_0
_要素を持つブルームフィルターと同じスペースを取ります。それで、どれくらいのスペースが必要ですか?決定するのはあなた次第です(しかし、トレードがあります:要素が多ければ多いほど、あなたはあなたと一緒にいるかどうか不確かです_possible in the set
_答え。
もう1つのクールな点は、スペースが一定であることです。データをセットに保存するとき、実際にこのデータを保存する必要があります。したがって、_this long string in the set
_を格納する場合、少なくとも27バイトのスペースを使用する必要があります。ただし、1%の誤差とkの最適値の場合 **、要素ごとに〜9.6ビット(<2バイト)が必要になります(短い整数か巨大なテキストの壁か)。
別の特性は、すべての操作が一定時間を要することです。これは、セットの場合の償却済み一定時間とはまったく異なります(セットに衝突がある場合、O(n)
時間で劣化する可能性があることに注意してください)。
**kはブルームフィルターで使用されるハッシュ関数の値です
ブルームフィルターの動作 (wikipediaの記事はすべてを説明する非常に良い仕事をしている)については説明しません。ここで、基本を簡単に説明します。
m
の空のビット配列を開始しますk
異なるハッシュ関数を選択します(独立しているほど良い)k
ハッシュを計算し、対応するビットを1に設定しますk
ハッシュも計算します。少なくとも1つが設定されていない場合は、確実に設定されていません。それ以外の場合は、セットに含めることができます。この説明でさえ、なぜわからないのかを理解するには十分です(他のさまざまな値からすべてのビットを設定できます)。 動作の非常に素晴らしい視覚化 です。
では、いつブルームフィルターが役立つのでしょうか?簡単な答えは、誤検知が許容されるすべての場所で、セットに何かがあるかどうかを確認したい場所ですが、そうでない場合でも検証者への高価な呼び出しを排除するための最初の防衛線になります。
より具体的な説明のリストは次のとおりです。
ブルームフィルターは、バイオインフォマティクスで非常に役立ちます。特に作業している文字列のサイズが非常に小さなアルファベット、つまり{A、G、T、C}の何億もの文字である場合、通常のハッシュを使用するよりもスペース効率が高くなります。通常、特定のk-merがゲノムに存在するかどうかを評価するために使用されます。関連する何かに使用される例があります here 。
編集:
複数のハッシュ関数は、誤検知を最小限に抑えるために使用されます。希望は、すべてのkハッシュ関数の間で、各値が他のすべての可能な値と比較してビット配列に一意の署名を持つことです。ただし、誤検知は存在しますが、管理可能なレベルに最小化できます。この手法を使用して、サイズの要素を独立してハッシュします。それらを検索するとき、各ハッシュ関数を使用し、ビット値がすべて1であることを確認します。
これを、要素のサイズを大きくするとハッシュテーブルのサイズが大幅に増加するヒトゲノムと比較してください(テーブルサイズは4 * 4k)。これは、2ビット/文字を使用して要素をエンコードすることを前提としています。
ブルームフィルターが、アイテムがセットのメンバーであると返した場合、誤検知が発生する可能性があります。セット内のメンバーシップを示すために単一のハッシュ関数のみが使用された場合、複数のハッシュ関数を使用するよりも誤検知の可能性が高くなります。