"Online" -Algorithmen (Iteratoralgorithmen) zur Schätzung des statistischen Medians, des Modus, der Schiefe und der Kurtosis?


86

Gibt es einen Algorithmus zum Schätzen des Medians, des Modus, der Schiefe und / oder der Kurtosis von Wertesätzen, für den jedoch NICHT alle Werte gleichzeitig im Speicher gespeichert werden müssen?

Ich möchte die Basisstatistik berechnen:

  • Mittelwert: arithmetischer Durchschnitt
  • Varianz: Durchschnitt der quadratischen Abweichungen vom Mittelwert
  • Standardabweichung: Quadratwurzel der Varianz
  • Median: Wert, der die größere Hälfte der Zahlen von der kleineren Hälfte trennt
  • Modus: Häufigster Wert im Set
  • Schiefe: tl; DR
  • Kurtosis: tl; DR

Die Grundformeln für die Berechnung einer dieser Formeln sind Grundschularithmetik, und ich kenne sie. Es gibt auch viele Statistikbibliotheken, die sie implementieren.

Mein Problem ist die große Anzahl (Milliarden) von Werten in den Mengen, die ich verarbeite: In Python kann ich nicht einfach eine Liste oder einen Hash mit Milliarden von Elementen erstellen. Selbst wenn ich dies in C geschrieben habe, sind Arrays mit Milliarden Elementen nicht allzu praktisch.

Die Daten werden nicht sortiert. Es wird zufällig und spontan von anderen Prozessen produziert. Die Größe jedes Satzes ist sehr variabel und die Größen werden nicht im Voraus bekannt sein.

Ich habe bereits herausgefunden, wie ich mit dem Mittelwert und der Varianz ziemlich gut umgehen kann, indem ich jeden Wert in der Menge in beliebiger Reihenfolge durchlaufen habe. (In meinem Fall nehme ich sie in der Reihenfolge, in der sie generiert wurden.) Hier ist der Algorithmus, den ich verwende, mit freundlicher Genehmigung von http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :

  • Initialisieren Sie drei Variablen: count, sum und sum_of_squares
  • Für jeden Wert:
    • Inkrementanzahl.
    • Addiere den Wert zur Summe.
    • Addiere das Quadrat des Wertes zu sum_of_squares.
  • Teilen Sie die Summe durch die Anzahl und speichern Sie sie als variablen Mittelwert.
  • Teilen Sie sum_of_squares durch count und speichern Sie es als Variable mean_of_squares.
  • Quadratischer Mittelwert, der als Quadrat_Mittelwert gespeichert wird.
  • Subtrahieren Sie square_of_mean von mean_of_squares und speichern Sie es als Varianz.
  • Ausgangsmittelwert und Varianz.

Dieser "Online" -Algorithmus weist Schwachstellen auf (z. B. Genauigkeitsprobleme, da sum_of_squares schnell größer als der ganzzahlige Bereich oder die Float-Genauigkeit wird), aber er gibt mir im Grunde das, was ich brauche, ohne jeden Wert in jedem Satz speichern zu müssen.

Ich weiß jedoch nicht, ob es ähnliche Techniken zur Schätzung der zusätzlichen Statistiken gibt (Median, Modus, Schiefe, Kurtosis). Ich könnte mit einem voreingenommenen Schätzer oder sogar einer Methode leben, die die Genauigkeit bis zu einem gewissen Grad beeinträchtigt, solange der zur Verarbeitung von N-Werten erforderliche Speicher wesentlich kleiner als O (N) ist.

Das Verweisen auf eine vorhandene Statistikbibliothek hilft auch, wenn die Bibliothek über Funktionen verfügt, mit denen eine oder mehrere dieser Operationen "online" berechnet werden können.


Werden die Daten sortiert übergeben und kennen Sie die Anzahl der Eingaben im Voraus?
Chillysapien

Nützlicher vorhandener Link auf StackOverflow: stackoverflow.com/questions/895929/…
dmckee --- Ex-Moderator-Kätzchen

