2010-05-26 26 views
15

Qualcuno sa di un modo efficiente per fare regressione lineare multipla in C#, dove il numero di equazioni simultanee può essere negli anni 1000 (con 3 o 4 ingressi diversi). Dopo aver letto this article sulla regressione lineare multipla Ho provato a realizzarlo con un equazione matriciale:Efficiente regressione lineare multipla 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()); 
} 

Tuttavia non si adatta bene alla scala di 1000 di equazioni dovuti all'operazione inversione di matrice. Posso chiamare il linguaggio R e usarlo, tuttavia speravo che ci sarebbe stata una soluzione .Net pura che si sarebbe estesa a questi grandi set.

Qualche suggerimento?

EDIT # 1:

ho risolto utilizzando R per il momento. Utilizzando statconn (scaricato here) ho trovato che sia veloce sia & relativamente facile da usare questo metodo. Cioè qui c'è un piccolo frammento di codice, in realtà non c'è molto codice per usare la libreria statconn R (nota: questo non è tutto il codice!).

_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

utilizzare una libreria GPU forse? –

+0

Intendi rendere le operazioni della matrice più veloci? Non penso che questo sia l'approccio migliore, penso che l'approccio migliore sarà quello di utilizzare un approccio di stile non matrice (o qualcosa che eviti l'inverso). – mike

+0

Ho avuto successo con http://www.codeproject.com/KB/recipes/LinReg.aspx Molto facile da usare e open source! – BoroDrummer

risposta

3

Per la cronaca, di recente ho trovato la biblioteca ALGLIB che, pur non avendo molta documentazione, ha alcune funzioni molto utili come la linear regression, che è una delle cose che mi è stato dopo.

Codice di esempio (questo è vecchio e non verificato, solo un esempio di base di come lo stavo usando). Stavo usando la regressione lineare su serie temporali con 3 voci (chiamate 3min/2min/1min) e poi il valore finale (Finale).

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

Bel suggerimento. Qualche esempio di codice che vorresti pubblicare? – Mario

+0

Vedere la modifica per qualche codice di esempio, spero che funzioni ancora (avrete bisogno di un riferimento a alglib) – mike

+0

Nice. Come incorporeresti una variabile costante sconosciuta in questo campione? – Oriental

1

Prova Meta.Numerics:

Meta.Numerics è una libreria per il calcolo scientifico avanzato in .NET Framework. Può essere utilizzato da C#, Visual Basic, F # o qualsiasi altro linguaggio di programmazione .NET. La libreria Meta.Numerics è completamente orientata agli oggetti e ottimizzata per la velocità di implementazione ed esecuzione.

Per popolare una matrice, vedere un esempio di ColumnVector Constructor (IList<Double>). Può costruire uno ColumnVector da molte raccolte ordinate di real, inclusi double [] e List.

+0

Grazie, non avevo mai visto quella libreria prima. Sembra buono, ma presenta ancora gli stessi problemi di risoluzione delle equazioni con le matrici. Penso di aver bisogno di un approccio diverso. – mike

2

La dimensione della matrice invertita NON aumenta con il numero di equazioni simultanee (campioni). x.Traspose() * x è una matrice quadrata in cui la dimensione è il numero di variabili indipendenti.

+0

Punto interessante, mi chiedo perché la mia performance degrada così tanto allora? Ho avuto circa 6000 campioni nel mio set. Dovrò indagare ulteriormente. – mike

+0

Direi che le prestazioni si degradano perché x.Transpose() * x richiede più tempo con matrici più grandi. Ho una libreria da qualche parte che funziona per milioni di punti dati ... cercherò di approfondire se sei interessato. Ho affrontato questo problema circa venti anni fa (sì, sono vecchio) e ho trovato una soluzione matematica intelligente :-) –

+1

Dovresti utilizzare il metodo di discesa del gradiente se vuoi un ridimensionamento migliore. –

1

Posso suggerire di utilizzare FinMath. È una libreria di calcolo numerico .net estremamente ottimizzata. Utilizza la libreria del kernel Math di Intel per eseguire calcoli complessi come la regressione lineare o la matrice inversa, ma la maggior parte delle classi ha interfacce molto semplici e accessibili. E, naturalmente, è scalabile per un ampio set di dati. esempio di mrnye sarà simile a questa:

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

ho recentemente imbattuto in MathNet-Numerics - che è disponibile sotto licenza MIT.

Si afferma di fornire alternative più veloci per il processo comune (X.Transpose() * X).Inverse() * (X.Transpose() * y).

Ecco alcune ottimizzazioni da this article. In primo luogo un essere:

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

Oppure, si potrebbe utilizzare Cholesky decomposition:

Problemi correlati