5分でブルームフィルタを理解する。10億レベルのデータフィルタリングアルゴリズムは、知っておく価値があります。

5分でブルームフィルタを理解する。10億レベルのデータフィルタリングアルゴリズムは、知っておく価値があります。

[[339720]]

この記事はWeChatの公開アカウント「Uncle Who Knows a Little Code」から転載したもので、著者はUncle Who Knows a Little Codeです。この記事を転載する場合は、Uncle Who Knows Codeの公式アカウントまでご連絡ください。

Bloom フィルターについて正式に説明する前に、次のビジネス シナリオを見てみましょう。

Redis は、ソフトウェア アーキテクチャでよく使用されるコンポーネントです。最も一般的な使用方法は、データベースへの負荷を軽減するために、ホット データを Redis にキャッシュすることです。クエリ プロセス中に最も一般的な使用方法は、Redis をクエリすることです。データが見つかった場合は、直接返されます。Redis に存在しない場合は、データベースのクエリを続行します。

この方法により、データベース アクセスの回数を減らすことができますが、「データがキャッシュにないときにデータベースをクエリする」ことは、同時実行性の高い環境では依然としてリスクを伴います。たとえば、要求されたデータの 90% がキャッシュにない場合、これらの要求はすべてデータベースに送られ、キャッシュ侵入が発生します。

では、この問題を解決する方法はあるのでしょうか? これは、「特定のデータが確実に存在しない」ことを判断できるブルーム フィルターを使用することで解決できます。

01. ブルームフィルタの概念

ブルーム フィルタは、「ブルーム」という人物によって提案されました。それ自体は非常に長いバイナリ ベクトル (配列として想像してください) と一連のランダム マッピング関数 (複数のハッシュ関数として想像してください) です。バイナリ ベクトルには 0 または 1 が格納されます (ブルーム フィルタについて学習する前に、まず BitMap アルゴリズムを理解すると理解しやすくなります)。

例えば、顧客の携帯電話番号を条件として顧客情報を照会したい場合、通常は携帯電話番号をキャッシュのキーとして設定します。長さ 16 の Bloom フィルターを設定してみましょう。

ブルームフィルタは 0 に初期化されます。

13800000000 に対して hash1()、hash2()、hash3() 演算を実行し、5、9、12 の 3 つの結果を取得します。対応する位置を 1 に設定します。

18900000000 に対して hash1()、hash2()、hash3() 演算を実行し、2、8、12 の 3 つの結果を取得します。対応する位置を 1 に設定します。これで、2、5、8、9、12 はすべて 1 になり、残りの要素は 0 になります。

電話番号が存在するかどうかを確認したい場合はどうすればいいでしょうか?

13700000000 に対してそれぞれ hash1()、hash2()、hash3() 演算を実行し、1、9、13 の 3 つの結果を取得します。次に、1 番目、9 番目、13 番目のビットの値が 0 か 1 かを判定します。すべて 1 でない場合は、13700000000 がこの Bloom フィルター上にないことを意味し、これにより、「特定のデータが確実に存在しない」ことが確認されます。

もちろん、ブルーム フィルタには問題があることもわかります。つまり、データが存在することを保証できないということです。たとえば、18000000000 に対して hash1()、hash2()、hash3() 演算を実行すると、結果は 5、8、9 となり、たまたま 1 になります。しかし、実際にはこのデータは存在しないため、ブルーム フィルタには一定の誤判定率があります。

また、計算後に複数のデータが同一の位置にマッピングされる可能性があるため(138と189の計算結果はともに12)、ビットごとにカウンターを追加しない限り、ブルームフィルターを削除することは困難です。削除する場合は、カウンターが0になるまでカウンターから1を減算し、ブルームフィルターの対応する位置を0に変更する必要があります。

02. 機能概要

ある要素が確実に存在しないと判断することは可能ですが、ある要素が確実に存在すると判断することは不可能です。

バイナリベクトルが長いほど、マッピング関数の数が多くなり、誤判定率が低くなります。誤判定率が事前に判定できれば、ブルームフィルタの長さも推測できます。

要素は追加できますが、削除することはできません (カウンターが増加しない限り)。

挿入クエリのストレージスペースと時間の複雑さの点で大きな利点があります。

この記事の冒頭のビジネス シナリオに戻ると、キャッシュ侵入を防ぐために、ブルーム フィルターを使用して、確実に存在しないデータをフィルター処理できます。誤って判断されたリクエストはデータベースに配置されますが、侵入の数は大幅に削減されます。

03. ブルームフィルタを手書きする

コードを書くことが目的ではなく、コーディングのプロセスは理解を深めることです。

まず、ビットマップを定義する必要があります。JDK には、対応するデータ構造クラス java.util.BitSet が既に存在します。

  1. //ブルームフィルターを設定する
  2. プライベートint DEFAULT_SIZE = 1 << 30;
  3.  
  4. プライベート BitSet ビットセット;

マッピング関数のセットも必要です。ここでは、加法ハッシュ関数を使用して、6 つの異なるハッシュ関数に対応する 6 つの素数を設定できます。

  1. //長さ6の素数配列を定義し、ランダムマッピング用の6つのハッシュ関数を生成できる
  2. プライベートint []シード = {3, 7, 13, 31, 37, 61};
  3.  
  4. プライベートHashFunction[] functions = new HashFunction[seeds.length];

