Apakah ada filter anti-Bloom?

25

Sebuah Bloom Filter memungkinkan untuk efisien melacak apakah berbagai nilai telah ditemui selama pengolahan. Ketika ada banyak item data maka filter Bloom dapat menghasilkan penghematan memori yang signifikan di atas tabel hash. Fitur utama dari filter Bloom, yang dibagikan dengan tabel hash, adalah selalu mengatakan "bukan baru" jika suatu item bukan barang baru, tetapi ada probabilitas bukan nol bahwa suatu barang akan ditandai sebagai "bukan barang baru" "Bahkan ketika itu baru.

Apakah ada "filter anti-Bloom", yang memiliki perilaku sebaliknya?

Dengan kata lain: apakah ada struktur data yang efisien yang mengatakan "baru" jika suatu barang baru, tetapi yang juga bisa mengatakan "baru" untuk beberapa item yang bukan barang baru?

Menyimpan semua item yang terlihat sebelumnya (misalnya, dalam daftar tertaut yang disortir) memenuhi persyaratan pertama tetapi mungkin menggunakan banyak memori. Saya berharap itu juga tidak perlu, mengingat persyaratan kedua yang santai.


Bagi mereka yang lebih menyukai perlakuan yang lebih formal, tulis jika filter Bloom menganggap adalah baru, b (x) = 0 sebaliknya, dan tulis n (x) = 1 jika x benar-benar baru dan n (x) ) = 0 sebaliknya.b(x)=1xb(x)=0n(x)=1xn(x)=0

Kemudian Pr[b(x)=0|n(x)=0]=1 ; Pr[b(x)=0|n(x)=1]=α ; Pr[b(x)=1|n(x)=0]=0 ; Pr[b(x)=1|n(x)=1]=1α , untuk beberapa 0<α<1 .

Saya bertanya: apakah ada struktur data yang efisien, menerapkan fungsi b dengan beberapa 0<β<1 , sehingga Pr[b(x)=0|n(x)=0]=β ; Pr[b(x)=0|n(x)=1]=0 ; Pr[b(x)=1|n(x)=0]=1β ; Pr[b(x)=1|n(x)=1]=1 ?


Sunting: Sepertinya pertanyaan ini telah ditanyakan sebelumnya di StackExchange, seperti /programming/635728 dan /cstheory/6596 dengan serangkaian jawaban dari "tidak bisa dilakukan "melalui" dapat dilakukan, dengan biaya "ke" itu sepele untuk dilakukan, dengan membalikkan nilai-nilai ". Belum jelas bagi saya apa jawaban "benar" itu. Apa yang jelas adalah bahwa skema LRU caching dari beberapa macam (seperti yang disarankan oleh Ilmari Karonen) bekerja cukup baik, mudah untuk menerapkan, dan menghasilkan pengurangan 50% dalam waktu yang dibutuhkan untuk menjalankan kode saya.b

András Salamon
sumber
Untuk beberapa alasan, saya tergoda untuk mengatakan bahwa ini sangat mirip dengan masalah yang berusaha diselesaikan oleh cache dan algoritma penempatan cache. Pertimbangkan cache menggunakan penggantian yang paling jarang digunakan (LFU). Algoritma penggantian yang optimal secara teoritis tetapi tidak mungkin adalah untuk mengusir yang Anda tidak akan melihat lagi untuk waktu yang lama, sama seperti untuk cache. Saya kira caching bergantung pada beberapa asumsi tentang sifat distribusi yang mungkin tidak berlaku secara umum, tetapi perlu dipertimbangkan apakah ini berlaku.
Patrick87
Anda mungkin tertarik dengan pembicaraan berikut: Filter keanggotaan set yang berbasis
kepuasan
@ Kaveh: terima kasih untuk penunjuknya, akan menonton.
András Salamon

Jawaban:

12

Sesuai dengan ide hash Patrick87, berikut ini adalah konstruksi praktis yang hampir memenuhi persyaratan Anda - kemungkinan salah mengira nilai baru untuk yang lama tidak cukup nol, tetapi dapat dengan mudah dibuat menjadi sangat kecil.

Pilih parameter dan ; nilai praktis mungkin, katakanlah, dan . Biarkan menjadi fungsi hash kriptografi aman yang menghasilkan (setidaknya) bit output.k n = 128 k = 16 H n + knkn=128k=16Hn+k

Biarkan menjadi array -bit bitstrings. Array ini menyimpan status filter, menggunakan total bit . (Tidak masalah bagaimana array ini diinisialisasi; kita bisa mengisinya dengan nol, atau dengan bit acak.)a n n 2 k2k nn2k

  • Untuk menambahkan nilai baru ke filter, hitung , di mana menunjukkan bit pertama dan menunjukkan bit . Biarkan .xi k j n H ( x ) a i = jij=H(x)ikjnH(x)ai=j

  • Untuk menguji apakah nilai telah ditambahkan ke filter, hitung , seperti di atas, dan periksa apakah . Jika ya, kembalikan benar; jika tidak, kembalikan false.i xa i = j ij=H(x)ai=j

