我想使用 C# 拟合一条具有 6 个参数的曲线。为此,我使用
MathNet.Numerics.Fit.Curve
。但由于它最多只支持 5 个参数,所以我尝试将函数的一个参数设置为猜测值并拟合其他参数。
为了拟合之前固定的值,我设置了另一个已拟合的值作为固定值并再次拟合。这个概念对于大多数数据都适用,但有时仍然会失败。
我想知道是否有人知道如何实现 6 个参数的
MathNet.Numerics.Fit.Curve
,因为我认为这可以解决我的问题。
谢谢
如果您想测试
MathNet.Fit
的五个以上参数
模型,我们可以创建 Fit.Curve
的版本
它采用具有动态数量参数的函数。这意味着
该模型将是类型的函数
Func<Vector<double>, double, double>
- 第一个
参数,是参数向量,第二个参数是
x
坐标的当前值。
Fit.Curve
实现的源代码;
它们基于 FindMinimum.OfFunction
的相应版本;
幸运的是,虽然没有动态参数数量版本
Fit.Curve
中,有 有一个
对于FindMinimum.OfFunctions
。使用此版本和一般方法
现有的 Fit.Curve
版本我们的函数可以写成
简单如:
static Vector<double> FitCurve2(double[] x, double[] y, Func<Vector<double>, double, double> f, Vector<double> initialGuess, double tolerance = 1e-8, int maxIterations = 1000) {
return FindMinimum.OfFunction((p) => Distance.Euclidean(Generate.Map(x, t => f(p, t)), y), initialGuess, tolerance, maxIterations);
}
用于测试您的特定案例的示例模型和数据将是最有帮助的,并且仍然可以帮助改进问题和答案。
不过,现在这里有一个使用此函数来拟合 6 参数曲线的示例。这里的模型函数是
F1
,一个带参数的有理函数
q0, ..., q5
。我从这些参数的一组已知值开始
q0 = 1.596, q1 = -1.277, .....
(所有这些都来自我的应用程序,
出于本次测试的目的,将它们视为随机的)并生成
与这些参数匹配的一组 x
、y0
数组。然后添加一些
随机噪声到 y0
并拟合所得的 x
、y
模型
功能。如果一切顺利,我们将检索一些参数 q0
、...
、q5
接近原始的,我们通常这样做。
using MathNet.Numerics;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
const int n = 200;
const double q0 = 1.596, q1 = -1.277, q2 = -4.33, q3 = 0.5, q4 = 1, q5 = 1.4; // "clear" parameters
var x = Generate.LinearSpaced(n, -3, 3);
var rnd = new double[n];
Normal.Samples(rnd, 0.0, 1.0);
var y0 = Generate.Map(x, xi=>F1(q0, q1, q2, q3, q4, q5, xi));
var y = Generate.Map2(y0, rnd, (yi, ri) => yi + ri * 0.2); // y0 + noise
Vector<double> initialGuess = DenseVector.OfArray([1.0, 1.0, 1.0, 1.0, 1.0, 1.0]);
var q = FitCurve2(x, y, (q, x) => F1(q[0], q[1], q[2], q[3], q[4], q[5], x),
initialGuess, 1e-9, 10000);
Console.WriteLine($"q0 = {q[0]} q1 = {q[1]} q2 = {q[2]} q3 = {q[3]} q4 = {q[4]} q5 = {q[5]}");
// parameters impacted by noise, still close the "clear" ones.
double F1(double q0, double q1, double q2, double q3, double q4, double q5, double x)
{
return (q0 + q1 * x + q2 * Math.Pow(x, 2) + q3 * Math.Pow(x, 3) + q4 * Math.Pow(x, 4))/(x*x + q5);
}
static Vector<double> FitCurve2(double[] x, double[] y, Func<Vector<double>, double, double> f, Vector<double> initialGuess, double tolerance = 1e-8, int maxIterations = 1000) {
return FindMinimum.OfFunction((p) => Distance.Euclidean(Generate.Map(x, t => f(p, t)), y), initialGuess, tolerance, maxIterations);
}
注意,可以验证如果使用少于6个参数 计算结果与计算结果相同
Fit.Curve
的静态参数数量版本(当然,如果
所有其他参数,例如初始猜测、容差或最大迭代次数
平等)。
话虽这么说,但应该注意的是
MathNet
并不是唯一的
可以在 C# 和 dotNet 中进行非线性曲线拟合的库。的
当然,stackoverflow不允许
寻求图书馆的建议,
我也没有资格给予一些。只考虑可能发生的情况
如果曲线拟合没有按预期结果,问题就来了
可能并不总是你的模型,但它也可以是算法
由库使用,在这种情况下,也可以测试其他库。