2010-05-26 57 views
15

¿Alguien sabe de una manera eficiente de hacer regresiones lineales múltiples en C#, donde el número de ecuaciones simultáneas puede estar en los 1000 (con 3 o 4 entradas diferentes). Después de leer this article de regresión lineal múltiple Probé implementarlo con una ecuación matricial:Regresión Lineal Múltiple Eficiente en 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()); 
} 

Sin embargo, no se adapta bien a la escala de 1000 de ecuaciones debido a la operación de matriz de inversión. Puedo llamar al lenguaje R y usar eso, sin embargo, esperaba que hubiera una solución .Net pura que se escalaría a estos grandes conjuntos.

¿Alguna sugerencia?

editar # 1:

que se han asentado usando R por el momento. Al usar statconn (descargado here) he encontrado que es rápido & relativamente fácil de usar este método. Es decir. Aquí hay un pequeño fragmento de código, realmente no es mucho código para usar la biblioteca R statconn (nota: ¡esto no es todo el código!).

_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

uso de una biblioteca GPU tal vez? –

+0

¿Quiere hacer que las operaciones matriciales se ejecuten más rápido? No creo que sea el mejor enfoque, creo que el mejor enfoque será utilizar un enfoque de estilo no matricial (o algo que evite lo contrario). – mike

+0

Tuve éxito con http://www.codeproject.com/KB/recipes/LinReg.aspx ¡Muy fácil de usar y de código abierto! – BoroDrummer

Respuesta

3

Para el registro, recientemente encontré la biblioteca ALGLIB que, aunque no tiene mucha documentación, tiene algunas funciones muy útiles como el linear regression que es una de las cosas que estaba buscando.

Código de muestra (esto es antiguo y no verificado, solo un ejemplo básico de cómo lo estaba usando). Estaba usando la regresión lineal en series de tiempo con 3 entradas (llamadas 3min/2min/1min) y luego el valor final (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

Sugerencia agradable. ¿Algún ejemplo de código que estaría dispuesto a publicar? – Mario

+0

Consulte la edición de algún código de muestra, espero que todavía funcione (necesitará una referencia a alglib) – mike

+0

Agradable. ¿Cómo incorporaría una variable constante desconocida en esta muestra? – Oriental

1

Trate Meta.Numerics:

Meta.Numerics es una biblioteca para la computación científica avanzada en .NET Framework. Se puede usar desde C#, Visual Basic, F # o cualquier otro lenguaje de programación .NET. La biblioteca Meta.Numerics está completamente orientada a objetos y optimizada para la velocidad de implementación y ejecución.

Para completar una matriz, consulte un ejemplo de ColumnVector Constructor (IList<Double>). Puede construir un ColumnVector de muchas colecciones ordenadas de reales, incluidos double [] y List.

+0

Gracias, no había visto esa biblioteca antes. Se ve bien, pero aún sufre los mismos problemas de resolver las ecuaciones con matrices. Creo que necesito un enfoque diferente. – mike

2

El tamaño de la matriz que se está invirtiendo NO aumenta con el número de ecuaciones simultáneas (muestras). x.Transpose() * x es una matriz cuadrada donde la dimensión es el número de variables independientes.

+0

Un punto interesante, me pregunto por qué mi rendimiento se degrada tanto entonces? Tenía alrededor de 6000 muestras en mi conjunto. Tendré que investigar esto más a fondo. – mike

+0

Supongo que su rendimiento se degrada porque x.Transpose() * x lleva más tiempo con las matrices más grandes. Tengo una biblioteca en alguna parte que funciona para millones de puntos de datos ... Intentaré desenterrarla si está interesado. Me enfrenté a este problema hace unos veinte años (sí, soy viejo) y encontré una solución matemática inteligente :-) –

+1

Debe usar el método de descenso gradual si desea una mejor escala. –

1

puedo sugerir a utilizar FinMath. Es una biblioteca de computación numérica .net extremadamente optimizada. Utiliza Intel Math Kernel Library para realizar cálculos complejos como regresión lineal o matriz inversa, pero la mayoría de las clases tienen interfaces accesibles muy simples. Y, por supuesto, es escalable para una gran cantidad de datos. ejemplo de mrnye será el siguiente aspecto:

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

Recientemente me encontré con MathNet-Numerics - que está disponible bajo la licencia MIT.

Afirma proporcionar alternativas más rápidas para el proceso común (X.Transpose() * X).Inverse() * (X.Transpose() * y).

Aquí hay algunas optimizaciones de this article. Primero un solo ser:

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

O bien, puede utilizar Cholesky decomposition:

Cuestiones relacionadas