Klaim 1: Probabilitas false positive (= nilai baru yang diklaim palsu telah terlihat) adalah . Ini dapat dibuat sewenang-wenang kecil, dengan biaya sederhana dalam ruang penyimpanan, dengan meningkatkan ; khususnya, untuk , probabilitas ini pada dasarnya dapat diabaikan, karena, dalam praktiknya, jauh lebih kecil daripada probabilitas positif palsu karena kegagalan fungsi perangkat keras. n n 1281/2n+knn128

Secara khusus, setelah nilai yang berbeda telah diperiksa dan ditambahkan ke filter, probabilitas setidaknya satu false positive terjadi adalah . Misalnya, dengan dan , jumlah nilai berbeda yang diperlukan untuk mendapatkan false positive dengan probabilitas 50% adalah sekitar .( N 2 - N ) / 2 n + k + 1 n = 128 k = 16 2 ( n + k ) / 2 = 2 72N(N2N)/2n+k+1n=128k=162(n+k)/2=272

Klaim 2: Probabilitas negatif palsu (= nilai tambah sebelumnya yang diklaim palsu sebagai baru) tidak lebih besar dari , di mana adalah jumlah nilai berbeda yang ditambahkan ke filter (atau, lebih khusus, jumlah nilai berbeda yang ditambahkan setelah nilai spesifik yang diuji paling baru ditambahkan ke filter). N1(12k)N1exp(N/2k)<N/2kN


Ps. Untuk menempatkan "sangat kecil" ke dalam perspektif, enkripsi 128-bit umumnya dianggap tidak dapat dipecahkan dengan teknologi yang saat ini dikenal. Mendapatkan false positive dari skema ini dengan adalah sama mungkin dengan seseorang yang menebak kunci enkripsi 128-bit rahasia Anda dengan benar pada upaya pertama mereka . (Dengan dan , sebenarnya sekitar 65.000 kali lebih kecil dari itu.)n = 128 k = 16n+k=128n=128k=16

Tetapi jika itu masih membuat Anda merasa gugup secara tidak rasional, Anda selalu dapat beralih ke ; itu akan dua kali lipat kebutuhan penyimpanan Anda, tapi aku bisa bertaruh Anda setiap jumlah yang anda akan peduli untuk nama yang tak seorang pun akan pernah melihat positif palsu dengan - dengan asumsi bahwa fungsi hash tidak rusak, anyway.n = 256n=256n=256

Ilmari Karonen
sumber
1
Tidak hanya probabilitas yang dapat dibuat sebanding dengan kerusakan perangkat keras; itu juga dapat dibuat sebanding dengan probabilitas seseorang menebak kunci RSA Anda untuk login SSH pada percobaan pertama . IMO yang terakhir menyampaikan kepraktisan solusi Anda lebih dari yang sebelumnya.
R ..
+1 Sangat bagus - pemahaman saya adalah ini memecahkan masalah efisiensi ruang dengan memungkinkan beberapa (sangat kecil) peluang salah menjawab "bukan baru" ketika item tersebut, pada kenyataannya, baru. Sangat praktis, dan analisisnya bagus.
Patrick87
1
Klaim 1 hanya menyatakan bahwa fungsi hash yang layak memiliki kemungkinan tabrakan yang rendah. Ini benar dalam praktiknya jika setidaknya 50 atau lebih. Untuk aplikasi saya, dan berfungsi dengan baik dengan fungsi 64-bit sederhana, tidak aman secara kriptografis, tetapi cepat. n = 44 k = 20n+kn=44k=20
András Salamon
@ AndrásSalamon: Benar, meskipun fungsi hash kriptografi yang aman sebenarnya memberikan jaminan yang sedikit lebih kuat: yaitu, bahwa tidak praktis untuk menemukan input yang bertabrakan bahkan jika Anda mencoba untuk sengaja mencarinya. Dengan cukup besar (mis. seperti yang saya sarankan di atas), ini berarti bahwa menyimpan data lengkap tidak diperlukan bahkan jika biaya false positive tinggi dan bahkan jika mungkin ada musuh aktif yang berusaha untuk menemukannya. Tentu saja, jika Anda tidak membutuhkan jaminan yang begitu kuat, risiko tabrakan yang agak lebih tinggi dapat diterima. n = 128nn=128
Ilmari Karonen
1
@Newtopian Alasan saya menentukan fungsi hash kriptografi adalah bahwa bagi mereka, tidak ada cara yang diketahui untuk menghasilkan tabrakan lebih efektif daripada dengan brute force (yaitu dengan menguji banyak input dan memilih yang bertabrakan), atau hash akan dipertimbangkan rusak (seperti, katakanlah, MD5 saat ini adalah). Jadi, untuk hash kriptografis, kita dapat dengan aman mengasumsikan bahwa laju tumbukan adalah sama dengan untuk fungsi hash acak yang ideal. Menggunakan fungsi hash universal atau MAC yang dikunci (dengan kunci rahasia acak) akan membuat jaminan ini lebih kuat.
Ilmari Karonen
8

