Question

Je n'ai pas vraiment calcul de variance utilisé beaucoup, et je ne sais pas à quoi nous attendre. En fait, je ne suis pas trop bon avec les mathématiques du tout.

J'ai un tableau de 1000000 valeurs numériques aléatoires dans la gamme 0-10000.

Le tableau pourrait croître encore plus, donc j'utiliser 64 bits int pour somme.

J'ai essayé de trouver le code sur la façon de calco la variance, mais je ne sais pas si je reçois une sortie correcte.

La moyenne est 4692 et la médiane est 4533. Je reçois la variance 1483780,469308 en utilisant le code suivant:

// size is the element count, in this case 1000000
// value_sum is __int64

double p2 = pow( (double)(value_sum - (value_sum/size)), (double)2.0 );
double variance = sqrt( (double)(p2 / (size-1)) );

Suis-je obtenir une valeur raisonnable?

Quelque chose ne va pas avec le calcul?

Était-ce utile?

La solution

Remarque:. Il ne ressemble pas à vous calculez la variance

variance est calculée en soustrayant la moyenne de tous les éléments et le calcul de la somme pondérée de ces différences.

Alors ce que vous devez faire est:

// Get mean
double mean = static_cast<double>(value_sum)/size;

// Calculate variance
double variance = 0;
for(int i = 0;i<size;++i) 
{
  variance += (MyArray[i]-mean)*(MyArray[i]-mean)/size;
}

// Display
cout<<variance;

Notez que ceci est la variance de l'échantillon et est utilisé lorsque la distribution sous-jacente est inconnue (donc on suppose une distribution uniforme).

En outre, après des fouilles autour, je trouve que ce n'est pas un estimateur sans biais. a quelque chose à dire au sujet de cette Wolfram Alpha , mais comme un exemple, quand calcule Matlab la variance, elle renvoie le "échantillon corrigé biais-variance" .

La variance corrigée polarisation peut être obtenue en divisant chaque élément par size-1, ou:

//Please check that size > 1
variance += (MyArray[i]-mean)*(MyArray[i]-mean)/(size-1); 

Notez également que, la valeur de mean reste le même.

Autres conseils

Tout d'abord, si vous êtes à la recherche d'obtenir une poignée sur ce qui est un écart « raisonnable », gardez à l'esprit que la variance est essentiellement l'écart-type au carré. L'écart-type mesure à peu près la distance typique d'un point de données à sa valeur attendue.

Donc, si vos données a une moyenne 4692, et votre variance calculée sort à 1.483.780, cela signifie que votre écart-type est d'environ 1218, ce qui suggère vos chiffres ont tendance à être quelque part à proximité de la plage 3474 - 5910. Donc, que la variance semble en fait un peu faible pour moi si la plage de numéros est 0-10000; mais cela dépend évidemment de la distribution de vos données.

En ce qui concerne le calcul lui-même: Vous pouvez calculer la variance à l'aide d'un calcul en cours d'exécution que vous lisez vos données la première fois (vous n'avez pas connaître la moyenne à l'avance) en utilisant Méthode de Welford:

  

Initialize M1 = x1 et S1 = 0.

     

Pour de suite x, utilisez la récurrence   formules

     

Mk = Mk-1 + (xk - Mk-1) / k = Sk Sk-1 +   (Xk - Mk-1) * (xk - Mk).

     

2 ≤ k ≤ n, l'estimation de la kième du   est la variance s2 = Sk / (k - 1).

Juste pour le plaisir, une route légèrement différente au même résultat, en utilisant std :: valarray au lieu de std :: vecteur et (divers) algorithmes:

template <class T>
T const variance(std::valarray<T> const &v) {
    if (v.size() == 0)
        return T(0.0);
    T average = v.sum() / v.size();
    std::valarray<T> diffs = v-average;
    diffs *= diffs;
    return diffs.sum()/diffs.size();
}

Comme Jacob a laissé entendre, il y a vraiment deux versions possibles d'un calcul de la variance. En l'état actuel, cela suppose que vos entrées sont « l'univers ». Si vous avez pris seulement un échantillon de l'univers global, la dernière ligne devrait utiliser:. (diffs.size()-1) au lieu de diffs.size()

Utilisez une autre formule peut-être?

#include <functional>
#include <algorithm>
#include <iostream>
int main()
{
 using namespace std;

 vector<double> num( 3 );
 num[ 0 ] = 4000.9, num[ 1 ] = 11111.221, num[ 2 ] = -2;


 double mean = std::accumulate(num.begin(), num.end(), 0.0) / num.size();
 vector<double> diff(num.size());
 std::transform(num.begin(), num.end(), diff.begin(), 
                std::bind2nd(std::minus<double>(), mean));
 double variance = std::inner_product(diff.begin(), diff.end(), 
                                     diff.begin(), 0.0) / (num.size() - 1);
 cout << "mean = " << mean << endl
      << "variance = " << variance << endl;
}

Sorties:     moyenne = 5036,71     variance = 3.16806e + 07

calcul de la variance de l'échantillon:

#include <math.h>
#include <vector>

double Variance(std::vector<double>);

int main()
{
     std::vector<double> samples;
     samples.push_back(2.0);
     samples.push_back(3.0);
     samples.push_back(4.0);
     samples.push_back(5.0);
     samples.push_back(6.0);
     samples.push_back(7.0);

     double variance = Variance(samples);
     return 0;
}

double Variance(std::vector<double> samples)
{
     int size = samples.size();

     double variance = 0;
     double t = samples[0];
     for (int i = 1; i < size; i++)
     {
          t += samples[i];
          double diff = ((i + 1) * samples[i]) - t;
          variance += (diff * diff) / ((i + 1.0) *i);
     }

     return variance / (size - 1);
}

Puisque vous travaillez avec un grand nombre, puis faire des opérations à virgule flottante sur eux, vous pouvez tout faire en double; cela vous permettra d'économiser beaucoup de moulages.

Utilisation pow .. 2 pour calculer un carré semble un peu maladroit. Vous pouvez calculer votre numéro, puis multiplier par lui-même pour obtenir un carré.

Si vous faites division et ressentent le besoin de jeter, jeter le opérandes (à savoir le numérateur et / ou dénominateur) doubler plutôt que le résultat. Tu perds la précision si vous diviser des nombres entiers.

Je ne sais pas si votre formule pour la variance est correcte. Vous voudrez peut-être regarder l'explication dans Wikipedia, par exemple. Mais je ne suis pas expert en mathématiques soit, donc je ne suis pas sûr que vous avez une erreur.

Étant donné que la variance est le carré de l'écart-type, les réponses à SO 1174984 devrait aider. Le diagnostic court est que vous devez calculer la somme des carrés des valeurs ainsi que la somme des valeurs, et vous ne semblez pas faire.

Etant donné que vous avez 10 6 valeurs, et le carré d'une valeur quelconque peut être jusqu'à 10 8 , on peut se retrouver avec une somme de carrés de 10 < sup> 14 ; vos entiers 64 bits peuvent stocker jusqu'à 10 18 , vous pouvez toujours gérer dix mille fois plus d'entrées, ou des valeurs allant jusqu'à un million au lieu de seulement dix mille, sans courir en trop-pleins. Il n'y a pas de besoin urgent, donc, de passer à des calculs doubles purs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top