web-dev-qa-db-fra.com

Algorithmes "en ligne" (itérateurs) pour l'estimation de la médiane statistique, du mode, de l'asymétrie, du kurtosis?

Existe-t-il un algorithme pour estimer la médiane, le mode, l'asymétrie et/ou le kurtosis d'un ensemble de valeurs, mais cela ne nécessite PAS de stocker toutes les valeurs en mémoire à la fois?

Je voudrais calculer les statistiques de base:

  • moyenne: moyenne arithmétique
  • variance: moyenne des écarts carrés par rapport à la moyenne
  • écart type: racine carrée de la variance
  • médiane: valeur qui sépare la moitié supérieure des nombres de la moitié inférieure
  • mode: valeur la plus fréquente trouvée dans l'ensemble
  • asymétrie: tl; dr
  • kurtosis: tl; dr

La formule de base pour calculer l’un de ces facteurs est l’arithmétique des écoles primaires, et je les connais. De nombreuses bibliothèques de statistiques les implémentent également.

Mon problème est le grand nombre (milliards) de valeurs dans les ensembles que je gère: En travaillant en Python, je ne peux pas simplement créer une liste ou un hachage avec des milliards d'éléments. Même si j’écrivais ceci en C, les tableaux de milliards d’éléments ne sont pas très pratiques.

Les données ne sont pas triées. Il est produit au hasard, à la volée, par d'autres processus. La taille de chaque ensemble est très variable, et les tailles ne seront pas connues à l'avance.

J'ai déjà compris comment gérer assez bien la moyenne et la variance, en parcourant chaque valeur de l'ensemble dans n'importe quel ordre. (En fait, dans mon cas, je les prends dans l'ordre dans lequel elles ont été générées.) Voici l'algorithme que j'utilise, avec l'aimable autorisation http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :

  • Initialise trois variables: count, sum et sum_of_squares
  • Pour chaque valeur:
    • Nombre d'incréments.
    • Ajouter la valeur à la somme.
    • Ajoutez le carré de la valeur à sum_of_squares.
  • Diviser la somme par le nombre, en enregistrant comme moyenne variable.
  • Divisez sum_of_squares par count, en enregistrant la variable mean_of_squares.
  • Square signifie, stockant comme square_of_mean.
  • Soustrayez square_of_mean de mean_of_squares, en le stockant en tant que variance.
  • Moyenne de sortie et variance.

Cet algorithme "en ligne" présente des faiblesses (par exemple, des problèmes de précision car sum_of_squares augmente rapidement au-delà de la plage entière ou de la précision flottante), mais il me donne essentiellement ce dont j'ai besoin, sans avoir à stocker chaque valeur de chaque ensemble.

Mais je ne sais pas s'il existe des techniques similaires pour estimer les statistiques supplémentaires (médiane, mode, asymétrie, kurtosis). Je pourrais vivre avec un estimateur biaisé, voire une méthode qui compromet la précision dans une certaine mesure, à condition que la mémoire requise pour traiter N valeurs soit sensiblement inférieure à O (N).

Me pointer vers une bibliothèque de statistiques existante sera également utile si la bibliothèque dispose de fonctions permettant de calculer une ou plusieurs de ces opérations "en ligne".

80
Ryan B. Lynch

Skewness et Kurtosis

Pour les algorithmes en ligne pour Skewness et Kurtosis (le long des lignes de la variance), voir dans la même page de wiki ici les algorithmes parallèles pour les statistiques de moments plus élevés.

Médiane

La médiane est difficile sans données triées. Si vous connaissez le nombre de points de données dont vous disposez, vous ne devez en théorie que trier partiellement, par exemple. en utilisant un algorithme de sélection . Cependant, cela n'aide pas beaucoup avec des milliards de valeurs. Je suggérerais d'utiliser des comptes de fréquence, voir la section suivante.

Médiane et mode avec comptes de fréquence