Tidak, tidak mungkin untuk memiliki struktur data yang efisien dengan properti ini, jika Anda ingin memiliki jaminan bahwa struktur data akan mengatakan "baru" jika itu benar-benar baru (itu tidak akan pernah, pernah akan mengatakan "tidak baru" jika ini sebenarnya baru; tidak boleh ada negatif palsu). Setiap struktur data semacam itu harus menyimpan semua data agar selalu merespons "bukan baru". Lihat jawaban pents90 pada cerita untuk pembenaran yang tepat.

Sebaliknya, filter Bloom bisa mendapatkan jaminan bahwa struktur data akan mengatakan "bukan baru" jika bukan baru, dengan cara yang efisien. Secara khusus, filter Bloom dapat lebih efisien daripada menyimpan semua data: setiap item individual mungkin cukup panjang, tetapi ukuran filter Bloom berskala dengan jumlah item, bukan total panjangnya. Setiap struktur data untuk masalah Anda harus berskala dengan panjang total data, bukan jumlah item data.

jbapple
sumber
Lihat juga jawaban yang diterima, karena pertanyaannya sama
Joe
-1 Anda mungkin harus memenuhi syarat apa yang Anda maksud ketika Anda mengatakan itu tidak mungkin. Jelas itu mungkin untuk melakukannya secara efisien, dan itu juga mungkin untuk melakukannya dengan tingkat kesalahan yang rendah, jadi mencapai keseimbangan dalam implementasi yang diberikan harus layak ... khususnya, akan berguna untuk menjelaskan dengan tepat apa yang dimaksud dengan "semua data pernah", karena ini tidak sepenuhnya diperlukan untuk memenuhi pertanyaan yang diajukan. Negatif palsu - merespons "baru" ketika jawabannya "tidak baru" - diizinkan di sini, jadi tidak semua data perlu disimpan.
Patrick87
1
Jawaban ini sangat masuk akal, dan sepertinya ditujukan pada surat pertanyaan saya, tetapi mungkin bukan semangat.
András Salamon
@DW Terima kasih telah meluangkan waktu untuk memperbarui jawabannya. Saya cenderung meninggalkan ini sebagai jawaban sekarang, meskipun saya masih keberatan dengan bahasa yang digunakan ketika menggambarkan ketidakefisienan filter anti-mekar, selain berpikir akan lebih baik untuk menguraikan sedikit lebih banyak pada "detail" yang dirujuk. ..meninggalkan -1 untuk saat ini. Membersihkan beberapa komentar usang.
Patrick87
@ DW Dengan "false negative", saya bermaksud menjawab "baru" ketika jawabannya seharusnya "tidak baru". (Agak berlawanan dengan intuisi, "bukan baru" adalah kasus positif di sini.) Anda tidak perlu menyimpan "semua data yang pernah ada" untuk melakukan ini, meskipun saya cenderung percaya Anda perlu menyimpan seluruh elemen (hanya tidak semua elemen - kecuali Anda mau menerima peluang kesalahan yang bermakna secara hipotetis, seperti jawaban lain untuk pertanyaan di sini.)
Patrick87
6

Bagaimana dengan tabel hash saja? Ketika Anda melihat item baru, periksa tabel hash. Jika tempat item kosong, kembalikan "baru" dan tambahkan item. Jika tidak, periksa untuk melihat apakah tempat barang tersebut ditempati oleh barang tersebut. Jika demikian, kembalikan "bukan baru". Jika spot ditempati oleh item lain, kembalikan "baru" dan timpa spot dengan item baru.

Anda pasti akan selalu mendapatkan "Baru" dengan benar jika Anda belum pernah melihat hash item sebelumnya. Anda pasti akan selalu mendapatkan "Bukan Baru" dengan benar jika Anda hanya melihat hash item ketika Anda melihat item yang sama. Satu-satunya waktu Anda akan mendapatkan "Baru" ketika jawaban yang benar adalah "Bukan Baru" adalah jika Anda melihat item A, lalu melihat item B, lalu melihat item A lagi, dan kedua hash A dan B untuk hal yang sama. Yang penting, Anda tidak akan pernah mendapatkan "Bukan Baru" secara salah.