Sind das ganzzahlige Daten oder Float-Daten? Haben Sie einen Max- oder Min-Wert?
stephan

dmckee: Ich verwende tatsächlich die Welford-Methode für die Standardabweichung. Aber ich sehe in diesem Link nichts über Modus, Median, Kurtosis oder Schiefe ... Vermisse ich etwas?
Ryan B. Lynch

stephan: Einige Datensätze sind Ganzzahlen, andere Floats. Die Bevölkerungsverteilung liegt ziemlich nahe am Normalen (Gauß), so dass wir ein Konfidenzintervall festlegen können, aber es gibt keine harte Bereichsgrenze (außer x> 0 in einigen Fällen).
Ryan B. Lynch

Antworten:


53

Schiefe und Kurtosis

Informationen zu den Online-Algorithmen für Skewness und Kurtosis (entlang der Varianz) finden Sie auf derselben Wiki-Seite hier die parallelen Algorithmen für Statistiken mit höheren Momenten.

Median

Der Median ist ohne sortierte Daten schwierig. Wenn Sie wissen, wie viele Datenpunkte Sie haben, müssen Sie theoretisch nur teilweise sortieren, z. B. mithilfe eines Auswahlalgorithmus . Bei Milliarden von Werten hilft das jedoch nicht allzu viel. Ich würde vorschlagen, Frequenzzählungen zu verwenden, siehe nächster Abschnitt.

Median und Modus mit Frequenzzählungen

Wenn es sich um ganze Zahlen handelt, würde ich Frequenzen zählen und wahrscheinlich die höchsten und niedrigsten Werte über einen Wert hinaus abschneiden, bei dem ich sicher bin, dass sie nicht mehr relevant sind. Für Floats (oder zu viele Ganzzahlen) würde ich wahrscheinlich Buckets / Intervalle erstellen und dann den gleichen Ansatz wie für Ganzzahlen verwenden. Der (ungefähre) Modus und die Medianberechnung werden anhand der Häufigkeitstabelle einfacher.

Normalverteilte Zufallsvariablen

