Чи є фільтр проти цвітіння?


25

Bloom фільтр дозволяє ефективно відслідковувати чи вже зустрічалися різні значення в процесі обробки. Коли є багато елементів даних, тоді фільтр Bloom може призвести до значного збереження пам'яті в хеш-таблиці. Головною особливістю фільтра Bloom, який він ділиться з хеш-таблицею, є те, що він завжди говорить "не новий", якщо елемент не новий, але існує ненульова ймовірність того, що елемент буде позначено як "не новий "навіть коли це нове.

Чи є "фільтр" проти цвітіння ", який має протилежну поведінку?

Іншими словами: чи існує ефективна структура даних, яка говорить "нове", якщо елемент є новою, але яка може також сказати "нова" для деяких елементів, які не є новими?

Якщо зберігати всі раніше переглянуті предмети (наприклад, у відсортованому зв'язаному списку), задовольняє першу вимогу, але може використовуватися багато пам'яті. Я сподіваюся, що це також непотрібно, враховуючи невимушену другу вимогу.


Для тих, хто вважає за краще формальне лікування, напишіть b(x)=1 якщо фільтр Bloom вважає, що є новим, іншому випадку, і напишіть якщо дійсно є новим і інакше.b ( x ) = 0 n ( x ) = 1 x n ( x ) = 0xb(x)=0n(x)=1xn(x)=0

Тоді ; ; ; , для деяких .P r [ b ( x ) = 0 | n ( x ) = 1 ] = α P r [ b ( x ) = 1 | n ( x ) = 0 ] = 0 P r [ bPr[b(x)=0|n(x)=0]=1Pr[b(x)=0|n(x)=1]=αPr[b(x)=1|n(x)=0]=00 < α < 1Pr[b(x)=1|n(x)=1]=1α0<α<1

Я запитую: чи існує ефективна структура даних, реалізуючи функцію з деяким , таким, що ; ; ; ? 0 < β < 1 P r [ b ( x ) = 0 | n ( x ) = 0 ] = β P r [ b ( x ) = 0 | n ( x ) = 1 ] = 0 P r [ b ( x ) = 1 | n ( xb0<β<1Pr[b(x)=0|n(x)=0]=βPr[b(x)=0|n(x)=1]=0Pr[b(x)=1|n(x)=0]=1βPr[b(x)=1|n(x)=1]=1


Редагувати: Схоже, це питання було задано раніше на StackExchange, як /programming/635728 та /cstheory/6596 з діапазоном відповідей від "не може бути "через" можна зробити, за деяку ціну "до" це тривіально зробити, перевернувши значення ". Мені поки не ясно, що таке "правильна" відповідь. Що це ясно, що схема кешування LRU деякого виду (наприклад, один запропонований Ілмарі Karonen) працює досить добре, легко реалізувати, і призвело до скорочення часу , необхідного для запуску мого коду на 50%.b


Я чомусь спокусився сказати, що це дуже схоже на проблему, яку намагаються вирішити алгоритми кешування та кешування. Розглянемо кеш-пам'ять, використовуючи заміну, що використовується найменш часто (LFU). Теоретично оптимальним, але неможливим алгоритмом заміни було б вилучення того, якого ви більше не побачите довше, як і кеші. Я припускаю, що кешування спирається на деякі припущення щодо природи розподілу, які, як правило, не мають права, але варто подумати, чи це стосується.
Patrick87

Можливо, вас зацікавлять наступні бесіди: Фільтри членства на основі задоволеності
Kaveh,

@Kaveh: спасибі за вказівник, буде дивитись.
Андраш Саламон

Відповіді:


12

Виходячи з хеш-ідеї Patrick87, ось практична конструкція, яка майже відповідає вашим вимогам - ймовірність помилкового помилки нового значення для старого не зовсім нульова, але її можна легко зробити незначно малою.

Виберіть параметри і k ; практичні значення можуть бути, скажімо, n = 128 і k = 16 . Нехай H - захищена криптографічна хеш-функція, що виробляє (принаймні) n + k біт виводу.nkn=128k=16Hn+k

Нехай - масив 2 k n- бітових рядків. Цей масив зберігає стан фільтра, використовуючи загально n 2 k біт. (Не має особливого значення, як ініціалізується цей масив; ми можемо просто заповнити його нулями або випадковими бітами.)a2k nn2k

  • Щоб додати нове значення до фільтра, обчисліть ix , де i позначає перші k біти, а j позначає наступні n біт H ( x ) . Нехай a i = j .ij=H(x)ikjnH(x)ai=j

  • Щоб перевірити, чи додано у фільтр значення , обчисліть i 'x , як зазначено вище, і перевірте, чи a i = j . Якщо так, поверніть істину; інакше повернути помилкове.ij=H(x)ai=j

Пункт 1: Імовірність помилкових позитивних (= нове значення помилково стверджував, що було видно) є . Це можна зробити довільно невеликим, за помірних витрат у сховищі, збільшивши n ; Зокрема, для n 128 ця ймовірність, по суті, незначна, на практиці набагато менша, ніж ймовірність помилкового позитиву через апаратну несправність.1/2n+knn128

Зокрема, після того, як різних значень було перевірено та додано до фільтра, ймовірність виникнення принаймні одного помилкового додатника становить ( N 2 - N ) / 2 n + k + 1 . Наприклад, при n = 128 і k = 16 кількість чітких значень, необхідних для отримання помилкового додатного з 50% вірогідністю, становить приблизно 2 ( n + k ) / 2 = 2 72 .N(N2N)/2n+k+1n=128k=162(n+k)/2=272

Спосіб 2: Імовірність помилкового негативного (= раніше додана величина, помилково заявлена ​​як нова), не перевищує , де N - кількість відокремлених значень, доданих до фільтра (або, точніше, кількість розрізнених значень, доданих після того, як конкретне значення, яке тестується, було останнім часом додане до фільтра).1(12k)N1exp(N/2k)<N/2kN


Пс. Для того, щоб поставити "незначно мале" в перспективу, 128-бітове шифрування, як правило, вважається непорушним із відомою в даний час технологією. Отримати помилковий позитив із цієї схеми з само ймовірно, як хтось правильно вгадав ваш секретний 128-розрядний ключ шифрування при першій спробі . (З n = 128 і k = 16 , це насправді приблизно в 65 000 разів менше, ніж це.)n+k=128n=128k=16

Але якщо це все-таки залишає вас відчувати ірраціональну нервозність, ви завжди можете перейти до ; це подвоїть ваші вимоги щодо зберігання, але я з упевненістю можу обмінути вам будь-яку суму, яку б ви хотіли назвати, що ніхто ніколи не побачить помилковий позитив з n = 256 - якщо припустити, що хеш-функція все одно не порушена.n=256n=256


1
Мало того, що ймовірність можна порівняти з можливістю несправності обладнання; це також можна порівняти з ймовірністю того, що хтось здогадається ваш ключ RSA для входу в SSH при першій спробі . IMO останній передає практичність вашого рішення більше, ніж перше.
R ..

+1 Дуже приємно - я розумію, що це вирішує проблему ефективності простору, надаючи певний (дуже маленький) шанс невірно відповісти "не новий", коли предмет є насправді новим. Дуже практичний і хороший аналіз.
Patrick87

1
У пункті 1 йдеться лише про те, що гідна хеш-функція має низьку ймовірність зіткнень. Це справедливо на практиці вже тоді, коли становить щонайменше 50 або близько того. У моєму застосуванні n = 44 і k = 20 чудово працює з простою 64-бітовою, не криптографічно захищеною, але швидкою хеш-функцією. n+kn=44k=20
Андрас Саламон

@ AndrásSalamon: Правда, хоча безпечна криптографічна хеш-функція насправді дає дещо міцнішу гарантію: а саме, що непрактично знаходити вхідні дані, навіть якщо ви намагаєтесь навмисно їх шукати, недоцільно . Що стосується досить великого (наприклад, n = 128, як я запропонував вище), це означає, що зберігання повних даних є непотрібним, навіть якщо вартість помилкового додатника висока, і навіть якщо може бути активний противник, який намагається його знайти. Звичайно, якщо вам не потрібна настільки сильна гарантія, може бути прийнятний дещо більший ризик зіткнення. nn=128
Ільмарі Каронен

1
@Newtopian Причиною, що я вказав функцію криптографічного хешу, є те, що для них не існує відомого способу генерування зіткнень ефективніше, ніж за допомогою грубої сили (тобто шляхом тестування безлічі входів та вибору тих, що стикаються), інакше хеш вважатиметься зламаний (як, скажімо, MD5 нині є). Таким чином, для криптографічного хеша ми можемо з упевненістю припустити, що швидкість зіткнення така ж, як і для ідеальної випадкової хеш-функції. Використання універсальної хеш-функції або зафіксований MAC (з випадковим секретним ключем) зробить цю гарантію ще сильнішою.
Ільмарі Каронен

8

Ні, неможливо мати ефективну структуру даних з цими властивостями, якщо ви хочете мати гарантію, що структура даних скаже "нове", якщо вона справді нова (вона ніколи не скаже "не нова", якщо насправді це нове, не допускаються помилкові негативи). Будь-яка така структура даних повинна зберігати всі дані, щоб коли-небудь відповідати "не новими". Дивіться відповідь pents90 на cstheory для точного виправдання.

Навпаки, фільтри Bloom можуть отримати гарантію, що структура даних скаже «не нову», якщо вона не нова, ефективно. Зокрема, фільтри Bloom можуть бути ефективнішими, ніж зберігання всіх даних: кожен окремий елемент може бути досить довгим, але розмір фільтра Bloom масштабується з кількістю елементів, а не їх загальною довжиною. Будь-яка структура даних для вашої проблеми повинна масштабуватися із загальною довжиною даних, а не з кількістю даних.


Також дивіться прийняту відповідь, оскільки питання там те саме
Джо

-1 Ви, мабуть, повинні кваліфікувати, що ви маєте на увазі, коли ви говорите, що це неможливо. Зрозуміло, що це можливо зробити ефективно, і це також можна зробити з низькою швидкістю помилок, тому досягнення певного балансу в даній реалізації повинно бути здійсненним ... зокрема, було б корисно пояснити, що саме розуміється під "всі дані коли-небудь", оскільки це не обов'язково для задоволення запитання. Помилкові негативи - відповідь "новим", коли відповідь має бути "не новим" - тут дозволені, тому не всі дані потрібно зберігати.
Patrick87

1
Ця відповідь цілком розумна і, здається, стосується букви мого питання, але, можливо, не духу.
Андраш Саламон

@DW Дякуємо, що знайшли час для оновлення відповіді. Я схильний залишити це як відповідь зараз, хоча я все ще заперечую проти мови, яка використовується при описі неефективності фільтрів проти цвітіння, окрім того, що думаю, що було б краще детальніше розібратися про "деталі", про які йдеться. .. покинувши -1. Очистили деякі застарілі коментарі.
Patrick87

@DW За допомогою "помилкового негативного" я маю намір відповісти "новим", коли відповідь повинна була бути "не нова". (Дещо протирічно, "не нове" - це позитивний випадок.) Вам не потрібно зберігати "всі дані коли-небудь", щоб зняти це, хоча я схильний вважати, що вам потрібно зберегти цілі елементи (просто не всі елементи - якщо ви не готові прийняти гіпотетично значимий шанс помилки, відповідно до іншої відповіді на питання тут.)
Patrick87

6

А як щодо просто хеш-таблиці? Коли ви побачите новий елемент, перевірте хеш-таблицю. Якщо місце пункту порожнє, поверніть "нове" та додайте його. В іншому випадку перевірте, чи місце займає предмет. Якщо так, поверніть "не нове". Якщо місце займає якийсь інший предмет, поверніться «новий» і перепишіть місце новим елементом.

Ви обов'язково завжди отримаєте "Нове", якщо раніше ніколи не бачили хеш-позицію товару. Ви, безумовно, завжди отримаєте "Не новий", якщо ви бачили хеш товару лише тоді, коли бачили той самий предмет. Єдиний раз, коли ви отримаєте "Нове", якщо правильна відповідь - "Не нова", це якщо ви бачите пункт А, потім бачите пункт В, потім знову бачите пункт А, і обидва, і А, і Б, мають те ж саме. Що важливо, ви ніколи не можете отримати "Не новий" неправильно.


1
Я припускаю, що цей вид ігнорує проблему з просторовою ефективністю, а точніше, є значно менш ефективною, ніж фільтр цвітіння, оскільки фільтру цвітіння потрібно лише трохи на відро, і для цього потрібно стільки місця на відро, скільки потрібно місця для представляють предмети. Ну добре ... якщо тільки Всесвіт не є кінцевим (як у відповіді Wandering Logic), я думаю, ви, мабуть, не можете наблизитися до космічної ефективності фільтра цвітіння.
Patrick87

Особисто я вважаю, що ваша відповідь набагато краща за мою. Фільтр цвітіння - це не лише трохи на відро, якщо ви хочете, щоб вірогідність перевищувала 50%. Це також фіксований розмір, і як тільки ви заповните його більше, ніж наполовину, ймовірність помилкових позитивних результатів зростає швидко. Немає зручного способу розширити його, немає зручного способу використовувати його як кеш і немає зручного способу видалення елементів. Я буду приймати хеш-стіл кожного разу.
Мандрівна логіка

@WanderingLogic Використання невеликого насичуючого лічильника замість одного біта дозволяє підтримувати видалення (ціною ємності та лише у випадку, якщо лічильник не на максимумі, очевидно).
Пол А. Клейтон,

4

У випадку, коли Всесвіт предметів є кінцевим, тоді так: просто використовуйте фільтр розквітання, який записує, які елементи знаходяться поза набором, а не в наборі. (Тобто, використовуйте фільтр цвітіння, який представляє доповнення набору, що цікавить.)

Місце, де це корисно, - це допускати обмежену форму видалення. Ви тримаєте два фільтри цвітіння. Вони починаються порожніми. Коли ви вставляєте елементи, ви вставляєте їх у фільтр розквітання А. Якщо пізніше ви хочете видалити елемент, ви вставите цей елемент у фільтр розквітання B. Немає можливості його відновити. Щоб здійснити пошук, ви спочатку шукаєте фільтр цвітіння A. Якщо ви не знайдете відповідності, елемент ніколи не вставляли (з вірогідністю 1). Якщо ви знайдете відповідність, елемент може бути (а може й не бути) вставлений. У цьому випадку ви робите пошук у фільтрі розквітання B. Якщо ви не знайдете відповідності, елемент ніколи не був видалений. Якщо ви знайдете відповідність у фільтрі розквітання B, елемент, ймовірно, було вставлено та видалено.

Це насправді не дає відповіді на ваше запитання, але в цьому обмеженому випадку фільтр Бломіт Б виконує саме таку поведінку, яку ви шукаєте.

Дослідники фільтрів Real Bloom використовують набагато ефективніші способи подання видалення, дивіться на сторінці публікації Майка Міценмахера .


У цьому питанні ми обробляємо елементи, а видалень немає. Немає жодного змістовного способу зберігати комплімент, не виймаючи предмети з фільтра цвітіння
Джо

1
@Joe: Я погоджуюся з тим, що проблема взагалі нерозв'язна, тому обмежив мою відповідь випадком, коли доповнення було обмеженим і невеликим.
Блукаюча логіка

1

Я просто хочу додати тут, що якщо ви потрапили в удачу ситуацію, то ви знаєте всі цінності viщо ви, можливо, побачите; тоді ви можете використовувати фільтр підрахунку цвітіння.

Прикладом можуть бути ip-адреси, і ви хочете знати щоразу, коли з'являється, що ви ніколи не бачили. Але це все-таки скінченна множина, тож ви знаєте, чого можете очікувати.

Дійсне рішення просте:

  1. Додайте всі свої предмети до фільтру підрахунку цвітіння.
  2. Коли ви побачите новий елемент, він буде мати значення 1 у всіх слотах.
  3. Побачивши фактично новий елемент, відніміть його з фільтра.

Тож у вас можуть бути значення "помилкових позитивних результатів", які були фактично старими, але визнані новими. Однак ви ніколи не отримаєте «не нове» для нового значення, оскільки його значення все ще буде у всіх слотах, і ніхто інший не міг би це забрати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.