2017-09-03 78 views
-1

我經常通過數據處理某些數據。爲了簡單起見,讓我們考慮一下數據是一系列相同數量的數字。 當數字不合理時,標準化數據可能會有用。常見的轉換之一是減去所有值的平均值。在這個轉換之後,轉換的數據將具有平均零。嘗試規範化數據時出現巨大數值錯誤

零均值後可以完成的其他常見轉換是將數據除以它們的標準偏差。應用此轉換後,新數據有單位差異。

當以這種方式對數據進行歸一化處理時,我期望數值誤差應該更小。但是,我似乎無法做這些轉換,因爲即使我正在計算標準偏差,也會出現數字錯誤。

波紋管是c#中的示例代碼,我嘗試計算標準偏差。即使沒有(公式的)統計知識,程序的輸出應該爲零也可以很容易地看到。 (如果數據是常量的陣列則數據的平方的平均等於平均值​​的平方。)

static double standardDeviation(double[] data) 
{ 
    double sum = 0; 
    double sumOfSquares = 0; 
    foreach (double number in data) 
    { 
     sum += number; 
     sumOfSquares += number * number; 
    } 
    double average = sum/data.Length; 
    double averageOfSquares = sumOfSquares/data.Length; 
    return Math.Sqrt(averageOfSquares - average * average); 
} 
static void Main(string[] args) 
{ 
    double bigNumber = 1478340000000; 
    double[] data = Enumerable.Repeat(bigNumber, 83283).ToArray(); 
    Console.WriteLine(standardDeviation(data)); 
} 

代替零的程序輸出造成的數值誤差數量龐大:2133383.0308878

注意,如果我會省略Math.Sqrt(即我會計算方差而不是標準偏差),那麼錯誤會更高。

原因是什麼,如何用smaler數字錯誤書寫這個問題?

回答

1

儘管用於方差的公式在數學上是正確的 - 也就是說,如果您具有無限精度,則可能導致精度有限。

爲N個數據X A更好的方式是計算

variance = Sum{ square(X[i] - mean) }/ N 

其中

mean = Sum{ X[i] } /N 

作爲寫入這需要通過數據兩遍。如果這很尷尬,你實際上可以一次完成。您需要保留三個變量,n(迄今爲止看到的數據項的數量)均值和方差。這些都應該初始化爲0(又名0.0)。然後,當你得到一個數據項X:

n = n + 1 
f = 1.0/n 
d = x-mean 
mean = mean + f*d 
variance = (1.0-f)*(variance + f*d*d) 

在處理數據項n,之後每個階段,均值,方差的確計數,平均值和數據的變化爲止。

+0

Thx爲偉大的答案。我特別喜歡你一次傳球的方式。我明白這個意思是正確的。然而,對於我來說,方差似乎是錯誤的。以下公式如何?'vaiance =(1.0-f)*方差+ f * d * d *(1.0 + f)'這對我來說會更有意義。 –

+0

我很確定我的公式是正確的。當f = 1時,您的公式不能用於第一個數據項,當f = 1時,公式給出非零值,2 * d * d其中d是第一個數據值(因爲均值初始化爲0)。但是1件東西的差異是0 – dmuir

+0

你的反例是正確的。你的公式也是如此。我用你的公式編寫了程序,並返回期望值。所以我標記你的答案已被接受。但是我仍然不明白它爲什麼會起作用。 –

-1

我認爲你最大/最小可能數(±5.0×10-324到±1.7×10308)與有效數字(15 - 16)有雙倍數。

就你而言,我認爲你是在浪費數字而不是縮放首先輸入,即將你的值轉換爲1.47834,比例因子爲1/10^7你的數字計算。

+0

縮放無關於此。無論如何由FP表示完成並且可以分解或不分解。 –

相關問題