Có bộ lọc chống Bloom không?


25

Một Bloom lọc làm cho nó có thể để giữ một cách hiệu quả theo dõi cho dù giá trị khác nhau đã được gặp trong chế biến. Khi có nhiều mục dữ liệu thì bộ lọc Bloom có ​​thể giúp tiết kiệm bộ nhớ đáng kể qua bảng băm. Tính năng chính của bộ lọc Bloom, được chia sẻ với bảng băm, là nó luôn luôn nói "không mới" nếu một mục không mới, nhưng có một xác suất khác không là một mục sẽ được gắn cờ là "không mới "Ngay cả khi nó còn mới.

Có "bộ lọc chống Bloom", có hành vi ngược lại không?

Nói cách khác: có một cấu trúc dữ liệu hiệu quả nói "mới" nếu một mục là mới, nhưng cũng có thể nói "mới" cho một số mục không phải là mới?

Giữ tất cả các mục đã thấy trước đó (ví dụ, trong danh sách được liên kết được sắp xếp) đáp ứng yêu cầu đầu tiên nhưng có thể sử dụng nhiều bộ nhớ. Tôi hy vọng nó cũng không cần thiết, đưa ra yêu cầu thứ hai thoải mái.


Đối với những người thích điều trị chính thức hơn, hãy viết b(x)=1 nếu bộ lọc Bloom nghĩ x là mới, b(x)=0 nếu không và viết n(x)=1 nếu x thực sự mới và n(x)=0 nếu không.

Khi đó ; P r [ b ( x ) = 0 | n ( x ) = 1 ] = α ; P r [ b ( x ) = 1 | n ( x ) = 0 ] = 0Pr[b(x)=0|n(x)=0]=1Pr[b(x)=0|n(x)=1]=αPr[b(x)=1|n(x)=0]=0; , với một số 0 < α < 1 .Pr[b(x)=1|n(x)=1]=1α0<α<1

Tôi đang hỏi: có tồn tại cấu trúc dữ liệu hiệu quả không, thực hiện hàm với một số 0 < β < 1 , sao cho P r [ b ( x ) = 0 | n ( x ) = 0 ] = β ; P r [ b ( x ) = 0 | n ( x ) = 1 ] = 0 ; P rb0<β<1Pr[b(x)=0|n(x)=0]=βPr[b(x)=0|n(x)=1]=0 ; P r [ b ( x ) = 1 | n ( x ) = 1 ] = 1 ?Pr[b(x)=1|n(x)=0]=1βPr[b(x)=1|n(x)=1]=1


Chỉnh sửa: Có vẻ như câu hỏi này đã được hỏi trước đây trên StackExchange, vì /programming/635728/cstheory/6596 với một loạt các câu trả lời từ "không thể thực hiện "thông qua" có thể được thực hiện, với một số chi phí "thành" việc đó là không quan trọng, bằng cách đảo ngược các giá trị của ". Vẫn chưa rõ câu trả lời "đúng" là gì. Có gì rõ ràng là một chương trình LRU bộ nhớ đệm của một số loại (ví dụ như một đề nghị của Ilmari Karonen) hoạt động khá tốt, rất dễ dàng để thực hiện, và kết quả là giảm 50% trong thời gian thực hiện để chạy mã của tôi.b


Vì một số lý do, tôi muốn nói rằng điều này rất giống với vấn đề mà bộ nhớ cache và thuật toán vị trí bộ đệm cố gắng giải quyết. Xem xét bộ đệm bằng cách sử dụng thay thế ít được sử dụng nhất (LFU). Một thuật toán thay thế tối ưu về mặt lý thuyết nhưng không thể thay thế sẽ là loại bỏ thuật toán mà bạn sẽ không gặp lại trong thời gian dài nhất, giống như đối với bộ nhớ cache. Tôi cho rằng bộ nhớ đệm dựa trên một số giả định về bản chất của phân phối có thể không giữ được nói chung, nhưng đáng để xem xét liệu điều này có áp dụng hay không.
Patrick87

