net machine learning ejemplos accord c# math machine-learning statistics regression

c# - machine - accord net github



RegresiĆ³n no lineal en C# (4)

Estoy buscando una forma de producir una curva no lineal (preferiblemente cuadrática), basada en un conjunto de datos 2D, con fines predictivos. En este momento estoy usando mi propia implementación de mínimos cuadrados ordinarios (OLS) para producir una tendencia lineal, pero mis tendencias son mucho más adecuadas para un modelo de curva. Los datos que estoy analizando son la carga del sistema a lo largo del tiempo.

Aquí está la ecuación que estoy usando para producir mis coeficientes lineales:

He echado un vistazo a Math.NET Numerics y algunas otras librerías, pero proporcionan interpolación en lugar de regresión (que no me sirve), o el código simplemente no funciona de alguna manera.

¿Alguien sabe de cualquier libs de código abierto o muestras de código que puedan producir los coeficientes para tal curva?


El código @ ja72 es bastante bueno. Pero lo Math.NET en la versión actual de Math.NET (MathNet.Iridium no es compatible ahora, como yo entiendo) y optimizo tanto el tamaño del código como el rendimiento (la función Math.Pow no se usa en mi solución debido al bajo rendimiento).

public class PolynomialRegression { private int _order; private Vector<double> _coefs; public PolynomialRegression(DenseVector xData, DenseVector yData, int order) { _order = order; int n = xData.Count; var vandMatrix = new DenseMatrix(xData.Count, order + 1); for (int i = 0; i < n; i++) vandMatrix.SetRow(i, VandermondeRow(xData[i])); // var vandMatrixT = vandMatrix.Transpose(); // 1 variant: //_coefs = (vandMatrixT * vandMatrix).Inverse() * vandMatrixT * yData; // 2 variant: //_coefs = (vandMatrixT * vandMatrix).LU().Solve(vandMatrixT * yData); // 3 variant (most fast I think. Possible LU decomposion also can be replaced with one triangular matrix): _coefs = vandMatrix.TransposeThisAndMultiply(vandMatrix).LU().Solve(TransposeAndMult(vandMatrix, yData)); } private Vector<double> VandermondeRow(double x) { double[] result = new double[_order + 1]; double mult = 1; for (int i = 0; i <= _order; i++) { result[i] = mult; mult *= x; } return new DenseVector(result); } private static DenseVector TransposeAndMult(Matrix m, Vector v) { var result = new DenseVector(m.ColumnCount); for (int j = 0; j < m.RowCount; j++) for (int i = 0; i < m.ColumnCount; i++) result[i] += m[j, i] * v[j]; return result; } public double Calculate(double x) { return VandermondeRow(x) * _coefs; } }

También está disponible en github:gist .



No creo que quieras una regresión no lineal. Incluso si está utilizando una función cuadrática, todavía se llama regresión lineal. Lo que quiere se llama regresión multivariante. Si quiere un cuadrático, simplemente agregue el término ax al cuadrado a sus variables dependientes.


MathNet.Iridium lanzamiento MathNet.Iridium porque es compatible con .NET 3.5 y VS2008. El método se basa en la matriz de Vandermonde . Luego creé una clase para mantener mi regresión polinomial

using MathNet.Numerics.LinearAlgebra; public class PolynomialRegression { Vector x_data, y_data, coef; int order; public PolynomialRegression(Vector x_data, Vector y_data, int order) { if (x_data.Length != y_data.Length) { throw new IndexOutOfRangeException(); } this.x_data = x_data; this.y_data = y_data; this.order = order; int N = x_data.Length; Matrix A = new Matrix(N, order + 1); for (int i = 0; i < N; i++) { A.SetRowVector( VandermondeRow(x_data[i]) , i); } // Least Squares of |y=A(x)*c| // tr(A)*y = tr(A)*A*c // inv(tr(A)*A)*tr(A)*y = c Matrix At = Matrix.Transpose(A); Matrix y2 = new Matrix(y_data, N); coef = (At * A).Solve(At * y2).GetColumnVector(0); } Vector VandermondeRow(double x) { double[] row = new double[order + 1]; for (int i = 0; i <= order; i++) { row[i] = Math.Pow(x, i); } return new Vector(row); } public double Fit(double x) { return Vector.ScalarProduct( VandermondeRow(x) , coef); } public int Order { get { return order; } } public Vector Coefficients { get { return coef; } } public Vector XData { get { return x_data; } } public Vector YData { get { return y_data; } } }

que luego lo uso así:

using MathNet.Numerics.LinearAlgebra; class Program { static void Main(string[] args) { Vector x_data = new Vector(new double[] { 0, 1, 2, 3, 4 }); Vector y_data = new Vector(new double[] { 1.0, 1.4, 1.6, 1.3, 0.9 }); var poly = new PolynomialRegression(x_data, y_data, 2); Console.WriteLine("{0,6}{1,9}", "x", "y"); for (int i = 0; i < 10; i++) { double x = (i * 0.5); double y = poly.Fit(x); Console.WriteLine("{0,6:F2}{1,9:F4}", x, y); } } }

Coeficientes calculados de [1,0.57,-0.15] con la salida:

x y 0.00 1.0000 0.50 1.2475 1.00 1.4200 1.50 1.5175 2.00 1.5400 2.50 1.4875 3.00 1.3600 3.50 1.1575 4.00 0.8800 4.50 0.5275

Que coincide con los resultados quadratic de Wolfram Alpha.

Editar 1 Para obtener el ajuste, intente la siguiente inicialización para x_data y y_data :

Matrix points = new Matrix( new double[,] { { 1, 82.96 }, { 2, 86.23 }, { 3, 87.09 }, { 4, 84.28 }, { 5, 83.69 }, { 6, 89.18 }, { 7, 85.71 }, { 8, 85.05 }, { 9, 85.58 }, { 10, 86.95 }, { 11, 87.95 }, { 12, 89.44 }, { 13, 93.47 } } ); Vector x_data = points.GetColumnVector(0); Vector y_data = points.GetColumnVector(1);

que produce los siguientes coeficientes (desde la potencia más baja hasta la más alta)

Coef=[85.892,-0.5542,0.074990] x y 0.00 85.8920 1.00 85.4127 2.00 85.0835 3.00 84.9043 4.00 84.8750 5.00 84.9957 6.00 85.2664 7.00 85.6871 8.00 86.2577 9.00 86.9783 10.00 87.8490 11.00 88.8695 12.00 90.0401 13.00 91.3607 14.00 92.8312