Wie funktioniert der HyperLogLog-Algorithmus?

171

In meiner Freizeit habe ich in letzter Zeit verschiedene Algorithmen kennengelernt. Einer, auf den ich gestoßen bin und der sehr interessant erscheint, heißt HyperLogLog-Algorithmus. Er schätzt, wie viele eindeutige Elemente in einer Liste enthalten sind.

Dies war besonders interessant für mich, weil es mich zu meinen MySQL-Tagen zurückbrachte, als ich diesen "Kardinalitäts" -Wert sah (von dem ich bis vor kurzem immer angenommen hatte, dass er nicht geschätzt berechnet wurde).

Ich weiß also, wie man einen Algorithmus in O ( n ) schreibt , der berechnet, wie viele eindeutige Elemente sich in einem Array befinden. Ich habe das in JavaScript geschrieben:

function countUniqueAlgo1(arr) {
    var Table = {};
    var numUnique = 0;
    var numDataPoints = arr.length;
    for (var j = 0; j < numDataPoints; j++) {
        var val = arr[j];
        if (Table[val] != null) {
            continue;
        }
        Table[val] = 1;
        numUnique++;
    }
    return numUnique;
}

Das Problem ist jedoch, dass mein Algorithmus, während O ( n ), viel Speicher benötigt (Speichern von Werten in Table).

Ich habe dieses Papier darüber gelesen, wie man Duplikate in einer Liste in O ( n ) Zeit zählt und nur minimalen Speicher benötigt.

Es wird erklärt, dass durch Hashing und Zählen von Bits oder Ähnlichem die Anzahl der eindeutigen Elemente in einer Liste innerhalb einer bestimmten Wahrscheinlichkeit (unter der Annahme, dass die Liste gleichmäßig verteilt ist) geschätzt werden kann.

Ich habe die Zeitung gelesen, kann sie aber nicht verstehen. Kann jemand die Erklärung eines Laien geben? Ich weiß, was Hashes sind, aber ich verstehe nicht, wie sie in diesem HyperLogLog-Algorithmus verwendet werden.

K2xL
quelle
4
In diesem Dokument ( research.google.com/pubs/pub40671.html ) werden auch der HyperLogLog-Algorithmus und einige Verbesserungen zusammengefasst. Ich denke, es ist leichter zu verstehen als das Originalpapier.
Zhanxw
11
Nur ein Hinweis zur Nomenklatur: Einige Leute verwenden das Wort "Set", um eine Sammlung einzigartiger Gegenstände zu beschreiben . Für sie ist Ihre Frage möglicherweise sinnvoller, wenn Sie stattdessen die Begriffsliste oder das Array verwenden.
Paddy3118

Antworten:

153

Der Haupttrick hinter diesem Algorithmus besteht darin, dass, wenn Sie einen Strom zufälliger Ganzzahlen beobachten und eine Ganzzahl sehen, deren binäre Darstellung mit einem bekannten Präfix beginnt, die Wahrscheinlichkeit höher ist, dass die Kardinalität des Stroms 2 ^ beträgt (Größe des Präfixes). .

Das heißt, in einem zufälligen Strom von ganzen Zahlen beginnen ~ 50% der Zahlen (binär) mit "1", 25% mit "01", 12,5% mit "001". Dies bedeutet, dass, wenn Sie einen zufälligen Stream beobachten und eine "001" sehen, die Wahrscheinlichkeit höher ist, dass dieser Stream eine Kardinalität von 8 hat.

(Das Präfix "00..1" hat keine besondere Bedeutung. Es ist nur deshalb vorhanden, weil es bei den meisten Prozessoren leicht ist, das höchstwertige Bit in einer Binärzahl zu finden.)

Wenn Sie nur eine ganze Zahl beobachten, ist die Wahrscheinlichkeit, dass dieser Wert falsch ist, natürlich hoch. Aus diesem Grund unterteilt der Algorithmus den Stream in "m" unabhängige Teilströme und behält die maximale Länge eines sichtbaren "00 ... 1" -Präfixes jedes Teilstroms bei. Schätzt dann den Endwert, indem der Mittelwert jedes Teilstroms genommen wird.