Bạn có thể quan tâm đến cuộc nói chuyện sau: Bộ lọc thành viên dựa trên sự hài lòng
Kaveh

@Kaveh: cảm ơn con trỏ, sẽ xem.
András Salamon

Câu trả lời:


12

Theo ý tưởng băm của Patrick87, đây là một công trình thực tế gần như đáp ứng yêu cầu của bạn - xác suất nhầm lẫn một giá trị mới cho một giá trị cũ không hoàn toàn bằng không, nhưng có thể dễ dàng thực hiện nhỏ.

Chọn tham số k ; giá trị thực tế có thể là, n = 128k = 16 . Đặt Hhàm băm mật mã an toàn tạo ra (ít nhất) n + k bit đầu ra.nkn=128k=16Hn+k

Hãy để là một mảng của 2 k n -bit bitstrings. Mảng này lưu trữ trạng thái của bộ lọc, sử dụng tổng cộng n 2 k bit. (Nó không đặc biệt quan trọng như thế nào mảng này được khởi tạo; chúng ta chỉ có thể lấp đầy nó bằng các số không hoặc bằng các bit ngẫu nhiên.)a2k nn2k

  • Để thêm giá trị mới vào bộ lọc, hãy tính ix , trong đó i biểu thị k bitđầu tiênvà j biểu thị n bit sau của H ( x ) . Đặt a i = j .ij=H(x)ikjnH(x)ai=j

  • Để kiểm tra xem một giá trị đã được thêm vào bộ lọc, tính toán i 'x , như trên, và kiểm tra xem một i ' = j ' . Nếu có, trả lại đúng sự thật; Nếu không thì trả lại sai.ij=H(x)ai=j

Yêu cầu 1: Xác suất của một dương tính giả (= giá trị mới sai tuyên bố đã được nhìn thấy) được . Điều này có thể được thực hiện nhỏ tùy ý, với chi phí khiêm tốn trong không gian lưu trữ, bằng cách tăng n ; đặc biệt, với n 128 , xác suất này về cơ bản là không đáng kể, trong thực tế, nhỏ hơn nhiều so với xác suất dương tính giả do trục trặc phần cứng.1/2n+knn128

Đặc biệt, sau khi giá trị riêng biệt đã được kiểm tra và thêm vào bộ lọc, xác suất có ít nhất một dương tính giả đã xảy ra là ( N 2 - N ) / 2 n + k + 1 . Ví dụ: với n = 128k = 16 , số lượng giá trị riêng biệt cần thiết để có giá trị dương với xác suất 50% là khoảng 2 ( n + k ) / 2 = 2 72 .N(N2N)/2n+k+1n=128k=162(n+k)/2=272

Yêu cầu 2: Xác suất của âm tính giả (= giá trị được thêm trước đó được tuyên bố là mới) không lớn hơn , trong đó N là số lượng giá trị riêng biệt được thêm vào bộ lọc (hoặc cụ thể hơn là số lượng giá trị riêng biệt được thêm sau khi giá trị cụ thể được kiểm tra gần đây nhất được thêm vào bộ lọc).1(12k)N1exp(N/2k)<N/2kN


Thi thiên Để đặt "nhỏ không đáng kể" vào viễn cảnh, mã hóa 128 bit thường được coi là không thể phá vỡ với công nghệ hiện được biết đến. Nhận được dương tính giả từ sơ đồ này với có khả năng giống như ai đó đoán chính xác khóa mã hóa 128 bit bí mật của bạn trong lần thử đầu tiên . (Với n = 128k = 16 , thực tế ít hơn khoảng 65.000 lần so với điều đó.)n+k=128n=128k=16

Nhưng nếu điều đó vẫn khiến bạn cảm thấy lo lắng phi lý, bạn luôn có thể chuyển sang ; nó sẽ tăng gấp đôi yêu cầu lưu trữ của bạn, nhưng tôi có thể yên tâm đặt cược cho bạn bất kỳ khoản tiền bạn muốn quan tâm đến tên mà không ai sẽ bao giờ thấy một dương tính giả với n = 256 - giả định rằng hàm băm không bị hỏng, dù sao.n=256n=256


