如何在 mathdotnet 中使用 Nelder Meade Simplex 算法进行函数最大化

How to use the Nelder Meade Simplex algorithm in mathdotnet for function maximization

在我的 C# 程序中,我有一个数据集,其中每个数据点包括:

当强度较低时,正确率较低。当强度高时,正确率高。函数图为S型曲线,percentageCorrect在低端和高端达到渐近线。

我正在尝试找到阈值强度,其中 percentageCorrect 位于两端渐近线(S 形曲线的中心)的中间位置

我理解这是一个函数最大化问题,可以通过 Nelder Meade Simplex 算法解决。

我正在尝试使用 Nelder Meade Simplex algorithm in mathdotnet and its IObjectiveFunction 参数解决我的问题。

但是,我无法理解 NedlerMeadeSimplex class FindMinimum method and the IObjectiveFunction EvaluateAt 方法的 API。

我刚接触数值分析,这是这道题的先决条件。

具体问题是:

感谢您对此的任何指导。

初始猜测是对模型参数的猜测。

我一直使用不需要输入 initialPertubation 参数的表格,所以我无法在这方面为您提供帮助。

objective 函数是您要尽量减少的。例如,对于最小二乘法拟合,它将计算参数中给定点处的面积平方和。像这样:

private double SumSqError(Vector<double> v)
{
    double err = 0;
    for (int i = 0; i < 100; i++)
    {
        double y_val = v[0] + v[1] * Math.Exp(v[2] * x[i]);
        err += Math.Pow(y_val - y[i], 2);
    }
    return err;
}

您不必提供积分。该算法在搜索最小值时一遍又一遍地执行此操作。注意子程序访问向量 x.

以下是将函数拟合到随机数据的测试程序的代码:

private void btnMinFit_Click(object sender, EventArgs e)
{
    Random RanGen = new Random();
    x = new double[100];
    y = new double[100];

    // fit exponential expression with three parameters
    double a = 5.0;
    double b = 0.5;
    double c = 0.05;
    // create data set
    for (int i = 0; i < 100; i++) x[i] = 10 + Convert.ToDouble(i) * 90.0 / 99.0; // values span 10 to 100
    for (int i = 0; i < 100; i++)
    {
        double y_val = a + b * Math.Exp(c * x[i]);
        y[i] = y_val + 0.1 * RanGen.NextDouble() * y_val;  // add error term scaled to y-value
    }

    // var fphv = new Func<double, double, double, double>((x, A, B) => A * x + B * x + A * B * x * x); extraneous test


    var f1 = new Func<Vector<double>, double>(x => LogEval(x));
    var obj = ObjectiveFunction.Value(f1);
    var solver = new NelderMeadSimplex(1e-5, maximumIterations: 10000);
    var initialGuess = new DenseVector(new[] { 3.0, 6.0, 0.6 });

    var result = solver.FindMinimum(obj, initialGuess);


    Console.WriteLine(result.MinimizingPoint.ToString());

}