Si c’est un nombre entier, je compterais fréquences , en coupant probablement les valeurs les plus hautes et les plus basses au-delà d’une valeur où je suis sûr que ce n’est plus pertinent. Pour les floats (ou trop d’entiers), je créerais probablement des compartiments/intervalles, puis utiliserais la même approche que pour les entiers. Le mode (approximatif) et le calcul de la médiane deviennent faciles, en fonction du tableau des fréquences.

Variables aléatoires normalement distribuées

S'il est normalement distribué, j'utiliserais l'échantillon de population moyenne , variance , asymétrie et kurtosis comme estimateurs de vraisemblance maximum pour un petit sous-ensemble. Les algorithmes (en ligne) pour calculer ceux-ci, vous avez déjà maintenant. Par exemple. lisez en quelques centaines de milliers ou millions de points de données, jusqu'à ce que votre erreur d'estimation soit suffisamment petite. Assurez-vous simplement de choisir au hasard dans votre jeu (par exemple, de ne pas introduire de biais en choisissant les 100 000 premières valeurs). La même approche peut également être utilisée pour estimer le mode et la médiane dans le cas normal (la moyenne de l'échantillon est un estimateur).

D'autres commentaires

Tous les algorithmes ci-dessus peuvent être exécutés en parallèle (y compris de nombreux algorithmes de tri et de sélection, tels que QuickSort et QuickSelect), si cela vous aide.

J'ai toujours supposé (à l'exception de la section sur la distribution normale) que nous parlons d'échantillons de moments, de médianes et de modes, et non d'estimateurs de moments théoriques pour une distribution connue.

En général, échantillonner les données (c’est-à-dire ne regarder qu’un sous-ensemble) devrait être assez réussi compte tenu de la quantité de données, à condition que toutes les observations soient des réalisations de la même variable aléatoire la médiane existe réellement pour cette distribution. La dernière mise en garde n'est pas anodine. Par exemple, la moyenne (et tous les moments les plus élevés) pour la distribution Cauchy n’existe pas. Dans ce cas, la moyenne d'échantillon d'un "petit" sous-ensemble pourrait être très largement différente de la moyenne d'échantillon de l'ensemble.

50
stephan

J'utilise ces estimateurs moyen et médian incrémental/récursif, qui utilisent tous deux un stockage constant:

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

eta est un paramètre de vitesse d'apprentissage faible (par exemple, 0,001) et sgn () est la fonction signum qui renvoie l'un des éléments suivants: {-1, 0, 1}. (Utilisez une constante eta si les données sont non stationnaires et que vous souhaitez suivre les changements dans le temps; sinon, pour les sources stationnaires, vous pouvez utiliser un paramètre du type eta = 1/n. estimateur moyen, où n est le nombre d'échantillons vus jusqu'à présent ... malheureusement, cela ne semble pas fonctionner pour l'estimateur médian.)

Ce type d’estimateur moyen incrémental semble être utilisé partout, par ex. dans les règles d’apprentissage des réseaux de neurones non supervisés, mais la version médiane semble beaucoup moins commune, malgré ses avantages (robustesse aux valeurs aberrantes). Il semble que la version médiane pourrait remplacer l’estimateur moyen dans de nombreuses applications.

J'aimerais beaucoup voir un estimateur de mode incrémentiel de forme similaire ...

METTRE À JOUR

Je viens de modifier l'estimateur médian incrémental pour estimer des quantiles arbitraires. En général, une fonction quantile ( http://en.wikipedia.org/wiki/Quantile_function ) vous indique la valeur qui divise les données en deux fractions: p et 1-p. Ce qui suit estime cette valeur progressivement:

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

La valeur p doit être comprise entre [0,1]. Cela déplace essentiellement la sortie symétrique {-1,0,1} de la fonction sgn () vers un côté, partitionnant les échantillons de données en deux groupes de taille inégale (fractions p et 1-p des données). sont inférieures/supérieures à l’estimation quantile, respectivement). Notez que pour p = 0,5, ceci se réduit à l'estimateur médian.

53
Tyler Streeter