1
Không chỉ có thể xác suất có thể so sánh với sự cố phần cứng; nó cũng có thể được so sánh với xác suất ai đó đoán khóa RSA của bạn để đăng nhập SSH trong lần thử đầu tiên . IMO cái sau truyền tải tính thực tiễn của giải pháp của bạn hơn cái trước.
R ..

+1 Rất hay - tôi hiểu là điều này giải quyết vấn đề hiệu quả không gian bằng cách cho phép một số (rất nhỏ) cơ hội trả lời không chính xác "không mới" khi thực tế, vật phẩm mới. Rất thực tế, và phân tích tốt.
Patrick87

1
Yêu cầu 1 chỉ nói rằng hàm băm đàng hoàng có xác suất va chạm thấp. Điều này đúng trong thực tế nếu ít nhất là 50 hoặc hơn. Đối với ứng dụng của tôi, n = 44k = 20 hoạt động tuyệt vời với hàm băm 64 bit đơn giản, không bảo mật, nhưng nhanh chóng. n+kn=44k=20
András Salamon

@ AndrásSalamon: Đúng, mặc dù chức năng băm mật mã an toàn thực sự cung cấp một bảo đảm mạnh hơn một chút: cụ thể là việc tìm đầu vào va chạm ngay cả khi bạn cố tình tìm kiếm chúng. Với đủ lớn (ví dụ n = 128 như tôi đã đề xuất ở trên), điều này có nghĩa là việc lưu trữ toàn bộ dữ liệu là không cần thiết ngay cả khi chi phí của dương tính giả là cao và ngay cả khi có thể có một đối thủ tích cực cố gắng tìm kiếm. Tất nhiên, nếu bạn không cần một sự đảm bảo khá mạnh mẽ, rủi ro va chạm cao hơn một chút có thể được chấp nhận. nn=128
Ilmari Karonen

1
@Newtopian Lý do tôi chỉ định hàm băm mật mã là vì đối với những điều đó, không có cách nào tạo ra xung đột hiệu quả hơn bằng vũ lực (tức là bằng cách kiểm tra nhiều đầu vào và chọn những đầu vào đó), nếu không thì băm sẽ được xem xét bị hỏng (như, nói, MD5 ngày nay là). Do đó, đối với hàm băm mật mã, chúng ta hoàn toàn có thể giả định rằng tỷ lệ va chạm giống như đối với hàm băm ngẫu nhiên lý tưởng. Sử dụng hàm băm phổ quát hoặc MAC có khóa (với khóa bí mật ngẫu nhiên) sẽ giúp bảo đảm này mạnh hơn nữa.
Ilmari Karonen

8

Không, không thể có cấu trúc dữ liệu hiệu quả với các thuộc tính này, nếu bạn muốn đảm bảo rằng cấu trúc dữ liệu sẽ nói "mới" nếu nó thực sự mới (sẽ không bao giờ nói "không mới" nếu thực tế nó là mới, không cho phép phủ định sai). Bất kỳ cấu trúc dữ liệu nào như vậy sẽ cần phải giữ tất cả dữ liệu để phản hồi "không mới". Xem câu trả lời của pents90 trên cstheory để có lý do chính xác.

Ngược lại, các bộ lọc Bloom có thể đảm bảo rằng cấu trúc dữ liệu sẽ nói "không mới" nếu nó không mới, theo cách hiệu quả. Cụ thể, bộ lọc Bloom có ​​thể hiệu quả hơn so với việc lưu trữ tất cả dữ liệu: mỗi mục riêng lẻ có thể khá dài, nhưng kích thước của bộ lọc Bloom có ​​tỷ lệ với số lượng mục, không phải tổng chiều dài của chúng. Bất kỳ cấu trúc dữ liệu nào cho vấn đề của bạn sẽ phải mở rộng theo tổng chiều dài của dữ liệu, không phải số lượng mục dữ liệu.


Cũng xem câu trả lời được chấp nhận, vì câu hỏi này giống nhau
Joe

