Bloom фильтр позволяет эффективно отслеживать ли уже встречались различные значения в процессе обработки. Когда имеется много элементов данных, тогда фильтр Блума может привести к значительной экономии памяти по хеш-таблице. Основная особенность фильтра Блума, который он разделяет с хеш-таблицей, заключается в том, что он всегда говорит «не новый», если элемент не новый, но существует ненулевая вероятность того, что элемент будет помечен как «не новый». «даже когда это новое.
Есть ли «анти-Блум фильтр», который имеет противоположное поведение?
Другими словами: существует ли эффективная структура данных, которая говорит «новый», если элемент новый, но который может также сказать «новый» для некоторых элементов, которые не являются новыми?
Сохранение всех ранее просмотренных элементов (например, в отсортированном связанном списке) удовлетворяет первому требованию, но может занимать много памяти. Я надеюсь, что это также не нужно, учитывая ослабленное второе требование.
Для тех, кто предпочитает более формальный подход, напишите если фильтр Блума считает, что является новым, противном случае, и напишите если действительно новый и противном случае.
Тогда ; ; ; , для некоторых .
Я спрашиваю: существует ли эффективная структура данных, реализующая функцию с некоторыми , такими, что ; ; ; ?P r [ b ′ ( x ) = 1 | n ( x ) = 1 ] = 1
Изменить: Кажется, этот вопрос уже задавался ранее в StackExchange, так как /programming/635728 и /cstheory/6596 с диапазоном ответов от «не может быть» Выполнение «через» может быть выполнено, за определенную плату «до« это тривиально, путем изменения значения ». Мне пока не ясно, каков «правильный» ответ. Что это ясно, что схема кэширования LRU некоторого вида (например, один предложенный Илмари Karonen) работает довольно хорошо, легко реализовать, и привело к сокращению времени , необходимого для запуска моего кода на 50%.
источник
Ответы:
Если исходить из хэш-идеи Patrick87, то вот практическая конструкция, которая почти соответствует вашим требованиям - вероятность ошибочного принятия нового значения за старое не совсем равна нулю, но его легко можно сделать пренебрежимо малым.
Выберите параметры и ; практические значения могут быть, скажем, и . Пусть будет безопасной криптографической хеш-функцией, создающей (как минимум) битов вывода.k n = 128 k = 16 H n + kn k n=128 k=16 H n+k
Пусть будет массивом из битных цепочек битов. Этот массив хранит состояние фильтра, используя всего бит. (Не имеет особого значения, как инициализируется этот массив; мы можем просто заполнить его нулями или случайными битами.)2 к н н 2 кa 2k n n2k
Чтобы добавить новое значение в фильтр, вычислите , где обозначает первые битов, а обозначает следующие битов . Пусть .яx i∥j=H(x) k j n H ( x ) a i = ji k j n H(x) ai=j
Чтобы проверить, было ли добавлено значение в фильтр, вычислите , как указано выше, и проверьте, является ли . Если да, верните true; в противном случае верните false.я 'x′ a i ′ = j ′i′∥j′=H(x′) ai′=j′
Утверждение 1. Вероятность ложного срабатывания (= новое значение, ошибочно заявленное как замеченное) составляет . Это может быть сделано сколь угодно малым при скромных затратах в пространстве хранения путем увеличения ; в частности, для эта вероятность по существу незначительна, и на практике она намного меньше вероятности ложного срабатывания из-за аппаратного сбоя. п п ≥ 1281/2n+k n n≥128
В частности, после того, как различных значений были проверены и добавлены в фильтр, вероятность появления по меньшей мере одного ложного срабатывания равна . Например, при и число различных значений, необходимых для получения ложного срабатывания с вероятностью 50%, составляет около .( N 2 - N ) / 2 n + k + 1 n = 128 k = 16 2 ( n + k ) / 2 = 2 72N (N2−N)/2n+k+1 n=128 k=16 2(n+k)/2=272
Пункт 2: Вероятность ложного отрицательного (= ранее добавленную стоимость ложно утверждал, что новый) не больше , чем , где - количество различных значений, добавленных в фильтр (или, более конкретно, количество различных значений, добавленных после того, как конкретное тестируемое значение было добавлено в фильтр в последний раз). N1−(1−2−k)N≈1−exp(−N/2k)<N/2k N
Ps. Чтобы представить «ничтожно малое» в перспективе, 128-битное шифрование обычно считается неразрушимым с известной в настоящее время технологией. Получение ложных срабатываний по этой схеме с так же вероятно, как если бы кто-то правильно угадал ваш секретный 128-битный ключ шифрования с первой попытки . (При и вероятность этого примерно в 65 000 раз ниже).n = 128 k = 16n+k=128 n=128 k=16
Но если это все еще заставляет вас чувствовать себя иррационально нервным, вы всегда можете переключиться на ; это удвоит ваши требования к хранилищу, но я могу с уверенностью поспорить с вами на любую сумму, которую вы хотели бы назвать, что никто никогда не увидит ложный положительный результат при - при условии, что хеш-функция не нарушена.n = 256n=256 n=256
источник
Нет, невозможно иметь эффективную структуру данных с этими свойствами, если вы хотите гарантировать, что структура данных скажет «новая», если она действительно новая (она никогда и никогда не скажет «не новая», если это на самом деле новый; ложные негативы не допускаются). Любая такая структура данных должна сохранять все данные, чтобы когда-либо отвечать «не новым». См. Pents90 ответ на cstheory для точного обоснования.
Напротив, фильтры Блума могут гарантировать, что структура данных будет говорить «не новая», если она не новая, эффективным способом. В частности, фильтры Bloom могут быть более эффективными, чем хранение всех данных: каждый отдельный элемент может быть довольно длинным, но размер фильтра Bloom масштабируется с учетом количества элементов, а не их общей длины. Любая структура данных для вашей задачи должна масштабироваться с учетом общей длины данных, а не количества элементов данных.
источник
Как насчет хеш-таблицы? Когда вы видите новый элемент, проверьте хэш-таблицу. Если место элемента пусто, верните «новый» и добавьте элемент. В противном случае проверьте, не занято ли место предмета. Если это так, верните «не новый». Если место занято каким-либо другим элементом, верните «новый» и перезапишите место новым элементом.
Вы определенно всегда правильно получите «Новый», если вы никогда не видели хэш элемента раньше. Вы определенно всегда правильно получите «Не новый», если вы видели только хэш элемента, когда видели тот же элемент. Единственный раз, когда вы получите «Новый», когда правильный ответ «Не новый», - это если вы видите элемент А, затем видите элемент Б, затем снова видите элемент А, и оба хеша A и B одинаковы. Важно отметить, что вы не можете получить «Не новый» неправильно.
источник
В случае, когда совокупность элементов конечна, тогда да: просто используйте фильтр Блума, который записывает, какие элементы находятся вне набора, а не в наборе. (То есть используйте фильтр Блума, который представляет собой дополнение интересующего вас набора.)
Место, где это полезно - разрешить ограниченную форму удаления. Вы держите два фильтра Блума. Они начинают пустыми. Когда вы вставляете элементы, вы вставляете их в фильтр Блума А. Если позже вы захотите удалить элемент, вы вставляете этот элемент в фильтр Блума B. Невозможно восстановить его. Чтобы выполнить поиск, вы сначала ищите в фильтре Блума A. Если вы не нашли соответствия, элемент никогда не вставлялся (с вероятностью 1). Если вы нашли совпадение, элемент может (или не может) быть вставлен. В этом случае вы выполняете поиск в фильтре Блума B. Если вы не нашли соответствия, элемент никогда не удалялся. Если вы нашли совпадение в фильтре Блюма, возможно, элемент был вставлен, а затем удален.
Это на самом деле не отвечает на ваш вопрос, но в этом ограниченном случае фильтр Блума B выполняет именно то поведение «фильтра Блума», которое вы ищете.
Исследователи фильтра Real Bloom используют гораздо более эффективные способы представления удаления, см. Страницу публикации Майка Митценмахера .
источник
Я просто хочу добавить здесь, что, если вы находитесь в удачной ситуации, вы знаете все значения которые вы, возможно, увидите; тогда вы можете использовать фильтр подсчета Блума.vi
Примером могут быть IP-адреса, и вы хотите знать каждый раз, когда появляется сообщение о том, что вы никогда не видели раньше. Но это все еще ограниченный набор, так что вы знаете, чего ожидать.
Фактическое решение простое:
Таким образом, у вас могут быть значения «ложных срабатываний», которые на самом деле были старыми, но были признаны новыми. Однако вы никогда не получите «не новое» для нового значения, так как его значение все еще будет во всех слотах, и никто другой не мог бы забрать это.
источник