2010-05-26 15 views
15

Kennt jemand eine effiziente Methode zur Durchführung multipler linearer Regression in C#, wo die Anzahl der simultanen Gleichungen in den 1000ern liegen kann (mit 3 oder 4 verschiedenen Eingängen). Nach this article auf mehreren linearen Regressions Lesen habe ich versucht, es mit einer Matrixgleichung Umsetzung:Effiziente multiple lineare Regression in 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()); 
} 

jedoch es auf das Ausmaß der 1000 von Gleichungen aufgrund der Matrixinversionsoperation nicht gut skalieren. Ich kann die R-Sprache aufrufen und diese verwenden, aber ich hatte gehofft, dass es eine reine .Net-Lösung geben würde, die auf diese großen Sets skaliert.

Irgendwelche Vorschläge?

EDIT # 1:

Ich habe mit R entschied sich für den Augenblick. Durch die Verwendung von statconn (heruntergeladen here) habe ich festgestellt, dass es sowohl schnell & relativ einfach ist, diese Methode zu verwenden. I.e. Hier ist ein kleines Code-Snippet, es ist wirklich nicht viel Code, um die R statconn-Bibliothek zu benutzen (Anmerkung: das ist nicht der ganze Code!).

_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

Verwendung einer GPU Bibliothek vielleicht? –

+0

Wollen Sie die Matrix-Operationen schneller laufen lassen? Ich denke nicht, dass dies der beste Ansatz sein wird. Ich denke, der beste Ansatz wird darin bestehen, einen nicht-matrixartigen Ansatz zu verwenden (oder etwas, das die Umkehrung vermeidet). – mike

+0

Ich hatte Erfolg mit http://www.codeproject.com/KB/recipes/LinReg.aspx Sehr einfach zu bedienen und Open Source! – BoroDrummer

Antwort

3

Ich habe vor kurzem die ALGLIB Bibliothek gefunden, die, obwohl nicht viel Dokumentation, einige sehr nützliche Funktionen wie die linear regression hat, die eines der Dinge ist, nach denen ich suchte.

Beispielcode (das ist alt und nicht verifiziert, nur ein grundlegendes Beispiel dafür, wie ich es benutzt habe). Ich benutzte die lineare Regression auf Zeitreihe mit 3 Einträgen (genannt 3min/2min/1min) und dann den Endwert (Final).

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

Netter Vorschlag. Irgendwelche Codebeispiele, die Sie bereit wären zu posten? – Mario

+0

Siehe bearbeiten für einige Beispielcode, ich hoffe, es funktioniert immer noch (Sie benötigen einen Verweis auf Alglib) – mike

+0

Nizza. Wie würden Sie eine unbekannte konstante Variable in diese Stichprobe einbauen? – Oriental

1

Versuchen Meta.Numerics:

Meta.Numerics ist eine Bibliothek für fortgeschrittene wissenschaftliche Berechnungen in .NET Framework. Es kann von C#, Visual Basic, F # oder jeder anderen .NET-Programmiersprache verwendet werden. Die Meta.Numerics-Bibliothek ist vollständig objektorientiert und auf die Geschwindigkeit der Implementierung und Ausführung optimiert.

Um eine Matrix zu füllen, siehe ein Beispiel der ColumnVector Constructor (IList<Double>). Es kann eine ColumnVector aus vielen geordneten Sammlungen von Realen, einschließlich double [] und List erstellen.

+0

Danke, ich hatte diese Bibliothek noch nie gesehen. Sieht gut aus, leidet aber immer noch unter den gleichen Problemen beim Lösen der Gleichungen mit Matrizen. Ich denke, ich brauche einen anderen Ansatz. – mike

2

Die Größe der zu invertierenden Matrix wächst NICHT mit der Anzahl der simultanen Gleichungen (Samples). x.Transpose() * x ist eine quadratische Matrix, wobei die Dimension die Anzahl der unabhängigen Variablen ist.

+0

Interessanter Punkt, ich frage mich, warum meine Leistung so sehr verschlechtert? Ich hatte ungefähr 6000 Proben in meinem Set. Ich werde das weiter untersuchen müssen. – mike

+0

Ich schätze, Ihre Leistung verschlechtert sich, weil x.Transpose() * x bei größeren Matrizen mehr Zeit benötigt. Ich habe irgendwo eine Bibliothek, die für Millionen von Datenpunkten funktioniert ... Ich werde versuchen, sie auszugraben, wenn Sie interessiert sind. Ich habe dieses Problem vor etwa zwanzig Jahren (ja, ich bin alt) und habe eine kluge mathematische Lösung gefunden :-) –

+1

Sie sollten Gradienten-Abstieg-Methode verwenden, wenn Sie eine bessere Skalierung wünschen. –

1

Ich kann vorschlagen, FinMath zu verwenden. Es ist extrem-optimierte .net numerische Berechnungsbibliothek. Es verwendet Intel Math Kernel Library für komplexe Berechnungen wie lineare Regression oder Matrixinvertierung, aber die meisten Klassen haben sehr einfache zugängliche Schnittstellen. Und natürlich ist es auf große Datenmengen skalierbar. mrnye das Beispiel wird so sein aussehen:

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

ich vor kurzem kam über MathNet-Numerics - die unter MIT-Lizenz zur Verfügung.

Es behauptet, schnellere Alternativen für den gemeinsamen (X.Transpose() * X).Inverse() * (X.Transpose() * y) Prozess bereitzustellen.

Hier sind einige Optimierungen von this article. Zuerst ein Wesen:

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

Oder könnten Sie verwenden Cholesky decomposition:

Verwandte Themen