-1 Có lẽ bạn nên đủ điều kiện những gì bạn muốn nói khi bạn nói điều đó là không thể. Rõ ràng là có thể thực hiện một cách hiệu quả và cũng có thể thực hiện với tỷ lệ lỗi thấp, do đó, việc cân bằng trong một triển khai nhất định là khả thi ... đặc biệt, sẽ rất hữu ích khi giải thích chính xác ý nghĩa của nó là gì "Tất cả dữ liệu đã từng", vì điều này không thực sự cần thiết để đáp ứng câu hỏi. Phủ định sai - trả lời "mới" khi câu trả lời là "không mới" - được cho phép ở đây, vì vậy không phải tất cả dữ liệu cần được lưu giữ.
Patrick87

1
Câu trả lời này là hoàn toàn hợp lý, và dường như để giải quyết bức thư của câu hỏi của tôi, nhưng có lẽ không phải là tinh thần.
András Salamon

@DW Cảm ơn bạn đã dành thời gian cập nhật câu trả lời. Bây giờ tôi có xu hướng để lại câu trả lời này, mặc dù tôi vẫn phản đối ngôn ngữ được sử dụng khi mô tả sự không hiệu quả của các bộ lọc chống nở hoa, ngoài việc nghĩ rằng tốt nhất nên xây dựng thêm một chút về "chi tiết" được tham chiếu. .. để lại -1 cho bây giờ. Làm sạch một số ý kiến ​​lỗi thời.
Patrick87

@DW Bởi "âm tính giả", tôi dự định trả lời "mới" khi câu trả lời phải là "không mới". (Hơi trái ngược, "không mới" là trường hợp tích cực ở đây.) Bạn không cần phải lưu "tất cả dữ liệu" để loại bỏ điều này, mặc dù tôi có xu hướng tin rằng bạn cần phải lưu toàn bộ các yếu tố (chỉ không phải tất cả các yếu tố - trừ khi bạn sẵn sàng chấp nhận một cơ hội lỗi có ý nghĩa giả định, theo câu trả lời khác cho câu hỏi ở đây.)
Patrick87

6

Điều gì về chỉ một bảng băm? Khi bạn thấy một mục mới, hãy kiểm tra bảng băm. Nếu vị trí của mục trống, trả về "mới" và thêm mục đó. Mặt khác, kiểm tra xem vị trí của vật phẩm có bị chiếm bởi vật phẩm đó không. Nếu vậy, trả lại "không mới". Nếu vị trí bị chiếm bởi một số mặt hàng khác, hãy trả lại "mới" và ghi đè lên vị trí đó với mục mới.

Bạn chắc chắn sẽ luôn luôn nhận được "Mới" nếu bạn chưa bao giờ thấy hàm băm của mặt hàng trước đó. Bạn chắc chắn sẽ luôn luôn nhận được "Không mới" nếu bạn chỉ nhìn thấy hàm băm của mặt hàng khi bạn nhìn thấy cùng một mặt hàng. Lần duy nhất bạn sẽ nhận được "Mới" khi câu trả lời đúng là "Không mới" là nếu bạn thấy mục A, sau đó xem mục B, sau đó xem lại mục A và cả A và B băm vào cùng một điều. Điều quan trọng, bạn không bao giờ có thể nhận được "Không mới" không chính xác.


1
Tôi cho rằng loại bỏ qua vấn đề hiệu quả không gian này, hay nói đúng hơn là kém hiệu quả hơn so với bộ lọc nở, vì bộ lọc nở thực sự chỉ cần một bit trên mỗi thùng và điều này cần nhiều không gian cho mỗi thùng vì nó cần không gian đại diện cho các mặt hàng. Ôi chà ... trừ khi vũ trụ là hữu hạn (như trong câu trả lời của Wandering Logic) Tôi nghĩ có lẽ bạn không thể tiến gần đến hiệu quả không gian của bộ lọc nở hoa.
Patrick87

