Mit einem Bloom-Filter können Sie effizient verfolgen, ob während der Verarbeitung bereits verschiedene Werte festgestellt wurden. Wenn viele Datenelemente vorhanden sind, kann ein Bloom-Filter zu einer erheblichen Speichereinsparung über eine Hash-Tabelle führen. Das Hauptmerkmal eines Bloom-Filters, das es mit einer Hash-Tabelle teilt, ist, dass es immer "nicht neu" sagt, wenn ein Element nicht neu ist, aber es besteht eine Wahrscheinlichkeit ungleich Null, dass ein Element als "nicht neu" gekennzeichnet wird "auch wenn es neu ist.
Gibt es einen "Anti-Bloom-Filter", der das gegenteilige Verhalten aufweist?
Mit anderen Worten: Gibt es eine effiziente Datenstruktur, die "neu" sagt, wenn ein Artikel neu ist, aber für einige Artikel, die nicht neu sind, auch "neu" sagt?
Das Beibehalten aller zuvor angezeigten Elemente (beispielsweise in einer sortierten verknüpften Liste) erfüllt die erste Anforderung, beansprucht jedoch möglicherweise viel Speicher. Ich hoffe, dass es angesichts der entspannten zweiten Anforderung auch unnötig ist.
Für diejenigen, die eine formalere Behandlung bevorzugen, schreiben Sie wenn der Bloom-Filter für neu hält, , und schreiben Sie wenn wirklich neu ist und sonst.
Dann ; ; ; , für einige .0 < α < 1
Ich frage: Existiert eine effiziente Datenstruktur, die eine Funktion mit etwas implementiert , so dass ; ; ; & le; 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 ( xP r [ b ' ( x ) = 1 | n ( x ) = 1 ] = 1
Bearbeiten: Es scheint, dass diese Frage zuvor bei StackExchange gestellt wurde, da /programming/635728 und /cstheory/6596 mit einer Reihe von Antworten von "kann nicht sein" done "through" kann mit einigem Aufwand "to" durchgeführt werden, indem die Werte von umgekehrt werden ". Mir ist noch nicht klar, was die "richtige" Antwort ist. Es ist klar, dass ein LRU-Caching-Schema (wie das von Ilmari Karonen vorgeschlagene) ziemlich gut funktioniert, einfach zu implementieren ist und die Zeit für die Ausführung meines Codes um 50% verkürzt.
quelle
Antworten:
Passend zur Hash-Idee von Patrick87 finden Sie hier eine praktische Konstruktion, die fast Ihren Anforderungen entspricht - die Wahrscheinlichkeit, einen neuen Wert fälschlicherweise mit einem alten zu verwechseln, ist nicht ganz null, kann aber leicht vernachlässigbar klein gemacht werden.
Wählen Sie die Parameter und k ; praktische Werte könnten beispielsweise n = 128 und k = 16 sein . Sei H eine sichere kryptographische Hash-Funktion , die (mindestens) n + k Ausgabebits erzeugt.n k n=128 k=16 H n+k
Lassen ein Array von Be 2 k n -Bit bitstrings. Dieses Array speichert den Zustand des Filters mit insgesamt n 2 k Bits. (Es ist nicht besonders wichtig, wie dieses Array initialisiert wird. Wir können es einfach mit Nullen oder mit zufälligen Bits füllen.)a 2k n n2k
Um dem Filter einen neuen Wert hinzuzufügen , berechnen Sie ix , wobei i die ersten k Bits und j die folgenden n Bits von H ( x ) bezeichnet . Sei a i = j .i∥j=H(x) i k j n H(x) ai=j
Um zu testen, ob dem Filter ein Wert hinzugefügt wurde, berechnen Sie i '.x′ , wie oben, und überprüfe, ob a i ' = j ' ist . Wenn ja, geben Sie true zurück. Andernfalls wird false zurückgegeben.i′∥j′=H(x′) ai′=j′
Anspruch 1: Die Wahrscheinlichkeit eines falsch - positiven (= fälschlich neuen Wert beansprucht gesehen worden war) wird . Dies kann durch Erhöhen von n zu bescheidenen Kosten des Speicherplatzes beliebig klein gemacht werden ; Insbesondere ist diese Wahrscheinlichkeit für n ≥ 128 im Wesentlichen vernachlässigbar und in der Praxis viel geringer als die Wahrscheinlichkeit eines falschen Positivs aufgrund einer Hardwarefehlfunktion.1/2n+k n n≥128
Insbesondere beträgt , nachdem verschiedene Werte geprüft und dem Filter hinzugefügt wurden, die Wahrscheinlichkeit, dass mindestens ein falsches Positiv aufgetreten ist, ( N 2 - N ) / 2 n + k + 1 . Zum Beispiel beträgt bei n = 128 und k = 16 die Anzahl der eindeutigen Werte, die erforderlich sind, um ein falsches Positiv mit einer Wahrscheinlichkeit von 50% zu erhalten, ungefähr 2 ( n + k ) / 2 = 2 72 .N (N2−N)/2n+k+1 n=128 k=16 2(n+k)/2=272
Behauptung 2: Die Wahrscheinlichkeit eines falsch negativen (= früher fälschlicherweise als neu geltend gemachten Mehrwerts) ist nicht größer als wobei N die Anzahl der dem Filter hinzugefügten eindeutigen Werte ist (oder genauer gesagt die Anzahl der eindeutigen Werte, die hinzugefügt wurden, nachdem der zu testende spezifische Wert zuletzt dem Filter hinzugefügt wurde).1−(1−2−k)N≈1−exp(−N/2k)<N/2k N
Ps. Um "vernachlässigbar klein" ins rechte Licht zu rücken, gilt die 128-Bit-Verschlüsselung mit der derzeit bekannten Technologie im Allgemeinen als unzerbrechlich . Ein falsches Positiv aus diesem Schema mit ist so wahrscheinlich, als würde jemand Ihren geheimen 128-Bit-Verschlüsselungsschlüssel beim ersten Versuch richtig erraten . (Mit n = 128 und k = 16 ist die Wahrscheinlichkeit ungefähr 65.000-mal geringer.)n+k=128 n=128 k=16
Aber wenn Sie sich dadurch immer noch irrational nervös fühlen, können Sie jederzeit auf umschalten . Es wird Ihren Speicherbedarf verdoppeln, aber ich kann mit Sicherheit sagen, dass niemand jemals ein falsches Positiv mit n = 256 sehen wird - vorausgesetzt, die Hash-Funktion ist ohnehin nicht defekt.n=256 n=256
quelle
Nein, es ist nicht möglich, eine effiziente Datenstruktur mit diesen Eigenschaften zu haben, wenn Sie die Garantie haben möchten, dass die Datenstruktur "neu" sagt, wenn sie wirklich neu ist (wenn nicht, wird sie niemals "nicht neu" sagen) es ist in der Tat neu; keine falschen Negative erlaubt). Jede solche Datenstruktur muss alle Daten enthalten, um jemals "nicht neu" zu antworten. Siehe pents90 Antwort auf cstheory für eine präzise Begründung.
Im Gegensatz dazu Bloom Filter können eine Garantie erhalten , dass die Datenstruktur sagt „nicht neu“ , wenn es nicht neu ist, auf effiziente Art und Weise. Insbesondere können Bloom-Filter effizienter sein als das Speichern aller Daten: Jedes einzelne Element ist möglicherweise recht lang, aber die Größe des Bloom-Filters richtet sich nach der Anzahl der Elemente und nicht nach ihrer Gesamtlänge. Jede Datenstruktur für Ihr Problem muss mit der Gesamtlänge der Daten skaliert werden, nicht mit der Anzahl der Datenelemente.
quelle
Was ist mit nur einem Hash-Tisch? Wenn Sie ein neues Element sehen, überprüfen Sie die Hash-Tabelle. Wenn die Stelle des Artikels leer ist, geben Sie "neu" zurück und fügen Sie den Artikel hinzu. Andernfalls prüfen Sie, ob die Stelle des Artikels mit dem Artikel belegt ist. Wenn ja, geben Sie "nicht neu" zurück. Wenn die Stelle mit einem anderen Gegenstand belegt ist, geben Sie "neu" zurück und überschreiben Sie die Stelle mit dem neuen Gegenstand.
Sie erhalten auf jeden Fall immer "Neu", wenn Sie den Hash des Artikels noch nie zuvor gesehen haben. Sie erhalten auf jeden Fall immer "Nicht neu", wenn Sie den Hash des Artikels nur gesehen haben, als Sie den gleichen Artikel gesehen haben. Das einzige Mal, dass Sie "Neu" erhalten, wenn die richtige Antwort "Nicht neu" lautet, ist, wenn Sie Artikel A sehen, dann Artikel B sehen, dann Artikel A erneut sehen und A und B auf dasselbe gehasht haben. Wichtig ist, dass Sie niemals "Nicht neu" falsch erhalten können.
quelle
Wenn das Universum der Elemente endlich ist, dann ja: Verwenden Sie einfach einen Bloom-Filter, der aufzeichnet, welche Elemente nicht in der Menge, sondern in der Menge enthalten sind. (Verwenden Sie also einen Bloom-Filter, der das Komplement des interessierenden Satzes darstellt.)
Ein Ort, an dem dies nützlich ist, besteht darin, eine begrenzte Form des Löschens zuzulassen. Sie behalten zwei Blütenfilter. Sie fangen leer an. Wenn Sie Elemente einfügen, fügen Sie sie in Bloom-Filter A ein. Wenn Sie später ein Element löschen möchten, fügen Sie dieses Element in Bloom-Filter B ein. Es gibt keine Möglichkeit, die Löschung rückgängig zu machen. Um eine Suche durchzuführen, müssen Sie zuerst in Bloom-Filter A nachschlagen. Wenn Sie keine Übereinstimmung finden, wurde der Artikel nie eingefügt (mit Wahrscheinlichkeit 1). Wenn Sie eine Übereinstimmung finden, wurde das Element möglicherweise (oder möglicherweise nicht) eingefügt. In diesem Fall führen Sie eine Suche in Bloom-Filter B durch. Wenn Sie keine Übereinstimmung finden, wurde der Artikel nie gelöscht. Wenn Sie in Bloom-Filter B eine Übereinstimmung finden, wurde der Artikel wahrscheinlich eingefügt und dann gelöscht.
Dies beantwortet Ihre Frage nicht wirklich, aber in diesem begrenzten Fall führt der Bloom-Filter B genau das "Anti-Bloom-Filter" -Verhalten aus, das Sie suchen.
Real Bloom filter researchers use much more efficient ways of representing deletion, see Mike Mitzenmacher's publication's page.
quelle
Ich möchte hier nur hinzufügen, dass Sie, wenn Sie sich in einer glücklichen Situation befinden, alle Werte kennenvich dass Sie möglicherweise sehen könnten; Dann können Sie einen Zählblütenfilter verwenden.
Ein Beispiel könnten IP-Adressen sein, und Sie möchten jedes Mal wissen, wenn eine solche Adresse erscheint, die Sie noch nie gesehen haben. Aber es ist immer noch eine endliche Menge, sodass Sie wissen, was Sie erwarten können.
Die eigentliche Lösung ist einfach:
Es kann also sein, dass Sie "falsch-positive" Werte haben, die zwar alt, aber als neu erkannt wurden. Sie werden jedoch für einen neuen Wert niemals "nicht neu" erhalten, da sein Wert immer noch in allen Slots vorhanden ist, und niemand anderes hätte ihn wegnehmen können.
quelle