Das ist die Hauptidee dieses Algorithmus. Es fehlen einige Details (z. B. die Korrektur für niedrige Schätzwerte), aber in der Arbeit ist alles gut geschrieben. Entschuldigung für das schreckliche Englisch.

Juan Lopes
quelle
"Es besteht eine höhere Wahrscheinlichkeit, dass dieser Stream eine Kardinalität von 8 hat." Können Sie bitte erklären, warum 000 die erwartete Anzahl von Versuchen 2 ^ 3 bedeutet? Ich habe versucht, die mathematische Erwartung der Anzahl der Versuche zu berechnen, vorausgesetzt, wir haben mindestens einen Lauf mit 3 Nullen und keine Läufe mit 4 Nullen ...
Yura
5
Ich habe die Zeitung nicht ganz verstanden, bis ich sie gelesen habe. Jetzt macht es Sinn.
Josiah
5
@yura Ich weiß, es ist ein sehr alter Kommentar, aber es kann für andere Leute nützlich sein. Er sagte: "Das heißt, in einem zufälligen Strom von ganzen Zahlen beginnen (...) 12,5% mit" 001 "." Die wahrscheinliche Kardinalität beträgt 8, da 12,5% ein Achtel des gesamten Stroms ausmachen.
Braunmagrin
111

Ein HyperLogLog ist eine probabilistische Datenstruktur . Es zählt die Anzahl der verschiedenen Elemente in einer Liste. Aber im Vergleich zu einer einfachen Methode (eine Menge zu haben und Elemente zur Menge hinzuzufügen) geschieht dies ungefähr.

Bevor Sie sich ansehen, wie der HyperLogLog-Algorithmus dies tut, müssen Sie verstehen, warum Sie ihn benötigen. Das Problem mit einem einfachen Weg ist, dass es Platz verbraucht O(distinct elements). Warum gibt es hier eine große O-Notation statt nur bestimmter Elemente? Dies liegt daran, dass Elemente unterschiedliche Größen haben können. Ein Element kann ein 1anderes Element sein "is this big string". Wenn Sie also eine große Liste (oder einen großen Strom von Elementen) haben, wird viel Speicherplatz benötigt.


Probabilistisches Zählen

Wie kann man eine vernünftige Schätzung einer Reihe einzigartiger Elemente erhalten? Angenommen, Sie haben eine Zeichenfolge mit einer Länge, mdie {0, 1}mit gleicher Wahrscheinlichkeit besteht. Wie groß ist die Wahrscheinlichkeit, dass es mit 0, mit 2 Nullen, mit k Nullen beginnt? Es ist 1/2, 1/4und 1/2^k. Dies bedeutet, dass Sie, wenn Sie auf eine Zeichenfolge mit kNullen gestoßen sind, ungefähr 2^kElemente durchgesehen haben . Das ist also ein guter Ausgangspunkt. Wenn Sie eine Liste von Elementen haben, die gleichmäßig verteilt sind, 0und 2^k - 1Sie die maximale Anzahl des größten Präfixes von Nullen in der Binärdarstellung zählen können, erhalten Sie eine vernünftige Schätzung.