J'ai implémenté l'algorithme P-square pour le calcul dynamique de quantiles et d'histogrammes sans stockage d'observations dans un module Python ordonné que j'ai écrit appelé LiveStats . Cela devrait résoudre votre problème assez efficacement. La bibliothèque prend en charge toutes les statistiques que vous mentionnez sauf le mode. Je n'ai pas encore trouvé de solution satisfaisante pour l'estimation du mode.

9
Sean

Ryan, j'ai bien peur que vous ne fassiez pas la moyenne et la variance correctement ... Cela est arrivé il y a quelques semaines ici . Et l'un des points forts de la version en ligne (qui s'appelle en réalité la méthode de Welford) est le fait qu'elle est particulièrement précise et stable, voir la discussion ici . L'un des points forts est le fait qu'il n'est pas nécessaire de stocker la somme totale ou la somme totale des carrés ...

Je ne peux pas penser à une approche en ligne du mode et de la médiane, qui semble nécessiter l'examen de la liste complète à la fois. Mais il se peut très bien qu'une approche similaire à celle utilisée pour la variance et la moyenne fonctionne également pour l'asymétrie et le kurtosis ...

7
Jaime

L'article de Wikipedia cité dans la question contient les formules pour calculer l'asymétrie et le kurtosis en ligne.

Pour le mode - je crois - il n’ya aucun moyen de le faire en ligne. Pourquoi? Supposons que toutes les valeurs de votre entrée sont différentes, à l'exception du dernier qui duplique une précédente. Dans ce cas, vous devez vous souvenir de toutes les valeurs déjà vues dans l'entrée pour détecter que la dernière valeur duplique une valeur vue avant et en fait la plus fréquente.

Pour la médiane, c'est à peu près la même chose - jusqu'à la dernière entrée, vous ne savez pas quelle valeur deviendra la médiane si toutes les valeurs d'entrée sont différentes car elles pourraient se situer avant ou après la médiane actuelle. Si vous connaissez la longueur de l'entrée, vous pouvez trouver la médiane sans enregistrer toutes les valeurs en mémoire, mais vous devrez néanmoins en stocker plusieurs (je suppose autour de la moitié), car une séquence de saisie incorrecte risque de décaler fortement la seconde moitié faisant éventuellement n'importe quelle valeur de la première moitié de la médiane.

(Notez que je me réfère uniquement au calcul exact.)

3
Daniel Brückner

Si vous avez des milliards de points de données, il est peu probable que vous ayez besoin de réponses exactes, par opposition à des réponses proches. Généralement, si vous avez des milliards de points de données, le processus sous-jacent qui les génère obéira probablement à une sorte de propriété de stationnarité statistique/ergodicité/mélange. De plus, il peut être important que vous vous attendiez à ce que les distributions soient raisonnablement continues ou non. 

Dans ces circonstances, il existe des algorithmes pour les quantiles en ligne, à faible mémoire, estimation (la médiane est un cas particulier de quantile 0,5), ainsi que des modes, si vous n'avez pas besoin de réponses exactes. C'est un champ de statistiques actif. 

exemple d'estimation quantile: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

exemple d'estimation de mode: Bickel DR. Estimateurs robustes du mode et de l'asymétrie des données continues. Statistiques de calcul et analyse de données. 2002; 39: 153–163. doi: 10.1016/S0167-9473 (01) 00057-3.

Ce sont des champs actifs de statistiques de calcul. Vous entrez dans les domaines où il n’existe pas de meilleur algorithme exact, mais une diversité d’entre eux (estimateurs statistiques, en réalité), qui ont des propriétés, des hypothèses et des performances différentes. C'est des mathématiques expérimentales. Il y a probablement des centaines, des milliers d'articles dans ce domaine.

La dernière question est de savoir si vous avez réellement besoin d'asymétrie et de kurtosis par eux-mêmes ou, plus probablement, d'autres paramètres qui pourraient être plus fiables pour caractériser la distribution de probabilité (en supposant que vous ayez une distribution de probabilité!). Vous attendez un gaussien?

Avez-vous des moyens de nettoyer/pré-traiter les données pour les rendre principalement gaussiennes? (par exemple, les montants des transactions financières sont souvent quelque peu gaussiens après la prise de logarithmes). Vous attendez-vous à des écarts-types finis? Vous attendez-vous des queues grasses? Les quantités qui vous intéressent sont-elles dans la queue ou dans la masse? 

2
Matt Kennel

Tout le monde n'arrête pas de dire que vous ne pouvez pas utiliser le mode en ligne, mais ce n'est tout simplement pas vrai. Voici un article décrivant un algorithme pour résoudre ce problème, inventé en 1982 par Michael E. Fischer et Steven L. Salzberg de l’Université de Yale. De l'article: 

L'algorithme de recherche de majorité utilise l'un de ses registres pour les fichiers temporaires stockage d'un seul article du flux; Cet élément est le courant candidat à la majorité. Le deuxième registre est un compteur initialisé à 0. Pour chaque élément du flux, nous demandons l'algorithme effectuer la routine suivante. Si le compteur indique 0, installez le fichier élément de flux en cours en tant que nouveau candidat majoritaire (déplacement de tout élément qui pourrait déjà être dans le registre). Ensuite, si le l'élément en cours correspond au candidat majoritaire, incrémente le compteur; sinon, décrémentez le compteur. À ce stade du cycle, si le une partie du flux vu jusqu'ici a un élément majoritaire, cet élément est dans le registre candidat et le compteur contient une valeur supérieure à 0. Et s'il n'y a pas d'élément majoritaire? Sans faire un second passage dans les données, ce qui n'est pas possible dans un environnement de flux, le fichier L'algorithme ne peut pas toujours donner une réponse sans ambiguïté dans ceci circonstance. Il promet simplement d'identifier correctement la majorité élément s'il y en a un.

Il peut également être étendu pour trouver le top N avec plus de mémoire mais cela devrait le résoudre pour le mode.

2
hackartist

En fin de compte, si vous n’avez pas de connaissances paramétriques a priori sur la distribution, vous devez mémoriser toutes les valeurs. 

Cela dit, à moins que vous ne soyez confronté à une situation pathologique, le remède (Rousseuw et Bassett, 1990) pourrait bien suffire à vos fins.

Très simplement, il s’agit de calculer la médiane des lots de médianes. 

1
Edward Grace
0
user14717

la médiane et le mode ne peuvent pas être calculés en ligne en utilisant uniquement l'espace disponible constant. Cependant, comme la médiane et le mode sont de toute façon plus "descriptifs" que "quantitatifs", vous pouvez les estimer, par exemple. en échantillonnant l'ensemble de données.

Si les données sont distribuées normalement à long terme, vous pouvez simplement utiliser votre moyenne pour estimer la médiane.

Vous pouvez également estimer la médiane à l'aide de la technique suivante: établissez une estimation médiane M [i] pour chaque, par exemple, 1 000 000 entrées dans le flux de données, de sorte que M [0] soit la médiane du premier million d'entrées, M [1]. la médiane du deuxième million d'entrées, etc. Utilisez ensuite la médiane de M [0] ... M [k] comme estimateur médian. Cela économise évidemment de l'espace et vous pouvez contrôler la quantité d'espace que vous souhaitez utiliser en "ajustant" le paramètre 1 000 000. Ceci peut être aussi généralisé de manière récursive.

0
Antti Huima

OK mec essayez ceci:

pour 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;
}

là où vous dites que vous pouvez déjà calculer la variance de l’échantillon (svar) et la moyenne (avg) .__, vous les indiquez à vos fonctions.

Jetez également un coup d’œil à l’approximation de Pearson. sur un si grand ensemble de données, il serait assez similaire… .. 3 (moyenne - médiane)/écart typevous avez la médiane comme max - min/2

pour le mode floats n'a pas de sens. on les enfonce généralement dans des bacs d’une taille minime (1/100 * (max - min)).

0
peter