Last active
July 28, 2020 07:48
-
-
Save KvanTTT/3849678 to your computer and use it in GitHub Desktop.
Implementation of Polynomial regression (http://en.wikipedia.org/wiki/Polynomial_regression) with Math.NET library (http://www.mathdotnet.com/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using MathNet.Numerics.LinearAlgebra.Double; | |
using MathNet.Numerics.LinearAlgebra.Generic; | |
public class PolynomialRegression | |
{ | |
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 PolynomialRegression(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; | |
} | |
} |
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/MathExpressions.NET/tree/master/MathExpressions.NET.Benchmarks.GUI
@KvanTTT Is this code free for commercial use?
@remixie, sure, it's free for commercial use :)
Sorry for the delay. I'm afraid notifications does not work for gists :(
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 :)