我正在尝试使用 MathNet 库来计算基于非线性回归的曲线拟合。
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]}");
}
}
}
但是,我遇到以下异常:
System.ArgumentNullException: 'Value cannot be null.
Parameter name: objective'
我该如何修复它?
我给你写了一条评论,因为你的异常是错误的函数/模型(ObjectiveFunction.Value 返回一个带有接口 IObjectiveFunction 的对象)。最小化器需要了解您的模型才能最小化函数参数。我使用 Levenberg Marquardt 最小化器将您的数据放入下面的一段工作代码中,经过 18 次迭代后它似乎在我的系统上收敛。
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);