Un filtro Bloom permite realizar un seguimiento eficiente de si ya se han encontrado varios valores durante el procesamiento. Cuando hay muchos elementos de datos, un filtro Bloom puede generar un ahorro significativo de memoria en una tabla hash. La característica principal de un filtro Bloom, que comparte con una tabla hash, es que siempre dice "no nuevo" si un elemento no es nuevo, pero hay una probabilidad distinta de cero de que un elemento se marque como "no nuevo" "incluso cuando es nuevo.
¿Existe un "filtro anti-Bloom" que tenga el comportamiento opuesto?
En otras palabras: ¿existe una estructura de datos eficiente que diga "nuevo" si un elemento es nuevo, pero que también podría decir "nuevo" para algunos elementos que no son nuevos?
Mantener todos los elementos vistos anteriormente (por ejemplo, en una lista vinculada ordenada) satisface el primer requisito pero puede usar mucha memoria. Espero que también sea innecesario, dado el segundo requisito relajado.
Para aquellos que prefieren un tratamiento más formal, escriba si el filtro Bloom cree que es nuevo, contrario, y escriba si realmente es nuevo contrario.
Entonces ; ; ; , para algunos .
Estoy preguntando: ¿existe una estructura de datos eficiente, implementando una función con algún , tal que ; ; ; ?P r [ b ′ ( x ) = 1 | n ( x ) = 1 ] = 1
Editar: Parece que esta pregunta se ha hecho antes en StackExchange, ya que /programming/635728 y /cstheory/6596 con un rango de respuestas de "no se puede hecho "a través" se puede hacer, a algún costo "a" es trivial, invirtiendo los valores de ". Todavía no me queda claro cuál es la respuesta "correcta". Lo que está claro es que un esquema de almacenamiento en caché LRU de algún tipo (como el sugerido por Ilmari Karonen) funciona bastante bien, es fácil de implementar y resultó en una reducción del 50% en el tiempo necesario para ejecutar mi código.
fuente
Respuestas:
De acuerdo con la idea hash de Patrick87, aquí hay una construcción práctica que casi cumple con sus requisitos: la probabilidad de confundir falsamente un valor nuevo con uno antiguo no es del todo cero, pero puede hacerse fácilmente insignificante.
Elija los parámetros y ; valores prácticos podrían ser, por ejemplo, y . Sea una función hash criptográfica segura que produce (al menos) bits de salida.k n = 128 k = 16 H n + kn k n=128 k=16 H n+k
Vamos ser una matriz de bitstrings -bit. Esta matriz almacena el estado del filtro, utilizando un total de bits. (No importa en particular cómo se inicializa esta matriz; solo podemos llenarla con ceros o con bits aleatorios).2 k n n 2 ka 2k n n2k
Para agregar un nuevo valor al filtro, calcule , donde denota los primeros bits y denota los siguientes bits de . Deje .x i k j n H ( x ) a i = ji∥j=H(x) i k j n H(x) ai=j
Para probar si se ha agregado un valor al filtro, calcule , como se indica arriba, y verifique si . Si es así, devuelve verdadero; de lo contrario, devuelve falso.i ′x′ a i ′ = j ′i′∥j′=H(x′) ai′=j′
Reclamación 1: la probabilidad de un falso positivo (= nuevo valor que se afirma haber visto falsamente) es . Esto puede hacerse arbitrariamente pequeño, a un costo modesto en el espacio de almacenamiento, aumentando ; en particular, para , esta probabilidad es esencialmente insignificante, siendo, en la práctica, mucho menor que la probabilidad de un falso positivo debido a un mal funcionamiento del hardware. n n ≥ 1281/2n+k n n≥128
En particular, después de que se hayan verificado y agregado al filtro valores distintos, la probabilidad de que haya ocurrido al menos un falso positivo es . Por ejemplo, con y , el número de valores distintos necesarias para conseguir un falso positivo con 50% de probabilidad es de aproximadamente .( N 2 - N ) / 2 n + k + 1 n = 128 k = 16N (N2−N)/2n+k+1 n=128 k=16 2(n+k)/2=272
Reclamación 2: La probabilidad de un falso negativo (= valor agregado previamente que se afirma falsamente como nuevo) no es mayor que , donde es el número de valores distintos agregados al filtro (o, más específicamente, el número de valores distintos agregados después de que el valor específico que se está probando se haya agregado más recientemente al filtro).1−(1−2−k)N≈1−exp(−N/2k)<N/2k N
PD. Para poner en perspectiva "insignificantemente pequeño", el cifrado de 128 bits generalmente se considera indescifrable con la tecnología actualmente conocida. Obtener un falso positivo de este esquema con es tan probable como que alguien adivine correctamente su clave secreta de cifrado de 128 bits en su primer intento . (Con y , que es en realidad cerca de 65.000 veces menos probable que eso.)n+k=128 n=128 k=16
Pero si eso todavía te hace sentir irracionalmente nervioso, siempre puedes cambiar a ; que va a duplicar sus requisitos de almacenamiento, pero con seguridad se puede apostar cualquier suma que le importa a nombre de que nadie va nunca ver a un falso positivo con - suponiendo que la función hash no se rompe, de todos modos.n=256 n=256
fuente
No, no es posible tener una estructura de datos eficiente con estas propiedades, si desea tener una garantía de que la estructura de datos dirá "nuevo" si es realmente nuevo (nunca, nunca dirá "no nuevo" si de hecho es nuevo; no se permiten falsos negativos). Cualquier estructura de datos de este tipo deberá conservar todos los datos para responder "no nuevo". Vea la respuesta de pents90 en teoría para una justificación precisa.
En contraste, los filtros Bloom pueden garantizar que la estructura de datos dirá "no nuevo" si no es nuevo, de manera eficiente. En particular, los filtros Bloom pueden ser más eficientes que almacenar todos los datos: cada elemento individual puede ser bastante largo, pero el tamaño del filtro Bloom se escala con el número de elementos, no su longitud total. Cualquier estructura de datos para su problema tendrá que escalar con la longitud total de los datos, no con el número de elementos de datos.
fuente
¿Qué tal solo una tabla hash? Cuando vea un nuevo elemento, consulte la tabla hash. Si el lugar del elemento está vacío, devuelva "nuevo" y agregue el elemento. De lo contrario, verifique si el lugar del artículo está ocupado por el artículo. Si es así, devuelve "no nuevo". Si el lugar está ocupado por algún otro elemento, devuelva "nuevo" y sobrescriba el lugar con el nuevo elemento.
Definitivamente siempre obtendrá correctamente "Nuevo" si nunca antes ha visto el hash del elemento. Definitivamente siempre obtendrá correctamente "No nuevo" si solo ha visto el hash del elemento cuando ha visto el mismo elemento. La única vez que obtendrá "Nuevo" cuando la respuesta correcta sea "No nuevo" es si ve el elemento A, luego ve el elemento B, luego ve el elemento A nuevamente, y tanto A como B hacen lo mismo. Es importante destacar que nunca puede obtener "No nuevo" incorrectamente.
fuente
En el caso donde el universo de elementos es finito, entonces sí: solo use un filtro de floración que registre qué elementos están fuera del conjunto, en lugar de en el conjunto. (Es decir, use un filtro de floración que represente el complemento del conjunto de interés).
Un lugar donde esto es útil es permitir una forma limitada de eliminación. Tienes dos filtros de floración. Comienzan vacíos. A medida que inserta elementos, los inserta en el filtro de floración A. Si luego desea eliminar un elemento, inserte ese elemento en el filtro de floración B. No hay forma de recuperarlo. Para realizar una búsqueda, primero busque en el filtro de floración A. Si no encuentra ninguna coincidencia, el elemento nunca se insertó (con probabilidad 1). Si encuentra una coincidencia, el elemento puede (o no) haber sido insertado. En ese caso, realice una búsqueda en el filtro de floración B. Si no encuentra ninguna coincidencia, el elemento nunca se eliminó. Si encuentra una coincidencia en el filtro de floración B, el elemento probablemente se insertó y luego se eliminó.
Esto realmente no responde a su pregunta, pero, en este caso limitado, el filtro de floración B está realizando exactamente el comportamiento de "filtro anti-floración" que está buscando.
Los investigadores del filtro Real Bloom utilizan formas mucho más eficientes de representar la eliminación, consulte la página de publicación de Mike Mitzenmacher .
fuente
Solo quiero agregar aquí, que si estás en una situación afortunada, conoces todos los valores que posiblemente puedas ver; entonces puedes usar un filtro de recuento de floración.vi
Un ejemplo podría ser las direcciones IP, y desea saber cada vez que aparece una que nunca ha visto antes. Pero todavía es un conjunto finito, por lo que sabes lo que puedes esperar.
La solución real es simple:
Por lo tanto, es posible que tenga valores de 'falsos positivos' que en realidad eran viejos, pero reconocidos como nuevos. Sin embargo, nunca obtendrá 'no nuevo' para un nuevo valor, ya que su valor seguirá estando en todas las ranuras, y nadie más podría haberlo quitado.
fuente