Domanda

calcolo della varianza

Non ho davvero utilizzato più di tanto, e non so bene cosa aspettarci. In realtà io non sono troppo buono con la matematica a tutti.

Ho una una matrice di valori numerici casuali 1000000 nell'intervallo 0-10000.

La matrice potrebbe crescere ancora più grande, in modo da utilizzare a 64 bit int per somma.

Ho cercato di trovare il codice su come calc varianza, ma non so se ho uscita corretta.

La media è 4692 e la mediana è 4533. ottengo varianza 1.483.780,469,308 mila utilizzando il seguente codice:

// 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)) );

Sto ottenendo un valore ragionevole?

E 'qualcosa di sbagliato con il calcolo?

È stato utile?

Soluzione

Nota. Non sembra come si sta calcolando la varianza

varianza viene calcolata sottraendo la media da ogni elemento e calcolando la somma pesata di queste differenze.

Quindi quello che dovete fare è:

// 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;

Si noti che questa è la varianza del campione, e viene utilizzato quando la distribuzione sottostante è sconosciuto (così assumiamo una distribuzione uniforme).

Inoltre, dopo un po 'scavare intorno, ho scoperto che questo non è uno stimatore. Wolfram Alpha ha qualcosa da dire su questo, ma come esempio, quando MATLAB calcola la varianza, restituisce la 'varianza campionaria polarizzazione corretta' .

La varianza polarizzazione corretta può essere ottenuta dividendo per ciascun elemento da size-1, o:

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

Si noti inoltre che, il valore della mean rimane lo stesso.

Altri suggerimenti

Prima di tutto, se si sta solo cercando di ottenere una maniglia su ciò che è una varianza "ragionevole", tenere presente che la varianza è fondamentalmente la deviazione standard al quadrato. La deviazione standard misura più o meno la distanza tipica da un punto di dati al suo valore atteso.

Quindi, se i dati ha media 4692, e la vostra varianza calcolata è venuta fuori a 1.483.780, che significa che la vostra deviazione standard è di circa 1218, che suggerisce i numeri tendono ad essere da qualche parte nelle vicinanze della gamma 3474 - 5910. Così che la varianza in realtà sembra un po 'bassa per me, se la gamma dei vostri numeri è 0-10.000; ma dipende, ovviamente, dalla distribuzione dei dati.

Per quanto riguarda il calcolo stesso: È possibile calcolare la varianza utilizzando un calcolo in esecuzione come stai leggendo i dati la prima volta intorno (Non è necessario conoscere la media in anticipo) utilizzando di Welford Metodo :

  

Inizializza M1 = x1 e S1 = 0.

     

Per le successive xe, utilizzare la ricorrenza   formule

     

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

     

Per 2 ≤ k ≤ n, la stima del k-esima   varianza è s2 = Sk / (k - 1).

Solo per divertimento, un percorso leggermente diverso per lo stesso risultato, utilizzando std :: valarray invece di std :: vector e (varie) algoritmi:

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();
}

Come accennato Jacob, ci sono in realtà due possibili versioni di un calcolo della varianza. Così com'è, questo presuppone tuoi ingressi sono ' "universo". Se hai preso solo un campione dell'universo globale, l'ultima riga deve utilizzare:. (diffs.size()-1) invece di diffs.size()

Utilizzare una formula diversa, forse?

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

Uscite:     media = 5036,71     varianza = 3.16806e + 07

Esempio di calcolo della varianza:

#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);
}

Dal momento che si sta lavorando con un gran numero e poi facendo operazioni in virgola mobile su di loro, si potrebbe desiderare di fare tutto nel doppio; che si sarebbe risparmiare un sacco di calchi.

Utilizzando pow .. 2 per calcolare una piazza sembra un po 'imbarazzante. Si potrebbe calcolare il numero di prima, poi moltiplicarlo per sé per ottenere un quadrato.

Se stai facendo divisione e sentono il bisogno di lanciare, lanciare il operandi (cioè il numeratore e / o denominatore) per raddoppiare piuttosto che il risultato. Stai perdendo la precisione se si divide interi.

Non sono sicuro se la formula per la varianza è corretta. Si consiglia di guardare la spiegazione di Wikipedia, per esempio. Ma io non sono un esperto di matematica o, così io non sono sicuro di avere un errore.

Dal momento che la varianza è il quadrato della deviazione standard, le risposte a SO 1.174.984 dovrebbe dare una mano. La diagnosi breve è che è necessario per calcolare la somma dei quadrati dei valori, nonché la somma dei valori, e non sembra di farlo.

Poiché hai 10 6 valori, e il quadrato di qualsiasi valore può essere fino a 10 8 , si potrebbe finire con la somma dei quadrati fino a 10 < sup> 14 ; i tuoi interi a 64 bit possono memorizzare fino a 10 18 , così si potrebbe ancora gestire diecimila volte il numero di ingressi, o valori che vanno fino a un milione anziché soltanto diecimila, senza incorrere in overflow. Non c'è bisogno urgente, quindi, per passare a puri calcoli doppie.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top