主要内容

使用几种基于问题的方法的非线性数据拟合

对于最小二乘问题的一般建议是用一种允许的方式来表述问题解决认识到问题有最小二乘形式。当你这样做的时候,解决在内部调用lsqnonlin,它在解决最小二乘问题时很有效。看到为基于问题的最小二乘写目标函数

这个例子通过比较最小二乘求解器的性能来显示最小二乘求解器的效率lsqnonlin有了fminunc在同一个问题上。此外,该示例还展示了通过显式地识别和分别处理问题的线性部分可以获得的额外好处。

问题的设置

考虑以下数据:

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);情节(t y“罗”)标题(的数据点

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

问题是如何适应这个功能

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

对数据。

使用默认解算器的解决方法

首先,定义与方程对应的优化变量。

C = optimvar(“c”2);Lam = optimvar(“林”2);

任意设置起始点x0如下:C (1) = 1C (2) = 1Lam (1) = 1,Lam (2) = 0

X0.c = [1,1];x0。Lam = [1,0];

创建一个函数,按时间计算响应的值t当参数为c而且

diffun = c (1) * exp (lam (1) * t) + c (2) * exp (lam (2) * t);

转换diffun到函数和数据之间的差的平方和的优化表达式y

Diffexpr = sum((diffun - y).^2);

创建一个优化问题diffexpr作为目标函数。

Ssqprob =优化问题(“目标”, diffexpr);

使用默认解算器解决问题。

[sol,fval,exitflag,output] = solve(ssqprob,x0)
使用lsqnonlin解决问题。局部最小值。Lsqnonlin停止了,因为最终平方和相对于其初始值的变化小于函数公差的值。
索尔=带字段的结构:C: [2x1 double] lam: [2x1 double]
Fval = 0.1477
exitflag = FunctionChangeBelowTolerance
输出=带字段的结构:firstorderopt: 7.8870e-06迭代:6 funcCount: 7 cgiterations: 0算法:'信任区域反射'步长:0.0096消息:'本地最小可能....' objecvederivative: ' forward-AD '求解器:'lsqnonlin'

根据返回的解值绘制结果曲线sol.c而且sol.lam

Resp = evaluate(diffun,sol);持有情节(t,职责)

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

这件衣服看起来尽可能合身。

解决方法使用fminunc

来解决这个问题fminunc求解器,设置“规划求解”选项“fminunc”当调用解决

[xunc,fvalunc,exitflagunc,outputunc] = solve(ssqprob,x0, x0,“规划求解”“fminunc”
使用fminunc解决问题。找到局部极小值。优化完成,因为梯度的大小小于最优性公差的值。
xunc =带字段的结构:C: [2x1 double] lam: [2x1 double]
Fvalunc = 0.1477
exitflagunc =优化方案
outputunc =带字段的结构:迭代:30 funcCount: 37 stepsize: 0.0017 lssteplth: 1 firstorderopt: 2.9454e-05算法:'准牛顿'消息:'本地最小值找到....' objecvederivative: ' forward-AD '求解器:'fminunc'

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

流(['使用fminunc有%d次迭代,'...'和%d使用lsqcurvefit.\n'),...outputunc.iterations output.iterations)
有30次迭代使用fminunc, 6次使用lsqcurvefit。
流(['使用fminunc计算了%d个函数,'...'和%d使用lsqcurvefit '),...outputunc.funcCount output.funcCount)
使用fminunc进行37次功能评估,使用lsqcurvefit进行7次。

拆分线性与非线性问题

注意,拟合问题在参数中是线性的c (1)而且c (2).这意味着对于任意值林(1)而且林(2)的值,可以使用反斜杠操作符来查找c (1)而且c (2)解决了最小二乘问题。

将问题重新处理为二维问题,寻找的最佳值林(1)而且林(2).的价值c (1)而且c (2)在每一步都使用上面描述的反斜杠运算符进行计算。要做到这一点,请使用fitvector函数,该函数执行反斜杠操作来获取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

解决问题的方法解决从二维起始点开始x02.lam(1,0).要做到这一点,首先转换fitvector函数转换为使用的优化表达式fcn2optimexpr.看到将非线性函数转化为优化表达式.为避免警告,请给出结果表达式的输出大小。创建一个新的优化问题,目标为转换后的差异的平方和fitvector函数和数据y

x02.lam=x0。林;F2 = fcn2optimexpr(@(x) fitvector(x,t,y),lam,“OutputSize”,长度(t) 1);Ssqprob2 =优化问题(“目标”,sum((F2 - y).^2));[sol2,fval2,exitflag2,output2] = solve(ssqprob2,x02)
使用lsqnonlin解决问题。局部最小值。Lsqnonlin停止了,因为最终平方和相对于其初始值的变化小于函数公差的值。
sol2 =带字段的结构:Lam: [2x1 double]
Fval2 = 0.1477
exitflag2 = FunctionChangeBelowTolerance
output2 =带字段的结构:firstorderopt: 4.4087e-06迭代:10 funcCount: 33 cgiterations: 0算法:'信任区域反射'步长:0.0080消息:'本地最小值可能....' objecvederivative: '有限差分'求解器:'lsqnonlin'

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

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

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

为最初的四参数问题选择一个糟糕的起点会导致局部解决方案而不是全局解决方案。选择一个起点与相同的坏林(1)而且林(2)分离双参数问题的值可以得到全局解。为了显示这一点,请使用一个起点重新运行原始问题,该起点会导致一个相对较差的局部解决方案,并将得到的拟合结果与全局解决方案进行比较。

X0bad.c = [5 1];x0bad。林=[1 0]; [solbad,fvalbad,exitflagbad,outputbad] = solve(ssqprob,x0bad)
使用lsqnonlin解决问题。局部最小值。Lsqnonlin停止了,因为最终平方和相对于其初始值的变化小于函数公差的值。
solbad =带字段的结构:C: [2x1 double] lam: [2x1 double]
Fvalbad = 2.2173
exitflagbad = FunctionChangeBelowTolerance
outputbad =带字段的结构:firstorderopt: 0.0036迭代:31 funcCount: 32 cgiterations: 0算法:'信任区域-反射'步长:0.0012消息:'本地最小值可能....' objecvederivative: ' forward-AD '求解器:'lsqnonlin'
Respbad = evaluate(diffun,solbad);持有情节(t, respbad‘g’)传说(“数据”“全球健康”“不适应当地环境”“位置”“不”)举行

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

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

另请参阅

|

相关的话题

Baidu
map