2013-05-27 5 views
2

J'utilise actuellement un algorithme de variance en ligne pour calculer la variance pour une séquence donnée. Cela fonctionne bien, et donne également une bonne stabilité numérique et une résistance au débordement, au prix d'une certaine vitesse, ce qui est bien. Ma question est, existe-t-il un algorithme qui sera plus rapide que si la moyenne de l'échantillon est déjà connue, tout en ayant une stabilité et une résistance similaires au débordement (donc pas quelque chose comme un calcul de variance naïf).Calcul de la variance donnée moyenne

Le calcul actuel de la variance en ligne est un algorithme à un seul passage avec des divisions et des multiplications dans la boucle principale (ce qui influe sur la vitesse). De wikipedia:

def online_variance(data): 
    n = 0 
    mean = 0 
    M2 = 0 

    for x in data: 
     n = n + 1 
     delta = x - mean 
     mean = mean + delta/n 
     M2 = M2 + delta*(x - mean) 

    variance = M2/(n - 1) 
    return variance 
+0

Nous ne pouvons pas dire qu'un algorithme est plus rapide qu'un autre, sans connaître l'autre ... – Floris

Répondre

3

Ce qui provoque un calcul de variance naïve pour aller instable est le fait que vous additionnez séparément les X (pour obtenir mean (x)) et les valeurs de X^2, puis prendre la différence

var = mean(x^2) - (mean(x))^2 

Mais puisque la définition de la variance est

var = mean((x - mean(x))^2) 

Vous pouvez simplement évaluer cela et il sera aussi vite que possible. Lorsque vous ne connaissez pas la moyenne, vous devez d'abord la calculer pour la stabilité, ou utiliser la formulation "naïve" qui ne passe qu'une fois aux données au détriment de la stabilité numérique.

EDIT Maintenant que vous avez donné le code "original", il est facile d'être meilleur (plus rapide). Comme vous le signalez correctement, la division dans la boucle interne vous ralentit. Essayez celui-ci pour la comparaison:

def newVariance(data, mean): 
    n = 0 
    M2 = 0 

    for x in data: 
    n = n + 1 
    delta = x - mean 
    M2 = M2 + delta * delta 

    variance = M2/(n - 1) 
    return variance 

Remarque - cela ressemble beaucoup à la two_pass_variance algorithm from Wikipedia, sauf que vous n'avez pas besoin de la première passe pour calculer la moyenne, puisque vous dites qu'il est déjà connu.