I am trying to use MathNet library to compute curve fitting based on nonlinear regression.
using System;
using System.Linq;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Optimization;
class NonLinearRegressionExample
{
static void Main()
{
// Example data points
double[] xdata = new double[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
double[] ydata = new double[] { 1.0, 2.7, 5.8, 6.6, 7.5, 9.9 };
// Define the model function
Func<Vector<double>, double, double> modelFunc = (parameters, x) =>
parameters[0] * Math.Exp(parameters[1] * x);
// Objective function: sum of squared residuals
Func<Vector<double>, double> objectiveFunction = (parameters) =>
{
double sumOfSquares = 0;
for (int i = 0; i < xdata.Length; i++)
{
double error = ydata[i] - modelFunc(parameters, xdata[i]);
sumOfSquares += error * error;
}
return sumOfSquares;
};
// Gradient of the objective function (if it's not provided, you'll need to implement this)
Func<Vector<double>, Vector<double>> gradientFunction = (parameters) =>
{
// You'll need to implement the gradient here
throw new NotImplementedException("Gradient function is not implemented.");
};
// Initial guess for parameters a and b
var initialGuess = Vector<double>.Build.DenseOfArray(new double[] { 1.0, 0.1 });
// Create the objective function without a gradient
var objective = ObjectiveFunction.Value(objectiveFunction) as IObjectiveModel;
// Use a Levenberg-Marquardt optimizer for minimization
var optimizer = new LevenbergMarquardtMinimizer();
// Minimize the objective function starting from the initial guess
var result = optimizer.FindMinimum(objective, initialGuess);
// Output the results
if (result.MinimizingPoint.Count == 2)
{
Console.WriteLine("Fitted parameters:");
Console.WriteLine($"a = {result.MinimizingPoint[0]}");
Console.WriteLine($"b = {result.MinimizingPoint[1]}");
}
}
}
However, I am getting the following exception:
System.ArgumentNullException: 'Value cannot be null.
Parameter name: objective'
How can I fix it?
I wrote you a comment due to your exception being the wrong function/model (ObjectiveFunction.Value returns an object with interface IObjectiveFunction). The minimizer needs to know your model in order to minimize the function parameters. I put your data in a piece of working code below using the Levenberg Marquardt minimizer and it seems to converge on my system after 18 iterations.
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Optimization;
// example data
var xData = new DenseVector(new double[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 });
var yData = new DenseVector(new double[] { 1.0, 2.7, 5.8, 6.6, 7.5, 9.9 });
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, xData, yData);
var solver = new LevenbergMarquardtMinimizer(maximumIterations: 10000);
var result = solver.FindMinimum(objective, start);