Das Problem ist, dass die Annahme, gleichmäßig verteilte Zahlen von 0t zu haben, 2^k-1zu schwer zu erreichen ist (die Daten, auf die wir gestoßen sind, sind meist keine Zahlen, fast nie gleichmäßig verteilt und können zwischen beliebigen Werten liegen. Mit einer guten Hashing-Funktion können Sie dies jedoch annehmen Die Ausgangsbits wären gleichmäßig verteilt und die meisten Hashing-Funktionen hätten Ausgänge zwischen 0und 2^k - 1( SHA1 gibt Werte zwischen 0und an 2^160). Bisher haben wir also erreicht, dass wir die Anzahl der eindeutigen Elemente mit der maximalen Kardinalität der kBits nur durch Speichern abschätzen können Eine Anzahl von log(k)Größenbits. Der Nachteil ist, dass wir eine große Abweichung in unserer Schätzung haben. Eine coole Sache, die wir fast geschaffen habenDas probabilistische Zählpapier von 1984 (es ist ein bisschen schlauer mit der Schätzung, aber wir sind immer noch nah dran).

LogLog

Bevor wir weitermachen, müssen wir verstehen, warum unsere erste Schätzung nicht so gut ist. Der Grund dafür ist, dass ein zufälliges Auftreten eines hochfrequenten 0-Präfix-Elements alles verderben kann. Eine Möglichkeit, dies zu verbessern, besteht darin, viele Hash-Funktionen zu verwenden, das Maximum für jede der Hash-Funktionen zu zählen und sie am Ende zu mitteln. Dies ist eine ausgezeichnete Idee, die die Schätzung verbessern wird, aber LogLog-Papier verwendete einen etwas anderen Ansatz (wahrscheinlich, weil Hashing ziemlich teuer ist).

Sie verwendeten einen Hash, teilten ihn aber in zwei Teile. Einer wird als Bucket bezeichnet (die Gesamtzahl der Buckets ist 2^x) und ein anderer - entspricht im Grunde unserem Hash. Es war schwer für mich zu verstehen, was los war, also werde ich ein Beispiel geben. Angenommen , Sie haben zwei Elemente und Ihre Hash - Funktion , die Werte Form gibt 0zu 2^102 erzeugten Werte: 344und 387. Sie haben sich für 16 Eimer entschieden. Also hast du:

0101 011000  bucket 5 will store 1
0110 000011  bucket 6 will store 4

Wenn Sie mehr Eimer haben, verringern Sie die Varianz (Sie verbrauchen etwas mehr Platz, aber es ist immer noch winzig). Mit mathematischen Fähigkeiten konnten sie den Fehler quantifizieren (was ist 1.3/sqrt(number of buckets)).

HyperLogLog

HyperLogLog führt keine neuen Ideen ein, verwendet jedoch meistens viel Mathematik, um die vorherige Schätzung zu verbessern. Forscher haben herausgefunden, dass Sie die Schätzung erheblich verbessern, wenn Sie 30% der größten Zahlen aus den Eimern entfernen. Sie verwendeten auch einen anderen Algorithmus zur Mittelung von Zahlen. Das Papier ist mathematisch schwer.


Und ich möchte mit einem kürzlich erschienenen Artikel abschließen , der eine verbesserte Version des hyperLogLog-Algorithmus zeigt (bis jetzt hatte ich keine Zeit, ihn vollständig zu verstehen, aber vielleicht werde ich diese Antwort später verbessern).

Salvador Dali
quelle
2
Ich gehe theoretisch davon aus k zeroes nichts Besonderes ist. Sie können stattdessen suchen k onesund die Logik wäre die gleiche oder sogar nach einer k lengthZeichenfolge suchen, {0,1}aber nehmen Sie eine solche Zeichenfolge und bleiben Sie dabei? weil alle von ihnen bei solchen binären Strings die gleiche Wahrscheinlichkeit von 1/2 ^ k haben?
user881300
3
HyperLogLog entfernt nicht 30% der größten Zahlen. Dies ist die Idee des SuperLogLog-Algorithmus, der auch im LogLog-Dokument beschrieben wird. Die Hauptidee des HyperLogLog-Algorithmus besteht darin, die Potenz von Zweien unter Verwendung des harmonischen Mittelwerts anstelle des geometrischen Mittelwerts zu mitteln, wie er von SuperLogLog und LogLog verwendet wird.
Otmar
21

Die Intuition ist, wenn Ihre Eingabe eine große Menge von Zufallszahlen ist (z. B. Hash-Werte), sollten sie sich gleichmäßig über einen Bereich verteilen. Angenommen, der Bereich beträgt bis zu 10 Bit, um einen Wert von bis zu 1024 darzustellen. Dann wird der Mindestwert beobachtet. Nehmen wir an, es ist 10. Dann wird die Kardinalität auf ungefähr 100 (10 × 100 ≈ 1024) geschätzt.

Lesen Sie das Papier für die wahre Logik natürlich.

Eine weitere gute Erklärung mit Beispielcode finden Sie hier:
Verdammt coole Algorithmen: Kardinalitätsschätzung - Nicks Blog

Wai Yip Tung
quelle
3
für den Link zum verdammt coolen Algorithmus-Blogpost gestimmt. Das hat mir wirklich geholfen, den Algorithmus zu verstehen.
Igor Serebryany