我以前使用 Math.NET Numerics 库的Fit.Polynomial方法来拟合一组数据的三次多项式,这些数据可以建模为一个参数的函数y=f(x)
。
现在我想类似地找到一个适合数据的 2 或 3 阶多项式,该数据可以根据多个参数建模为函数y=f(x1, x2, x3, x4)
。
Math.NET 中是否已经有一个可以计算该多项式的内置函数?
如果没有,您是否看到我可以如何操纵我的数据以将其提交给 Fit.Polynomial?
我以前使用 Math.NET Numerics 库的Fit.Polynomial方法来拟合一组数据的三次多项式,这些数据可以建模为一个参数的函数y=f(x)
。
现在我想类似地找到一个适合数据的 2 或 3 阶多项式,该数据可以根据多个参数建模为函数y=f(x1, x2, x3, x4)
。
Math.NET 中是否已经有一个可以计算该多项式的内置函数?
如果没有,您是否看到我可以如何操纵我的数据以将其提交给 Fit.Polynomial?
该类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();
}
Fit.MultiDim
另一方面,默认情况下使用正规方程,这比 QR 分解要快得多,但在数值上的鲁棒性较差。这就是为什么您发现使用此方法会降低准确性。
public static double[] MultiDim(double[][] x, double[] y)
{
return MultipleRegression.NormalEquations(x, y);
}
在您的情况下,我会尝试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();
(使用 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();
}
请注意,线性模型中的x也可以是向量x=[x1 x2 ⋯ xk]并且任意函数fi(x)可以接受向量而不是标量。
这几乎是您想要的东西。