Search code examples
c#curve-fittingnumerical-methodsnon-linear-regressionmathnet-numerics

How can I return A and b from this exponential fit function?


using System;
using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Optimization;

namespace NonLinearRegressionExample
{
    public class NonlinearRegressionCurveFitting
    {
        public static (List<double>, List<double>, List<double>) FitCurve(List<double> xData, List<double> yData)
        {
            // example data
            var xDataDense = new DenseVector(xData.ToArray());
            var yDataDense = new DenseVector(yData.ToArray());

            Vector<double> Model(Vector<double> parameters, Vector<double> x)
            {
                var y = CreateVector.Dense<double>(x.Count);
                for (int i = 0; i < x.Count; i++)
                {
                    y[i] = parameters[0] * Math.Exp(parameters[1] * x[i]);
                }
                return y;
            }

            var start = new DenseVector(new double[] { 1.0, 0.1 });
            var objective = ObjectiveFunction.NonlinearModel(Model, xDataDense, yDataDense);
            var solver = new LevenbergMarquardtMinimizer(maximumIterations: 10000);
            var result = solver.FindMinimum(objective, start);

            Vector<double> points = result.MinimizedValues;

            Vector<double> minimizing = result.MinimizingPoint;

            return (xData, new List<double>(points.ToArray()), new List<double>(minimizing.ToArray()));
        }
    }
}

Driver program:

var fittedCurve = NonlinearRegressionCurveFitting.FitCurve(xData, yData);

            List<double> points = fittedCurve.Item2;
            List<double> result = fittedCurve.Item3;

            ///Output the results
            if (result.Count == 2)
            {
                DataPlotter plotter = new DataPlotter();
                //plotter.ZoomXaxis(0, 10);
                plotter.AddCurve("original",
                    new List<double>(xData.ToArray()),
                    new List<double>(yData.ToArray()),
                    IsSymbolVisible: false, color: Color.Red);
                plotter.AddCurve("fitted",
                    new List<double>(xData.ToArray()),
                    new List<double>(points.ToArray()),
                    IsSymbolVisible: false,
                    color: Color.Green);
                plotter.AddPoint("Point", result[0], result[1], Color.BlueViolet);
                plotter.ShowDialog();
            }

The above source code fits an exponential curve using nonlinear regression.

However, how can I return the best A and b values from this C# function for the exponential formula

y = A * exp(-x * b)

?

.

This function is returning MinimizingPoint which seems to be the starting point of the x-axis.

enter image description here

.


Solution

  • The values returned by MinimizingPoint are the parameters to the fitted function. In your case of y = A * exp(b * x), the first parameter is A = 0.84275567216928349 and the second is b = -0.0071155733183345549.

    If you want to find a value for any given x, then calculate:

    y = A * exp(b * x)

    or with the concrete parameters:

    y = 0.84275567216928349 * exp(-0.0071155733183345549 * x)

    It makes no sense to plot these parameters given as result[0] and result[1] in the FitCurve method with

    plotter.AddPoint("Point", result[0], result[1], Color.BlueViolet);

    since they do not represent a point in the graph.