public
Last active

Implementation of Polynominal regression (http://en.wikipedia.org/wiki/Polynomial_regression) with Math.NET library (http://www.mathdotnet.com/)

  • Download Gist
PolynominalRegression.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Generic;
 
public class PolynominalRegression
{
private int _order;
private Vector<double> _coefs;
 
/// <summary>
/// Calculates polynom regression for xData = [x1, x2, ... , xn] and yData = [y1, y2, ... , yn].
/// </summary>
/// <param name="order">Order of output polynom.</param>
public PolynominalRegression(DenseVector xData, DenseVector yData, int order)
{
_order = order;
 
var vandMatrix = new DenseMatrix(xData.Count, order + 1);
for (int i = 0; i < xData.Count; i++)
{
double mult = 1;
for (int j = 0; j < order + 1; j++)
{
vandMatrix[i, j] = mult;
mult *= 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));
}
 
/// <summary>
/// Calculates polynom regression for xData = [0, 1, ... , n] and yData = [y1, y2, ... , yn].
/// </summary>
/// <param name="order">Order of output polynom.</param>
public PolynominalRegression(DenseVector yData, int order)
{
_order = order;
 
var vandMatrix = new DenseMatrix(yData.Count, order + 1);
for (int i = 0; i < yData.Count; i++)
{
double mult = 1;
for (int j = 0; j < order + 1; j++)
{
vandMatrix[i, j] = mult;
mult *= i;
}
}
 
_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;
}
}

Hi! I can't seem to get this working, I'm getting NaN's only. What value should I provide for the order parameter?

Fixed: Used DenseVector.OfEnumerable(IEnumerable) to create the vectors :)

Order parameter should be greater or equal to 0. If you will use 0 for order parameter, you'll get parallel to abscissa line. Parameter of 1 will give you custom line, 2 will give you parabola etc. Example of this code using you can explore here: https://github.com/KvanTTT/Math-Functions/tree/master/MathFunctions.Benchmarks.GUI

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.