Patrick87
sumber
1
Saya kira ini semacam mengabaikan masalah efisiensi ruang, atau lebih tepatnya, secara signifikan kurang efisien daripada filter mekar akan, karena filter mekar benar-benar hanya membutuhkan sedikit per ember, dan ini membutuhkan ruang sebanyak per ember karena dibutuhkan ruang untuk mewakili item. Oh well ... kecuali alam semesta terbatas (seperti dalam jawaban Wandering Logic), saya pikir Anda mungkin tidak bisa mendekati efisiensi ruang filter bloom.
Patrick87
Secara pribadi, saya pikir jawaban Anda jauh lebih baik daripada jawaban saya. Filter mekar bukan hanya sedikit per ember jika Anda ingin probabilitas lebih baik dari 50%. Ini juga merupakan ukuran tetap dan sekali Anda mengisinya lebih dari setengah penuh, kemungkinan positif palsu meningkat dengan cepat. Tidak ada cara mudah untuk mengembangkannya, tidak ada cara mudah untuk menggunakannya sebagai cache dan tidak ada cara mudah untuk menghapus elemen. Saya akan mengambil tabel hash setiap kali.
Logika Pengembaraan
@WanderingLogic Menggunakan penghitung jenuh kecil alih-alih bit tunggal memungkinkan penghapusan didukung (dengan biaya kapasitas dan hanya jika penghitung tidak maksimal, jelas).
Paul A. Clayton
4

Dalam kasus di mana alam semesta item terbatas, maka ya: cukup gunakan filter mekar yang merekam elemen mana yang di luar set, bukan di set. (Yaitu, gunakan filter bloom yang mewakili komplemen dari set bunga.)

Tempat di mana ini berguna adalah untuk memungkinkan penghapusan bentuk terbatas. Anda menyimpan dua filter mekar. Mereka mulai kosong. Saat Anda memasukkan elemen, Anda memasukkannya ke filter bloom A. Jika nanti Anda ingin menghapus elemen, Anda memasukkan elemen ke filter bloom B. Tidak ada cara untuk membatalkan penghapusan. Untuk melakukan pencarian Anda pertama kali mencari di filter bloom A. Jika Anda tidak menemukan yang cocok, item tersebut tidak pernah dimasukkan (dengan probabilitas 1). Jika Anda menemukan kecocokan, elemen mungkin (atau mungkin tidak) telah dimasukkan. Dalam hal ini Anda melakukan pencarian di filter mekar B. Jika Anda tidak menemukan kecocokan, item itu tidak pernah dihapus. Jika Anda menemukan kecocokan dalam filter mekar B, item itu mungkin dimasukkan dan kemudian dihapus.

Ini tidak benar-benar menjawab pertanyaan Anda, tetapi, dalam kasus terbatas ini, filter bloom B melakukan persis perilaku "filter anti-bloom" yang Anda cari.

Peneliti filter Bloom Nyata menggunakan cara yang jauh lebih efisien untuk mewakili penghapusan, lihat halaman publikasi Mike Mitzenmacher .

Logika Pengembaraan
sumber
Dalam pertanyaan ini, kami sedang memproses item, dan tidak ada penghapusan. Tidak ada cara yang berarti untuk menyimpan pujian tanpa harus menghapus item dari filter bloom
Joe
1
@ Jo: Saya setuju bahwa masalahnya tidak dapat dipecahkan secara umum, jadi batasi jawaban saya untuk kasus di mana komplemen terbatas dan kecil.
Logika Pengembaraan
1

Saya hanya ingin menambahkan di sini, bahwa jika Anda berada dalam situasi beruntung, bahwa Anda tahu semua nilai-nilai yang mungkin Anda mungkin melihat; maka Anda dapat menggunakan penghitungan filter bloom.vi

Contohnya mungkin alamat ip, dan Anda ingin tahu setiap kali ada yang muncul yang belum pernah Anda lihat sebelumnya. Tetapi ini masih merupakan perangkat yang terbatas, sehingga Anda tahu apa yang dapat Anda harapkan.

Solusi sebenarnya sederhana:

  1. Tambahkan semua item Anda ke filter bloom penghitungan.
  2. Saat Anda melihat item baru, item itu akan memiliki nilai di semua slot.1
  3. Setelah melihat item baru yang sebenarnya, kurangi dari filter.

Jadi, Anda mungkin memiliki nilai 'false positive' yang sebenarnya sudah lama, tetapi diakui sebagai baru. Namun Anda tidak akan pernah mendapatkan 'bukan baru' untuk nilai baru, karena nilainya masih di semua slot, dan tidak ada orang lain yang bisa mengambilnya.

Thomas Ahle
sumber