私はブルームフィルターについて読んでいますが、ばかげているように見えます。ブルームフィルターで達成できることは何でも、複数のスペースではなく1つのハッシュ関数を使用して、より少ないスペースで、より効率的に達成することができます。なぜブルームフィルターを使用するのですか?
私はブルームフィルターについて読んでいますが、ばかげているように見えます。ブルームフィルターで達成できることは何でも、複数のスペースではなく1つのハッシュ関数を使用して、より少ないスペースで、より効率的に達成することができます。なぜブルームフィルターを使用するのですか?
回答:
ウィキペディアから:
ブルームフィルターは、自己均衡バイナリ検索ツリー、トライ、ハッシュテーブル、または単純な配列やエントリのリンクリストなどのセットを表すために、他のデータ構造よりも強力なスペースの利点があります。これらのほとんどは、少なくともデータ項目自体を格納する必要があり、小さな整数の場合は少数のビットから、文字列などの任意のビット数までのいずれかを必要とする可能性があります(試行は例外です。プレフィックスが等しい要素)。リンクされた構造体は、ポインターに対して追加の線形スペースオーバーヘッドが発生します。一方、エラーが1%で最適値がkのブルームフィルターでは、要素のサイズに関係なく、要素あたり約9.6ビットしか必要ありません。この利点の一部は、配列から継承されたそのコンパクトさです。部分的にはその確率的性質から。1%の誤検知率が高すぎると思われる場合は、要素ごとに約4.8ビットを追加するたびに、10倍減らします。
私にはかなり明確です。
ブルームフィルターは要素自体を格納しません。これが重要なポイントです。ブルームフィルターを使用して要素が存在するかどうかをテストするのではなく、偽陰性を保証しないため、要素が存在しないかどうかをテストするために使用します。これにより、セットに存在しない要素(それらを検索するためのディスク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です。配列のサイズが巨大であっても、ハッシュテーブルの場合のように1または0のみを格納し、URLは格納しないため、この小さなサイズが予想されます。この配列はビット配列として扱うことができます。つまり、1と0の2つの値しかないため、バイトの代わりに個別のビットを設定できます。これにより、スペースを8分の1に削減できます。この1.13 MBブルームフィルターは、サイズが小さいため、Webブラウザー自体に格納できます!! したがって、ユーザーが来てURLを入力すると、必要なハッシュ関数を(ブラウザー自体で)適用し、ブルームフィルター(ブラウザーに保存されている)のすべての位置を確認します。いずれかの位置の値が0の場合、このURLは悪意のあるURLのリストに定義されておらず、ユーザーは自由に進むことができます。したがって、サーバーを呼び出さなかったため、時間を節約できました。値1は、URLが悪意のあるURLのリストに含まれている可能性があることを示しています。これらのケースでは、リモートサーバーを呼び出し、その上で、最初のケースと同様に、ハッシュテーブルを含む他のハッシュ関数を使用して、URLが実際に存在するかどうかを取得して確認できます。ほとんどの場合、URLは悪意のあるURLである可能性が低いため、ブラウザの小さなブルームフィルタがそれを認識し、リモートサーバーへの呼び出しを回避することで時間を節約します。一部の場合にのみ、ブルームフィルターによってURLが悪意のある可能性があると通知された場合にのみ、サーバーに呼び出しを行います。その「MIGHT」は99%正しいです。これらのケースでは、リモートサーバーを呼び出し、その上で、最初のケースと同様に、ハッシュテーブルを含む他のハッシュ関数を使用して、URLが実際に存在するかどうかを取得して確認できます。ほとんどの場合、URLは悪意のあるURLである可能性は低いため、ブラウザの小さなブルームフィルタがそれを認識し、リモートサーバーへの呼び出しを回避することで時間を節約します。一部の場合にのみ、ブルームフィルターによってURLが悪意のある可能性があると通知された場合にのみ、サーバーに呼び出しを行います。その「MIGHT」は99%正しいです。これらのケースでは、リモートサーバーを呼び出し、その上で、最初のケースと同様に、ハッシュテーブルを含む他のハッシュ関数を使用して、URLが実際に存在するかどうかを取得して確認できます。ほとんどの場合、URLは悪意のあるURLである可能性が低いため、ブラウザの小さなブルームフィルタがそれを認識し、リモートサーバーへの呼び出しを回避することで時間を節約します。一部の場合にのみ、ブルームフィルターによってURLが悪意のある可能性があると通知された場合にのみ、サーバーに呼び出しを行います。その「MIGHT」は99%正しいです。ブラウザーの小さなブルームフィルターはそれを計算し、リモートサーバーへの呼び出しを回避することで時間を節約します。一部の場合にのみ、ブルームフィルターによってURLが悪意のある可能性があると通知された場合にのみ、サーバーに呼び出しを行います。その「MIGHT」は99%正しいです。ブラウザーの小さなブルームフィルターはそれを計算し、リモートサーバーへの呼び出しを回避することで時間を節約します。一部の場合にのみ、ブルームフィルターによってURLが悪意のある可能性があると通知された場合にのみ、サーバーに呼び出しを行います。その「MIGHT」は99%正しいです。
したがって、ブラウザーで小さなブルームフィルターを使用することで、入力されたすべてのURLに対してサーバー呼び出しを行う必要がないため、時間を大幅に節約できました。
単一のハッシュ関数を持つハッシュテーブルが、ブルームフィルターとはまったく異なる目的で使用されていることがわかります。うまくいけば、これはあなたの疑問を解消します:)
Pythonでの悪意のあるURLテストのタスクにブルームフィルターを実装しました。コードはここにあります-https://github.com/tarunsharma1/Bloom-Filter コードは非常に理解しやすく、詳細な説明はreadmeファイルに記載されています。
HashSet<String>
テーブルは、ハッシュテーブルが完全にいっぱいである最良のシナリオで、要素要素ごとに16バイトを使用します。4バイトは、「バケット」からエントリテーブルのエントリにマッピングされます(配列でパックされた単一リンク)リスト)、キャッシュされたハッシュコード用に4バイト、「次の」ポインター用に4バイト、キーへのポインター用に4バイト。そして、それは文字列のサイズを数えていません。最悪の場合、40 String
バイトです。64ビットアーキテクチャの場合、ポインタが8バイトに拡大すると、エントリの半分が使用されず、エントリあたり20バイトになります。
まず、ブルームフィルターとは何か、何が可能で何ができないのか、なぜそれが必要なのか、直感的な説明でどのように機能するのかを説明し、次にそれらが役立つ場合の例をいくつか示します。
したがって、標準のブルームフィルターは、次のことができる確率的データ構造です*:
definitely not in the set
かpossibly in the set
これpossibly in the set
がまさに確率論と呼ばれる理由です。スマートワードを使用するということは、偽陽性が発生する可能性があることを意味します(要素が陽性であると誤って判断する場合もあります)が、偽陰性は不可能です。
しかし、それはできません *:
* この缶のセットは、基本的なブルームフィルター用です。それはずっと前に作成された有用なデータ構造であるため、人々は他の有用な機能でそれを増強する方法を見つけました。
しかし、少し待ってください。あいまいな「可能性」なしに、またすべての制限なしにこれをすべて解決できる(削除できない、すべてを表示できない)データ構造がすでにわかっています。そして、それはセットと呼ばれています。そしてここにブルームフィルターの主な利点があります。それはスペース効率がよく、スペース定数です。
つまり、そこに格納する要素の数は問題ではなく、スペースは同じになります。はい、10^6
要素のあるブルームフィルター(役に立たないブルームフィルター)は、要素のあるブルームフィルターと同じ量のスペースと、10^20
要素のあるブルームフィルターと同じスペースを取り0
ます。それではどのくらいのスペースが必要でしょうか?決めるのはあなた次第です(しかし、トレードがあります:要素が多いほど、possible in the set
答えが不確かになります。
別のクールなことは、それが空間定数であることです。データをセットに保存するときは、実際にこのデータを保存する必要があります。したがって、保存this long string in the set
する場合は、少なくとも27バイトのスペースを使用する必要があります。しかし、1%のエラーとk **の最適値の場合、要素ごとに〜9.6ビット(<2バイト)が必要になります(短いintであるか、テキストの巨大な壁であるかにかかわらず)。
別の特性は、すべての操作が一定の時間を費やしていることです。これは、セットの場合の償却一定時間とは完全に同じではありません(セットに衝突がある場合、O(n)
時間の経過とともに悪化する可能性があることを忘れないでください)。
** kは、ブルームフィルターで使用されるハッシュ関数の値です。
ブルームフィルターのしくみについては説明しません(ウィキペディアの記事では、すべてを説明するのに非常に優れています)。ここでは、基本を簡単に説明します。
m
k
異なるハッシュ関数を選択します(独立性が高いほど良い)k
、この値のすべてのハッシュを計算し、対応するビットを1に設定しますk
ハッシュも計算し、それらの少なくとも1つが設定されていない場合は、確かにセットに含まれていません。それ以外の場合は、セットに含めることができます。この説明でさえ、なぜ確信が持てないのかを理解するには十分です(他のさまざまな値からすべてのビットを設定できます)。これは、それがどのように機能するかについての非常に素晴らしい視覚化です。
では、ブルームフィルターはいつ役立つのでしょうか。短い答えは、誤検知が許容され、セットに何かが含まれているかどうかを確認する必要があるすべての場所ですが、そうでない場合でも、検証者への高価な呼び出しを除外することは、防御の最前線になる可能性があります。
以下は、より具体的な説明のリストです。
ブルームフィルターは、バイオインフォマティクスで非常に便利です。特に、使用している文字列のサイズが非常に小さなアルファベットの数億の文字、つまり{A、G、T、C}である場合は、通常のハッシュを使用するよりもスペース効率が高くなります。それらは通常、特定のk-merがゲノムに存在するかどうかを評価するために使用されます。ここに関連する何かに使用されるものの例があります。
編集:
複数のハッシュ関数は、誤検知を最小限に抑えるために使用されます。すべてのkハッシュ関数の間で、各値は、他のすべての可能な値と比較して、ビット配列内に一意の署名を持つことになります。ただし、誤検知は存在しますが、管理可能なレベルに最小化できます。この技術を使用して、あなたは要素ハッシュ独立して自分のサイズのを。それらを検索するときは、各ハッシュ関数を使用して、ビット値がすべて1であることを確認します。
これを人間のゲノムと比較すると、要素のサイズが増加すると、ハッシュテーブルのサイズが大幅に増加します(テーブルサイズは4 * 4 kです)。これは、2ビット/文字を使用して要素をエンコードすることを前提としています。