コンストラクターで初期化し、BitSet の長さを設定し、マッピング関数を生成します。

  1. /**
  2. * 初期化
  3. */
  4. パブリックブルームフィルタ() {
  5. ビットセット = 新しい BitSet(DEFAULT_SIZE);
  6.  
  7. ( int i = 0; i < seeds.length; i++) {
  8. functions[i] = 新しいHashFunction(DEFAULT_SIZE、seeds[i]);
  9. }
  10. }

要素を追加するときは、入力パラメータに対して 6 つのハッシュ操作を実行し、結果に対応する位置を 1 に変更します (BitSet に対応する位置は true に変更されます)。

  1. /**
  2. * 要素を追加し、ハッシュ演算の結果を取得し、対応する位置を1( true に変更します。
  3. * @パラメータ値
  4. */
  5. パブリックvoid add (文字列値) {
  6. 値 != null の場合{
  7. (HashFunction f: 関数)の場合{
  8. bitset.set (f.hash(値), true );
  9. }
  10. }
  11. }

Bloom マネージャーに要素が存在するかどうかを判断するには、入力パラメータに対して 6 つのハッシュ演算を実行し、結果の対応する位置が 0 か 1 (真か偽か) かどうかを確認する必要があります。ビットの 1 つが 0 の場合、データが確実に存在しないことを意味します。すべてが 1 の場合、データが存在する可能性がある (高い確率で存在する) ことを意味します。

  1. /**
  2. * 要素がブルームフィルタ内にあるかどうかを判定する
  3. * @パラメータ値
  4. * @戻る 
  5. */
  6. パブリックブール値には(文字列値)が含まれます{
  7. 値 == null場合
  8. 戻る 間違い;
  9. }
  10.  
  11. (HashFunction f: 関数)の場合{
  12. if(!bitset.get(f.hash(値))){
  13. //位置が1( true )でない場合は存在しないことを意味し、直接falseを返します 
  14. 戻る 間違い;
  15. }
  16. }
  17.  
  18. 戻る 真実;
  19. }

04. Guava の BloomFilter

Bloom マネージャーの実装に役立つオープンソース フレームワークはすでに多数存在します。たとえば、すぐに使用できる Bloom フィルターを備えた Google 製の Guava ツール ライブラリなどです。

  1. パブリッククラスBloomFilterTest {
  2. 公共 静的void main(String[] args){
  3. 整数 サイズ= 1000000;
  4. //ブルームフィルター
  5. BloomFilter< Integer > bloomFilter = BloomFilter.create ( Funnels.integerFunnel(),サイズ, 0.001);
  6.      
  7. ( int i = 0; i <サイズ; i++) {
  8. ブルームフィルタを put(i);
  9. }
  10.      
  11. リスト<整数> リスト = 新しい ArrayList<整数>(1000);
  12. ( int i =サイズ+ 1; i <サイズ+ 10000; i++) {
  13. if (bloomFilter.mightContain(i)) {
  14. リストに追加します(i);
  15. }
  16. }
  17. System.out.println ( "誤判定数:" +list.size ( ));
  18. }
  19. }

<<:  2020年グローバルスマート教育会議でAI教育統合イノベーションの成果が発表されました

>>:  IDC: 人工知能への世界的支出は4年で倍増すると予想

ブログ    
ブログ    
ブログ    

推薦する

ツール・ド・フランスがChatGPTとデジタルツイン技術を導入

6月30日のニュースによると、ツール・ド・フランスは世界で最も権威のある自転車レースの一つで、毎年何...

OpenVINOの新バージョンがリリースされ、視覚を超えた音声をサポートし、よりインテリジェントなエッジ開発者の力を高める

本日、インテルとその開発者エコシステム パートナーは、「インテリジェント エッジに焦点を当て、開発者...

Taとのチャットを手助けするロボットをカスタマイズする

[[427589]]自動チャットの例これは 200 万件のチャット記録に基づいてトレーニングされてい...

2000億回のオープン学習を経て、DeepMindのAIはさらに洗練されてきた

[[415688]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

百度技術委員会の呉華委員長:NLP技術は機械に人間の言語によるコミュニケーション能力を持たせるはずだ

[[211656]] 「人工知能を人間の生活に取り入れたいなら、人間とコミュニケーションできる言語能...

C#DES アルゴリズムの概念と特性の簡単な分析

C# DES アルゴリズムは開発のセキュリティ部分として、その概念といくつかの簡単な歴史的起源を理解...

最高裁:アプリは顔情報を収集・処理するためにユーザーの個別の同意が必要

最高人民法院研究室民事部の陳龍野部長は、一部のモバイルアプリケーション(APP)はしばらくの間、パッ...

C# はデジタル変換のための中国語アルゴリズムを記述します

C# はデジタル変換のための中国語アルゴリズムを記述します最近、プロジェクト上の理由により、C# で...

...

...

転移学習により、ディープラーニングは難しくなくなりました...

それほど遠くない過去には、データ サイエンス チームがディープラーニングを効果的に活用するには、いく...

AIとロボットのユースケース

人工知能とロボット工学はテクノロジー分野に大きな変化をもたらしています。 20年前に人々が夢見ていた...

...

RealAIは、業界の信頼できる発展を促進するために人工知能セキュリティ技術ツールを作成します。

4月26日、中国サイバースペース管理局の主催で「人工知能-社会実験の観点から見た社会ガバナンス」を...

マスク氏のニューラリンクが人間の脳にインターフェースを挿入するにはどれくらいの時間がかかるのでしょうか?

マスク氏は常にその知名度の高さで知られている。彼はテスラとスペースXという2つの大企業を所有している...