wip*_*wip 15 c# curve-fitting math.net
我以前使用Math.NET Numerics库的Fit.Polynomial方法在一组数据上拟合三次多项式,这些数据可以作为一个参数的函数建模y=f(x).
现在我想类似地找到一个2或3阶多项式,它适合可以根据多个参数建模为函数的数据y=f(x1, x2, x3, x4).
Math.NET中是否已有可以计算多项式的内置函数?
如果没有,你看到我如何操纵我的数据,以便将其提交给Fit.Polynomial?
Chr*_*egg 14
本Fit类只是一个门面是在大多数情况下不够好,但你总是可以直接使用算法来得到你所需要的东西.
Fit.Polynomial:具有高阶的多项式曲线拟合在数值上有点问题,因此已经开发了用于在最后调整/细化参数的专门算法和例程.但是,Math.NET Numerics现在只使用QR分解(尽管计划在某些时候替换实现):
public static double[] Polynomial(double[] x, double[] y, int order)
{
var design = Matrix<double>.Build.Dense(x.Length, order + 1, (i, j) => Math.Pow(x[i], j));
return MultipleRegression.QR(design, Vector<double>.Build.Dense(y)).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
Fit.MultiDim另一方面,默认情况下使用正规方程,这比QR分解要快得多但数值上不够稳健.这就是为什么你看到这种方法降低了准确性的原因.
public static double[] MultiDim(double[][] x, double[] y)
{
return MultipleRegression.NormalEquations(x, y);
}
Run Code Online (Sandbox Code Playgroud)
在你的情况下,我会尝试MultipleRegression直接使用该类,使用QR(如果足够好)或Svd(如果需要更强大;更慢(考虑使用本机提供程序,如果太慢)):
var x1 = new double[] { ... };
var x2 = new double[] { ... };
var y = new double[] { ... };
var design = Matrix<double>.Build.DenseOfRowArrays(
Generate.Map2(x1,x2,(x1, x2) => new double[] { x1*x1, x1, x2*x2, x2, 1d }));
double[] p = MultipleRegression.QR(design, Vector<double>.Build.Dense(y)).ToArray();
Run Code Online (Sandbox Code Playgroud)
(使用Math.NET Numerics v3.0.0-alpha7)
RosettaCode为多项式回归提出了这个解决方案(使用Math.Net):
public static double[] Polyfit(double[] x, double[] y, int degree)
{
// Vandermonde matrix
var v = new DenseMatrix(x.Length, degree + 1);
for (int i = 0; i < v.RowCount; i++)
for (int j = 0; j <= degree; j++) v[i, j] = Math.Pow(x[i], j);
var yv = new DenseVector(y).ToColumnMatrix();
QR<double> qr = v.QR();
// Math.Net doesn't have an "economy" QR, so:
// cut R short to square upper triangle, then recompute Q
var r = qr.R.SubMatrix(0, degree + 1, 0, degree + 1);
var q = v.Multiply(r.Inverse());
var p = r.Inverse().Multiply(q.TransposeThisAndMultiply(yv));
return p.Column(0).ToArray();
}
Run Code Online (Sandbox Code Playgroud)