2010-05-26 306 views
15

沒有人知道的有效的方法來做到多元線性迴歸在C#,其中的聯立方程式的數目可以是在1000的(具有3個或4個不同的輸入)。上的多個線性迴歸讀取this article後我試圖與一個矩陣方程執行它:高效多元線性迴歸在C#/ .NET

Matrix y = new Matrix(
    new double[,]{{745}, 
        {895}, 
        {442}, 
        {440}, 
        {1598}}); 

Matrix x = new Matrix(
    new double[,]{{1, 36, 66}, 
       {1, 37, 68}, 
       {1, 47, 64}, 
       {1, 32, 53}, 
       {1, 1, 101}}); 

Matrix b = (x.Transpose() * x).Inverse() * x.Transpose() * y; 

for (int i = 0; i < b.Rows; i++) 
{ 
    Trace.WriteLine("INFO: " + b[i, 0].ToDouble()); 
} 

然而,它不能很好地擴展到1000的方程由於矩陣求逆操作的規模。我可以調用R語言並使用它,但是我希望有一個純粹的.Net解決方案可以擴展到這些大集合。

有什麼建議嗎?

EDIT#1:

我已經,使用R暫時解決。通過使用statconn(已下載here)我發現它是快速的&比較容易使用這種方法。即這是一個小的代碼片段,它使用R statconn庫實際上並沒有太多的代碼(注意:這不是所有的代碼!)。

_StatConn.EvaluateNoReturn(string.Format("output <- lm({0})", equation)); 
object intercept = _StatConn.Evaluate("coefficients(output)['(Intercept)']"); 
parameters[0] = (double)intercept; 
for (int i = 0; i < xColCount; i++) 
{ 
    object parameter = _StatConn.Evaluate(string.Format("coefficients(output)['x{0}']", i)); 
    parameters[i + 1] = (double)parameter; 
} 
+0

使用GPU庫吧? – 2010-05-26 05:52:23

+0

你的意思是讓矩陣運算更快運行嗎?我認爲這不是最好的方法,我認爲最好的方法是使用非矩陣式方法(或避免相反的方法)。 – mike 2010-05-26 05:59:38

+0

我已經成功了http://www.codeproject.com/KB/recipes/LinReg.aspx非常容易使用和開源! – BoroDrummer 2011-10-21 14:10:50

回答

3

爲了記錄,我最近發現了ALGLIB庫,它雖然沒有太多文檔,卻有一些非常有用的功能,如linear regression這是我之後的事情之一。

示例代碼(這是舊的,未經證實的,我是如何使用它的只是一個基本的例子)。我在時間序列上使用3個條目(稱爲3分鐘/ 2分鐘/ 1分鐘)和最終值(最終)進行線性迴歸。

public void Foo(List<Sample> samples) 
{ 
    int nAttributes = 3; // 3min, 2min, 1min 
    int nSamples = samples.Count; 
    double[,] tsData = new double[nSamples, nAttributes]; 
    double[] resultData = new double[nSamples]; 

    for (int i = 0; i < samples.Count; i++) 
    { 
    tsData[i, 0] = samples[i].Tminus1min; 
    tsData[i, 1] = samples[i].Tminus2min; 
    tsData[i, 2] = samples[i].Tminus3min; 

    resultData[i] = samples[i].Final; 
    } 

    double[] weights = null; 
    int fitResult = 0; 
    alglib.lsfit.lsfitreport rep = new alglib.lsfit.lsfitreport(); 
    alglib.lsfit.lsfitlinear(resultData, tsData, nSamples, nAttributes, ref fitResult, ref weights, rep); 

    Dictionary<string, double> labelsAndWeights = new Dictionary<string, double>(); 
    labelsAndWeights.Add("1min", weights[0]); 
    labelsAndWeights.Add("2min", weights[1]); 
    labelsAndWeights.Add("3min", weights[2]); 
} 
+0

不錯的建議。任何你願意發佈的代碼示例? – Mario 2011-01-05 16:18:43

+0

請參閱編輯一些示例代碼,我希望它仍然有效(您將需要對alglib的引用) – mike 2011-01-06 08:06:22

+0

很好。你如何將一個未知的常量變量加入到這個示例中? – Oriental 2015-09-20 10:17:48

1

嘗試Meta.Numerics

Meta.Numerics是在.NET Framework先進的科學計算庫。它可以從C#,Visual Basic,F#或任何其他.NET編程語言中使用。 Meta.Numerics庫完全面向對象,針對實現和執行的速度進行了優化。

要填充矩陣,請參見ColumnVector Constructor (IList<Double>)的示例。它可以從許多有序的實數集合構造一個ColumnVector,包括double []和List。

+0

謝謝,我以前沒有見過那個圖書館。看起來不錯,但仍然遇到與用矩陣求解方程相同的問題。我想我需要一種不同的方法。 – mike 2010-05-26 12:49:55

2

矩陣的大小被反轉不與聯立方程式(樣本)的數目增加。 x.Transpose()* x 是一個方形矩陣,其中的維數是自變量的數量。

+0

有趣的一點,我想知道爲什麼我的表現會如此惡化?我有約6000個樣本。我將不得不進一步調查。 – mike 2010-05-26 12:51:39

+0

我猜你的性能會下降,因爲x.Transpose()* x需要更多時間處理更大的矩陣。我有一個圖書館適合數百萬個數據點......如果你有興趣,我會盡力挖掘它。大約二十年前我遇到過這個問題(是的,我很老),發現了一個聰明的數學解決方案:-) – 2010-05-27 22:51:25

+1

如果你想要更好的縮放,你應該使用梯度下降法。 – 2013-11-02 10:38:59

1

我可以建議使用FinMath。它是極其優化的.net數值計算庫。它使用英特爾數學核心函數庫來執行復雜的計算,如線性迴歸或矩陣求逆,但大多數類具有非常簡單的平易近人的界面。當然,它可以擴展到大量的數據。 mrnye的例子將是這個樣子:

using FinMath.LeastSquares; 
using FinMath.LinearAlgebra; 

Vector y = new Vector(new double[]{745, 
    895, 
    442, 
    440, 
    1598}); 

Matrix X = new Matrix(new double[,]{ 
    {1, 36, 66}, 
    {1, 37, 68}, 
    {1, 47, 64}, 
    {1, 32, 53}, 
    {1, 1, 101}}); 

Vector b = OrdinaryLS.FitOLS(X, y); 

Console.WriteLine(b); 
0

我最近碰到MathNet-Numerics來了 - 這是在MIT許可使用。

它聲稱提供共同(X.Transpose() * X).Inverse() * (X.Transpose() * y)過程更快的替代品。

以下是來自this article的一些優化。第一個是:

X.TransposeThisAndMultiply(X).Inverse() * X.TransposeThisAndMultiply(y) 

或者,你可以使用Cholesky decomposition