2016-06-14 39 views
2

我得到了一組三維向量(x,y,z),並且我想計算協方差矩陣而不存儲向量。我會在C#中做到這一點,但最終我會用C語言在微控制器上實現它,所以我需要算法本身,而不是庫。運行(單程)協方差計算

僞代碼也會很棒。

回答

1

我想我找到了解決方案。它基於這篇文章約how to calculate covariance manually和這個約calculating running variance。然後我根據第一篇文章中的理解,對後者中的算法進行了調整,以計算協方差而非方差。

public class CovarianceMatrix 
{ 
    private int _n; 
    private Vector _oldMean, _newMean, 
        _oldVarianceSum, _newVarianceSum, 
        _oldCovarianceSum, _newCovarianceSum; 

    public void Push(Vector x) 
    { 
     _n++; 
     if (_n == 1) 
     { 
      _oldMean = _newMean = x; 
      _oldVarianceSum = new Vector(0, 0, 0); 
      _oldCovarianceSum = new Vector(0, 0, 0); 
     } 
     else 
     { 
      //_newM = _oldM + (x - _oldM)/_n; 
      _newMean = new Vector(
       _oldMean.X + (x.X - _oldMean.X)/_n, 
       _oldMean.Y + (x.Y - _oldMean.Y)/_n, 
       _oldMean.Z + (x.Z - _oldMean.Z)/_n); 

      //_newS = _oldS + (x - _oldM) * (x - _newM); 
      _newVarianceSum = new Vector(
       _oldVarianceSum.X + (x.X - _oldMean.X) * (x.X - _newMean.X), 
       _oldVarianceSum.Y + (x.Y - _oldMean.Y) * (x.Y - _newMean.Y), 
       _oldVarianceSum.Z + (x.Z - _oldMean.Z) * (x.Z - _newMean.Z)); 

      /* .X is X vs Y 
      * .Y is Y vs Z 
      * .Z is Z vs X 
      */ 
      _newCovarianceSum = new Vector(
       _oldCovarianceSum.X + (x.X - _oldMean.X) * (x.Y - _newMean.Y), 
       _oldCovarianceSum.Y + (x.Y - _oldMean.Y) * (x.Z - _newMean.Z), 
       _oldCovarianceSum.Z + (x.Z - _oldMean.Z) * (x.X - _newMean.X)); 

      // set up for next iteration 
      _oldMean = _newMean; 
      _oldVarianceSum = _newVarianceSum; 
     } 
    } 
    public int NumDataValues() 
    { 
     return _n; 
    } 

    public Vector Mean() 
    { 
     return (_n > 0) ? _newMean : new Vector(0, 0, 0); 
    } 

    public Vector Variance() 
    { 
     return _n <= 1 ? new Vector(0, 0, 0) : _newVarianceSum.DivideBy(_n - 1); 
    } 
} 
+0

是的,這可以解決!如果您想移動窗口並刪除離開當前窗口的值,只需從舊的協方差總和中減去對於x,首先將「oldMean」計算爲tempMean.X =((oldMean.x * n) - x)/(n-1),然後使用oldCov.x - =(y - oldMean.y)更新協方差和。 *(x - tempMean.x) ,然後將您的oldMean更新爲tempMean。 – optional

2

的公式很簡單,如果你有MatrixVector班的手:

Vector mean; 
Matrix covariance; 
for (int i = 0; i < points.size(); ++i) { 
    Vector diff = points[i] - mean; 
    mean += diff/(i + 1); 
    covariance += diff * diff.transpose() * i/(i + 1); 
} 

我個人總是喜歡這種風格,而不是雙通道計算。代碼簡短,結果完美無瑕。

MatrixVector可以具有固定的尺寸並且可以容易地爲此編碼。您甚至可以將代碼重寫爲離散浮點計算,並避免計算協方差矩陣的對稱部分。

請注意,在最後一行代碼上有一個向量外部產品。並非所有的矢量庫都能正確解釋它。

0

從鴯鶓的代碼是優雅,但需要一個額外的步驟是正確的:

Vector mean; 
Matrix covariance; 
for (int i = 0; i < points.size(); ++i) { 
    Vector diff = points[i] - mean; 
    mean += diff/(i + 1); 
    covariance += diff * diff.transpose() * i/(i + 1); 
} 

covariance = covariance/(points.size()-1); 

注正規化的協方差的最後步驟。