Wenn es normal verteilt ist, würde ich den Mittelwert der Populationsstichprobe , die Varianz , die Schiefe und die Kurtosis als Schätzer für die maximale Wahrscheinlichkeit für eine kleine Teilmenge verwenden. Die (Online-) Algorithmen zur Berechnung dieser haben Sie bereits jetzt. Lesen Sie beispielsweise ein paar hunderttausend oder Millionen Datenpunkte ein, bis Ihr Schätzfehler klein genug wird. Stellen Sie einfach sicher, dass Sie zufällig aus Ihrem Satz auswählen (z. B. dass Sie keine Verzerrung einführen, indem Sie die ersten 100'000 Werte auswählen). Der gleiche Ansatz kann auch für den Schätzmodus und den Median für den Normalfall verwendet werden (für beide ist der Stichprobenmittelwert ein Schätzer).

Weitere Kommentare

Alle oben genannten Algorithmen können parallel ausgeführt werden (einschließlich vieler Sortier- und Auswahlalgorithmen, z. B. QuickSort und QuickSelect), sofern dies hilfreich ist.

Ich habe immer angenommen (mit Ausnahme des Abschnitts über die Normalverteilung), dass wir über Stichprobenmomente, Median und Modus sprechen, nicht über Schätzer für theoretische Momente bei einer bekannten Verteilung.

Im Allgemeinen sollte das Abtasten der Daten (dh nur das Betrachten einer Teilmenge) angesichts der Datenmenge ziemlich erfolgreich sein, solange alle Beobachtungen Realisierungen derselben Zufallsvariablen (mit denselben Verteilungen) und der Momente, des Modus und der Daten sind Median existiert tatsächlich für diese Verteilung. Die letzte Einschränkung ist nicht harmlos. Zum Beispiel existieren der Mittelwert (und alle höheren Momente) für die Cauchy-Verteilung nicht. In diesem Fall kann der Stichprobenmittelwert einer "kleinen" Teilmenge massiv vom Stichprobenmittelwert der gesamten Stichprobe abweichen.


57

Ich verwende diese inkrementellen / rekursiven Mittelwert- und Medianschätzer, die beide konstanten Speicher verwenden:

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

Dabei ist eta ein kleiner Lernratenparameter (z. B. 0,001) und sgn () die Signumfunktion, die einen von {-1, 0, 1} zurückgibt. (Verwenden Sie eine konstante eta, wenn die Daten nicht stationär sind und Sie Änderungen über die Zeit verfolgen möchten. Andernfalls können Sie für stationäre Quellen so etwas wie eta = 1 / n für den Mittelwertschätzer verwenden, wobei n die Anzahl der so gesehenen Stichproben ist weit ... leider scheint dies für den Medianschätzer nicht zu funktionieren.)

Diese Art von inkrementellem Mittelwertschätzer scheint überall verwendet zu werden, z. B. in unbeaufsichtigten Lernregeln für neuronale Netze, aber die Medianversion scheint trotz ihrer Vorteile (Robustheit gegenüber Ausreißern) viel seltener zu sein. Es scheint, dass die Medianversion in vielen Anwendungen als Ersatz für den Mittelwertschätzer verwendet werden könnte.

Ich würde gerne einen inkrementellen Modusschätzer einer ähnlichen Form sehen ...

AKTUALISIEREN

Ich habe gerade den inkrementellen Medianschätzer modifiziert, um beliebige Quantile zu schätzen. Im Allgemeinen gibt eine Quantilfunktion ( http://en.wikipedia.org/wiki/Quantile_function ) den Wert an, der die Daten in zwei Brüche unterteilt: p und 1-p. Im Folgenden wird dieser Wert schrittweise geschätzt:

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

Der Wert p sollte innerhalb von [0,1] liegen. Dies verschiebt im Wesentlichen die symmetrische Ausgabe {-1,0,1} der Funktion sgn () nach einer Seite und unterteilt die Datenproben in zwei ungleich große Bins (die Brüche p und 1-p der Daten sind kleiner als / größer als die Quantilschätzung). Beachten Sie, dass sich dies für p = 0,5 auf den Medianschätzer reduziert.


3
Dieser Medianschätzer ist großartig. Wissen Sie, ob es ähnliche Schätzer für 0,25 / 0,75-Quantile gibt?
Gacek

1
@Gacek, sicher: Teilen Sie den Eingabestream in Lohalf <Median und Hihalf> Median und verwenden Sie Running-Median für jede Hälfte.
Denis

2
@Gacek: Ich habe gerade meine Antwort mit einer inkrementellen Methode aktualisiert, um jedes Quantil zu schätzen, wobei Sie p auf 0,25, 0,75 oder einen beliebigen Wert innerhalb von [0,1] setzen können.
Tyler Streeter

10
Dies funktioniert gut für Mittelwert, aber ich sehe nicht, wie es etwas erzeugt, das in der Nähe des Medians liegt. Nehmen Sie zum Beispiel eine Folge von Millisekunden-Zeitstempeln [1328083200000, 981014400000, -628444800000, 318240000000, 949392000000], die einen Median von haben 318240000000. Diese Gleichung verschiebt den vorherigen Median um +/-, etavon dem der empfohlene Wert war 0.001. Für große Zahlen wie diese wird das nichts bewirken, und für wirklich kleine Zahlen könnte es zu groß sein. Wie würden Sie eine auswählen eta, die Ihnen tatsächlich die richtige Antwort gab, ohne die Antwort a priori zu kennen?
McKamey

9
Stellen Sie sich vor, die Zahlen haben Einheiten, z. B. Millimeter. Dann ist klar, dass eta (für die Schätzung des Medians) die gleichen Einheiten wie die Messungen haben muss, und daher macht ein generischer Wert wie 0,001 einfach keinen Sinn. Ein scheinbar besserer Ansatz besteht darin, eta aus einer laufenden Schätzung der absoluten Abweichung festzulegen: sampleAktualisieren Sie für jeden neuen Wert cumadev += abs(sample-median). Stellen Sie dann ein eta = 1.5*cumadev/(k*k), wo kdie Anzahl der bisher gesehenen Proben liegt.
Tholy

12

Ich habe den P-Quadrat-Algorithmus zur dynamischen Berechnung von Quantilen und Histogrammen ohne Speichern von Beobachtungen in einem von mir geschriebenen Python-Modul namens LiveStats implementiert . Es sollte Ihr Problem ziemlich effektiv lösen. Die Bibliothek unterstützt alle von Ihnen erwähnten Statistiken mit Ausnahme des Modus. Ich habe noch keine zufriedenstellende Lösung für die Modenschätzung gefunden.


Zu Ihrer Information: Der p-Quadrat-Algorithmus ist in C ++ Boost : <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>.
Neil G

7

Ryan, ich fürchte, du machst den Mittelwert und die Varianz nicht richtig ... Das ist vor ein paar Wochen hier aufgetaucht . Und eine der Stärken der Online-Version (die eigentlich unter dem Namen Welfords Methode bekannt ist) ist die Tatsache, dass sie besonders genau und stabil ist (siehe Diskussion hier) . Eine der Stärken ist die Tatsache, dass Sie nicht die Gesamtsumme oder die Gesamtsumme der Quadrate speichern müssen ...

Ich kann mir keinen Online-Ansatz für den Modus und den Median vorstellen, bei dem anscheinend die gesamte Liste auf einmal berücksichtigt werden muss. Aber es kann sehr gut sein, dass ein ähnlicher Ansatz als der für die Varianz und den Mittelwert auch für die Schiefe und Kurtosis funktioniert ...


Betreff: skewness and kurtosisJa. Siehe diesen Artikel: johndcook.com/blog/skewness_kurtosis
Jesse Chisholm

3

Der in der Frage zitierte Wikipedia-Artikel enthält die Formeln zur Online-Berechnung von Schiefe und Kurtosis.

Für den Modus - glaube ich - gibt es keine Möglichkeit, dies online zu tun. Warum? Angenommen, alle Werte Ihrer Eingabe unterscheiden sich außer dem letzten, der einen vorherigen dupliziert. In diesem Fall müssen Sie sich alle Werte merken, die bereits in der Eingabe angezeigt wurden, um festzustellen, dass der letzte Wert einen zuvor angezeigten Wert dupliziert und ihn zum häufigsten macht.

Für den Median ist es fast derselbe - bis zur letzten Eingabe wissen Sie nicht, welcher Wert zum Median wird, wenn alle Eingabewerte unterschiedlich sind, da er vor oder nach dem aktuellen Median liegen kann. Wenn Sie die Länge der Eingabe kennen, können Sie den Median finden, ohne alle Werte im Speicher zu speichern, aber Sie müssen immer noch viele davon speichern (ich schätze ungefähr die Hälfte), da eine schlechte Eingabesequenz den Median stark im verschieben könnte Die zweite Hälfte macht möglicherweise einen Wert aus der ersten Hälfte des Medians.

(Beachten Sie, dass ich mich nur auf die genaue Berechnung beziehe.)


2

Wenn Sie Milliarden von Datenpunkten haben, ist es unwahrscheinlich, dass Sie genaue Antworten benötigen, im Gegensatz zu engen Antworten. Wenn Sie Milliarden von Datenpunkten haben, wird der zugrunde liegende Prozess, der sie generiert, wahrscheinlich einer statistischen Stationarität / Ergodizität / Mischeigenschaft entsprechen. Es kann auch wichtig sein, ob Sie erwarten, dass die Verteilungen einigermaßen kontinuierlich sind oder nicht.

Unter diesen Umständen gibt es Algorithmen für die Online- Schätzung mit geringem Speicher von Quantilen mit (der Median ist ein Sonderfall von 0,5 Quantilen) sowie Modi, wenn Sie keine genauen Antworten benötigen. Dies ist ein aktives Statistikfeld.

Beispiel für eine Quantilschätzung: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

Beispiel für eine Modusschätzung: Bickel DR. Robuste Schätzer für den Modus und die Schiefe kontinuierlicher Daten. Computerstatistik und Datenanalyse. 2002; 39: 153–163. doi: 10.1016 / S0167-9473 (01) 00057-3.

Dies sind aktive Felder der Computerstatistik. Sie gelangen in die Bereiche, in denen es keinen einzigen exakten Algorithmus gibt, sondern eine Vielzahl von Algorithmen (in Wahrheit statistische Schätzer), die unterschiedliche Eigenschaften, Annahmen und Leistungen aufweisen. Es ist experimentelle Mathematik. Es gibt wahrscheinlich Hunderte bis Tausende von Artikeln zu diesem Thema.

Die letzte Frage ist, ob Sie wirklich Schiefe und Kurtosis für sich brauchen oder eher einige andere Parameter, die bei der Charakterisierung der Wahrscheinlichkeitsverteilung zuverlässiger sind (vorausgesetzt, Sie haben eine Wahrscheinlichkeitsverteilung!). Erwarten Sie einen Gaußschen?

Haben Sie Möglichkeiten, die Daten zu bereinigen / vorzuverarbeiten, um sie größtenteils gaußsch zu machen? (Zum Beispiel sind Finanztransaktionsbeträge nach Logarithmen oft etwas Gaußsch). Erwarten Sie endliche Standardabweichungen? Erwarten Sie fette Schwänze? Sind die Mengen, die Sie interessieren, in den Schwänzen oder in der Masse?


2

Jeder sagt immer wieder, dass man den Modus nicht online machen kann, aber das ist einfach nicht wahr. Hier ist ein Artikel , der einen Algorithmus beschreibt, der genau dieses Problem löst, das 1982 von Michael E. Fischer und Steven L. Salzberg von der Yale University erfunden wurde. Aus dem Artikel:

Der Mehrheitsfindungsalgorithmus verwendet eines seiner Register zum temporären Speichern eines einzelnen Elements aus dem Stream. Dieser Punkt ist der aktuelle Kandidat für das Mehrheitselement. Das zweite Register ist ein auf 0 initialisierter Zähler. Für jedes Element des Streams bitten wir den Algorithmus, die folgende Routine auszuführen. Wenn der Zähler 0 lautet, installieren Sie das aktuelle Stream-Element als neuen Mehrheitskandidaten (wobei jedes andere Element ersetzt wird, das sich möglicherweise bereits im Register befindet). Wenn das aktuelle Element mit dem Mehrheitskandidaten übereinstimmt, erhöhen Sie den Zähler. Andernfalls dekrementieren Sie den Zähler. Wenn zu diesem Zeitpunkt im Zyklus der bisher gesehene Teil des Streams ein Mehrheitselement aufweist, befindet sich dieses Element im Kandidatenregister, und der Zähler enthält einen Wert größer als 0. Was ist, wenn es kein Mehrheitselement gibt? Ohne einen zweiten Durchlauf durch die Daten - was in einer Stream-Umgebung nicht möglich ist - kann der Algorithmus unter diesen Umständen nicht immer eine eindeutige Antwort geben. Es verspricht lediglich, das Mehrheitselement korrekt zu identifizieren, falls es eines gibt.

Es kann auch erweitert werden, um das oberste N mit mehr Speicher zu finden, dies sollte es jedoch für den Modus lösen.


4
Das ist ein interessanter Algorithmus, aber wenn mir nichts fehlt, sind zwar alle Mehrheitswerte Modi, aber nicht alle Modi Mehrheitswerte.
Jkebinger

Der Link ist gestorben, daher bin ich froh, dass die Beschreibung enthalten ist. ABER wie beschrieben erhöht sich der Zähler nur, wenn das zweite Vorkommen des Mehrheitskandidaten neben dem ersten Vorkommen liegt. Welche IMPLIES sortierte Daten. Was im Online- (Streaming-) Datenfall NICHT garantiert ist. Bei zufällig angeordneten Daten ist es unwahrscheinlich, dass Modi gefunden werden.
Jesse Chisholm

1

Wenn Sie keine a priori parametrischen Kenntnisse über die Verteilung haben, müssen Sie meiner Meinung nach alle Werte speichern.

Das heißt, wenn Sie nicht mit einer pathologischen Situation zu tun haben, kann das Heilmittel (Rousseuw und Bassett 1990) für Ihre Zwecke gut genug sein.

Ganz einfach geht es darum, den Median der Medianstapel zu berechnen.


0

Median und Modus können nicht online berechnet werden, wenn nur konstanter Speicherplatz verfügbar ist. Da Median und Modus ohnehin eher "beschreibend" als "quantitativ" sind, können Sie sie beispielsweise durch Abtasten des Datensatzes schätzen.

Wenn die Daten auf lange Sicht normal verteilt sind, können Sie einfach Ihren Mittelwert verwenden, um den Median zu schätzen.

Sie können den Median auch mit der folgenden Technik schätzen: Erstellen Sie eine Medianschätzung M [i] für beispielsweise 1.000.000 Einträge im Datenstrom, sodass M [0] der Median der ersten eine Million Einträge ist, M [1] the Median der zweiten Million Einträge usw. Verwenden Sie dann den Median von M [0] ... M [k] als Medianschätzer. Dies spart natürlich Platz und Sie können steuern, wie viel Platz Sie verwenden möchten, indem Sie den Parameter 1.000.000 "einstellen". Dies kann auch rekursiv verallgemeinert werden.


0

OK, Alter, probier diese aus:

für c ++:

double skew(double* v, unsigned long n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow((v[i] - mu)/sigma, 3);
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

double kurt(double* v, double n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

Wenn Sie sagen, dass Sie bereits die Stichprobenvarianz (svar) und den Durchschnitt (avg) berechnen können, verweisen Sie diese auf Ihre Funktionen, um dies zu tun.

Schauen Sie sich auch Pearsons Annäherungssache an. Bei einem so großen Datensatz wäre es ziemlich ähnlich. 3 (Mittelwert - Median) / Standardabweichung Sie haben den Median als max - min / 2

Für Floats hat der Modus keine Bedeutung. man würde sie normalerweise in Behälter mit einer signifikanten Größe stecken (wie 1/100 * (max - min)).



-1

Ich würde dazu neigen, Eimer zu verwenden, die anpassungsfähig sein könnten. Die Schaufelgröße sollte der Genauigkeit entsprechen, die Sie benötigen. Wenn dann jeder Datenpunkt eingeht, addieren Sie einen zur Anzahl der relevanten Buckets. Diese sollten Ihnen einfache Annäherungen an Median und Kurtosis geben, indem Sie jeden Eimer als seinen Wert zählen, gewichtet mit seiner Anzahl.

Das einzige Problem könnte ein Auflösungsverlust im Gleitkomma nach Milliarden von Operationen sein, dh das Hinzufügen einer ändert den Wert nicht mehr! Um dies zu umgehen, können Sie eine große Anzahl aller Zählungen entfernen, wenn die maximale Schaufelgröße einen bestimmten Grenzwert überschreitet.


-1
for j in range (1,M):
    y=np.zeros(M) # build the vector y
    y[0]=y0

    #generate the white noise
    eps=npr.randn(M-1)*np.sqrt(var)

    #increment the y vector
    for k in range(1,T):
        y[k]=corr*y[k-1]+eps[k-1]

    yy[j]=y

list.append(y)

Könnte eine Erklärung gebrauchen, um dies besser mit der ursprünglichen Frage zu verknüpfen.
Erica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.