主要内容

非线性数据拟合

这个例子展示了如何使用几个优化工具箱™算法将非线性函数拟合到数据。

问题的设置

考虑以下数据:

Data =...[0.0000 5.8955 0.1000 3.5639 0.2000 2.5173 0.3000 1.9790 0.4000 1.8990 0.5000 1.3938 0.6000 1.1359 0.7000 1.0096 0.8000 1.0343 0.9000 0.8435 1.0000 0.6856 1.1000 0.6100 1.2000 0.3946 1.4000 0.3903 1.5000 0.5474 1.6000 0.3459 1.7000 0.1370 1.8000 0.2211 1.9000 0.2636];

让我们把这些数据点画出来。

t = Data(:,1);y = Data(:,2);%轴([0 2 -0.5 6])%坚持情节(t y“罗”)标题(的数据点

图中包含一个轴对象。具有标题数据点的axes对象包含一个line类型的对象。

%延迟

我们想要拟合函数

Y = c(1)*exp(-lam(1)*t) + c(2)*exp(-lam(2)*t)

对数据。

解决方法使用lsqcurvefit

lsqcurvefit函数很容易解决这类问题。

首先,用一个变量x定义参数:

X (1) = c(1)

X (2) = lam(1)

X (3) = c(2)

X (4) = lam(2)

然后将曲线定义为参数x和数据t的函数:

F = @ (x, xdata) x (1) * exp (- x (2) * xdata) + x (3) * exp (- x (4) * xdata);

我们任意设置初始点x0如下:c(1) = 1, lam(1) = 1, c(2) = 1, lam(2) = 0:

X0 = [1 1 10 0];

我们运行求解器并绘制结果拟合图。

[x,resnorm,~,exitflag,output] = lsqcurvefit(F,x0,t,y)
局部最小值。Lsqcurvefit停止了,因为相对于其初始值的平方和的最终变化小于函数公差的值。
x =1×43.0068 10.5869 2.8891 1.4003
Resnorm = 0.1477
Exitflag = 3
输出=带字段的结构:firstorderopt: 7.8830e-06迭代:6 funcCount: 35 cgiterations: 0算法:'信任区域反射'步长:0.0096消息:'本地最小可能....'
持有情节(t, F (x, t))

图中包含一个轴对象。具有标题数据点的axis对象包含2个类型为line的对象。

解决方法使用fminunc

解决问题使用fminunc时,我们将目标函数设为残差平方和。

Fsumsquares = @(x)sum((F(x,t) - y).^2);Opts = optimoptions(“fminunc”“算法”“拟牛顿”);[xunc, ressquared eflag outputu] =...fminunc (x0, Fsumsquares选择)
找到局部极小值。优化完成,因为梯度的大小小于最优性公差的值。
xunc =1×42.8890 1.4003 3.0069 10.5862
Ressquared = 0.1477
Eflag = 1
outputu =带字段的结构:迭代:30 funcCount: 185步长:0.0017 lssteplth: 1 firstorderopt: 2.9662e-05算法:'准牛顿'消息:'本地最小值发现....'

请注意,fminunc得到了相同的解lsqcurvefit,但需要进行更多的函数计算。的参数fminunc和for的顺序相反吗lsqcurvefit;较大的lam是lam(2),而不是lam(1)。这并不奇怪,变量的顺序是任意的。

流(['使用fminunc有%d次迭代,'...'和%d使用lsqcurvefit.\n'),...outputu.iterations output.iterations)
有30次迭代使用fminunc, 6次使用lsqcurvefit。
流(['使用fminunc计算了%d个函数,'...'和%d使用lsqcurvefit '),...outputu.funcCount output.funcCount)
185例功能评价使用fminunc, 35例使用lsqcurvefit。

拆分线性与非线性问题

注意,拟合问题在参数c(1)和c(2)中是线性的。这意味着对于lam(1)和lam(2)的任何值,我们可以使用反斜杠运算符来找到解决最小二乘问题的c(1)和c(2)的值。

现在我们将问题重新处理为二维问题,寻找lam(1)和lam(2)的最佳值。c(1)和c(2)的值在每一步都使用上面描述的反斜杠运算符计算。

类型fitvector
function yEst = fitvector(lam,xdata,ydata) % fitvector DATDEMO用于返回拟合函数的值。% yEst = FITVECTOR(lam,xdata)返回拟合函数y %(定义如下)在参数设置为lam的数据点xdata处的值。% yeest作为一个N × 1的列向量返回,其中N是%数据点的数量。FITVECTOR假设拟合函数y,其形式为% % y = c(1)*exp(-lam(1)*t) +…+ c(n)*exp(-lam(n)*t) % %含n个线性参数c, n个非线性参数lam。为了求解线性参数c,我们构建一个矩阵a,其中a的第j列是exp(-lam(j)*xdata) (xdata是一个向量)。然后我们求解A*c = ydata的线性最小二乘解c,其中ydata是y的观测值。A = 0 (length(xdata),length(lam));%构造一个矩阵为j = 1:length(lam) A(:,j) = exp(-lam(j)*xdata);end c = A\ydata;%求解A*c = y的线性参数c yEst = A*c; % return the estimated response based on c

解决问题的方法lsqcurvefit,从二维初始点lam(1), lam(2)开始:

X02 = [10];F2 = @(x,t) fitvector(x,t,y);[x2,resnorm2,~,exitflag2,output2] = lsqcurvefit(F2,x02,t,y)
局部最小值。Lsqcurvefit停止了,因为相对于其初始值的平方和的最终变化小于函数公差的值。
x2 =1×210.5861 - 1.4003
Resnorm2 = 0.1477
Exitflag2 = 3
output2 =带字段的结构:firstorderopt: 4.4087e-06迭代:10 funcCount: 33 cgiterations: 0算法:'信任区域反射'步长:0.0080消息:'本地最小可能....'

二维解的效率与四维解的效率相似:

流(['有%d个函数计算使用2-d '...'公式,%d使用4-d公式。'),...output2.funcCount output.funcCount)
有33个功能评估使用2-d公式,35个使用4-d公式。

拆分问题对初始猜想的鲁棒性更强

为最初的四参数问题选择一个糟糕的起点会导致局部解决方案而不是全局解决方案。对于分裂的双参数问题,选择具有相同坏lam(1)和lam(2)值的起始点可以得到全局解。为了证明这一点,我们重新运行原始问题的起点,导致一个相对较差的局部解决方案,并将结果与全局解决方案进行比较。

X0bad = [5 1 10 0];[xbad, resnormbad, ~, exitflagbad outputbad] =...lsqcurvefit (F, x0bad t y)
局部最小值。Lsqcurvefit停止了,因为相对于其初始值的平方和的最终变化小于函数公差的值。
xbad =1×4-22.9036 2.4792 28.0273 2.4791
Resnormbad = 2.2173
Exitflagbad = 3
outputbad =带字段的结构:firstorderopt: 0.0056迭代:32 funcCount: 165 cgiterations: 0算法:'信任区域反射'步长:0.0021消息:'本地最小可能....'
持有情节(t、F (xbad t),‘g’)传说(“数据”“全球健康”“不适应当地环境”“位置”“不”)举行

图中包含一个轴对象。具有标题数据点的axes对象包含3个类型为line的对象。这些对象表示数据、全局拟合、糟糕的局部拟合。

流(['在良好终点的剩余范数是%f '...'在坏终点的剩余范数是%f '),...resnorm resnormbad)
好的终点的剩余范数为0.147723,坏的终点的剩余范数为2.217300。

相关的话题