Cá nhân, tôi nghĩ rằng câu trả lời của bạn là cách tốt hơn của tôi. Bộ lọc nở không chỉ là một bit trên mỗi nhóm nếu bạn muốn xác suất tốt hơn 50%. Nó cũng là một kích thước cố định và một khi bạn lấp đầy nó hơn một nửa thì xác suất dương tính giả sẽ tăng nhanh chóng. Không có cách thuận tiện để mở rộng nó, không có cách thuận tiện để sử dụng nó làm bộ đệm và không có cách thuận tiện để xóa các yếu tố. Tôi sẽ lấy một bảng băm mỗi lần.
Logic lang thang

@WanderingLogic Sử dụng bộ đếm bão hòa nhỏ thay vì bit đơn cho phép xóa được hỗ trợ (với chi phí dung lượng và chỉ khi bộ đếm không ở mức tối đa, rõ ràng).
Paul A. Clayton

4

Trong trường hợp vũ trụ của các vật phẩm là hữu hạn, thì có: chỉ cần sử dụng bộ lọc nở ghi lại các phần tử nằm ngoài tập hợp, thay vì trong tập hợp. (Tức là sử dụng bộ lọc nở đại diện cho phần bổ sung của bộ lợi ích.)

Một nơi mà điều này hữu ích là cho phép một hình thức xóa hạn chế. Bạn giữ hai bộ lọc nở. Họ bắt đầu trống rỗng. Khi bạn chèn các phần tử, bạn chèn chúng vào bộ lọc nở A. Nếu sau này bạn muốn xóa một phần tử, bạn chèn phần tử đó vào bộ lọc nở B. Không có cách nào để phục hồi. Để thực hiện tra cứu, trước tiên bạn tra cứu trong bộ lọc nở A. Nếu bạn không tìm thấy kết quả trùng khớp, mục này không bao giờ được chèn (với xác suất 1). Nếu bạn tìm thấy một kết quả khớp, phần tử có thể (hoặc có thể không) đã được chèn. Trong trường hợp đó, bạn thực hiện tra cứu trong bộ lọc nở B. Nếu bạn không tìm thấy kết quả trùng khớp, mục này sẽ không bao giờ bị xóa. Nếu bạn tìm thấy kết quả khớp trong bộ lọc nở B, mục có thể đã được chèn và sau đó bị xóa.

Điều này không thực sự trả lời câu hỏi của bạn, nhưng, trong trường hợp giới hạn này, bộ lọc nở B đang thực hiện chính xác hành vi "bộ lọc chống nở hoa" mà bạn đang tìm kiếm.

Các nhà nghiên cứu bộ lọc Real Bloom sử dụng các cách hiệu quả hơn để thể hiện việc xóa, xem trang xuất bản của Mike Mitzenmacher .


Trong câu hỏi này, chúng tôi đang xử lý các mục và không có xóa. Không có cách nào có ý nghĩa để lưu trữ lời khen mà không phải xóa các mục khỏi bộ lọc nở
Joe

1
@Joe: Tôi đồng ý rằng vấn đề nói chung là không hòa tan, vì vậy hạn chế câu trả lời của tôi cho trường hợp phần bù là hữu hạn và nhỏ.
Logic lang thang

1

vtôi

Một ví dụ có thể là địa chỉ IP và bạn muốn biết mỗi lần xuất hiện mà bạn chưa từng thấy trước đây. Nhưng nó vẫn là một tập hợp hữu hạn, vì vậy bạn biết những gì bạn có thể mong đợi.

Giải pháp thực tế rất đơn giản:

  1. Thêm tất cả các mục của bạn vào bộ lọc nở.
  2. 1
  3. Sau khi thấy một mục mới thực sự, hãy trừ nó khỏi bộ lọc.

Vì vậy, bạn có thể có các giá trị 'dương tính giả' thực sự cũ, nhưng được công nhận là mới. Tuy nhiên, bạn sẽ không bao giờ nhận được 'không mới' cho một giá trị mới, vì giá trị của nó sẽ vẫn nằm trong tất cả các vị trí và không ai khác có thể lấy đi điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.