MATLAB有关lsqcurvefit函数对多个未知参数函数拟合的相关问题

在MATLAB中关于函数拟合的函数主要分为两类。一类是线性拟合,另一类则是非线性拟合。非线性拟合相对来说,难度会比线性拟合更大一些。本篇文章主要是关于如何使用lsqcurvefit函数进行非线性拟合的,从而得到函数中的多个未知量。

1、首先,我们通过MATLAB命令行窗口输入help lsqcurvefit,对lsqcurvefit函数的使用作一个大致的了解。

Nonlinear least-squares solver——基于最小二乘法的非线性拟合

以下是使用lsqcurvefit的格式

x = lsqcurvefit(fun,x0,xdata,ydata)
x = lsqcurvefit(fun,x0,xdata,ydata,lb,ub)
x = lsqcurvefit(fun,x0,xdata,ydata,lb,ub,options)
x = lsqcurvefit(problem)
[x,resnorm] = lsqcurvefit(___)
[x,resnorm,residual,exitflag,output] = lsqcurvefit(___)
[x,resnorm,residual,exitflag,output,lambda,jacobian] = lsqcurvefit(___)

参数说明:
x0为初始解向量;xdata,ydata为满足关系ydata=F(x, xdata)的数据;
lb、ub为解向量的下界和上界lb≤x≤ub,若没有指定界,则lb=[ ],ub=[ ];
options为指定的优化参数;
fun为待拟合函数,计算x处拟合函数值,其定义为 function F = myfun(x,xdata)
resnorm=sum ((fun(x,xdata)-ydata).^2),即在x处残差的平方和;
residual=fun(x,xdata)-ydata,即在x处的残差;
exitflag为终止迭代的条件;
output为输出的优化信息;
lambda为解x处的Lagrange乘子;
jacobian为解x处拟合函数fun的jacobian矩阵。
一般来说,拟合复杂的函数并不是一开始就能成功的,resnorm是一个衡量拟合质量好坏的参数,所以不建议采用前四中格式。本次采用的为:[x,resnorm] = lsqcurvefit(___)

2、编写待拟合的函数
在拟合的.m文件末尾编写待拟合的函数,以下为我需要拟合的函数,其中含有6个未知参数。在拟合前,一定一定要多次检验待拟合函数的正确性。待拟合函数中出现错误,会是致命的错误。以下,是本人需要拟合的函数。

 function neff=nef_r(a,f)
     epxlb=a(1);    f0e=a(2);     miub=a(3);    fpm=a(4);     f0m=a(5);     gammam=a(6); 
     epxl0=1/(36*pi*10^9);
     miu0=4*pi*10^-7;
     h=0.0003;
     d=0.003;
     k=2*pi*f*sqrt(epxl0*miu0);
     epxl=epxlb*(1-(f0e*10^9)^2./f.^2);
     miu=miub-(fpm*10^9)^2./(f.^2-(f0m*10^9)^2+1i*(gammam*10^9)*f);
     epxl_av=epxl*h/d;
     miu_av=miu*h/d;
     n_r=real(1./(k*d).*acos((4-(k*d).^2.*epxl_av.*miu_av)./(4+(k*d).^2.*epxl_av.*miu_av).*cos(k*d)-(2*(epxl_av+miu_av).*k*d)./(4+(k*d).^2.*epxl_av.*miu_av).*sin(k*d)));
     n_i=imag(1./(k*d).*acos((4-(k*d).^2.*epxl_av.*miu_av)./(4+(k*d).^2.*epxl_av.*miu_av).*cos(k*d)-(2*(epxl_av+miu_av).*k*d)./(4+(k*d).^2.*epxl_av.*miu_av).*sin(k*d)));
     for m=1:length(f)
        if n_i(m)<0
             n_r(m)=-n_r(m);
             n_i(m)=-n_i(m); 
        end
     end
     neff=n_r;
 end

3、设置拟合的上、下限以及初始值。
这应该是多个未知参数拟合最难的部分,也是最容易卡壳的地方。在设置拟合的上、下限和初始值时,稍有偏差,就会使拟合效果不佳,即resnorm值偏大。这一部分我们留到最后再说明如何调试出较佳的拟合效果。

    a0=[1;      35;     10;      26;      10;        0.02];%初始值
    lb=[0;      30;      1;      24;      8;      0];%下限
    ub=[2;        50;     14;     30;     20;    0.5];%上限

4、绘图
应该是最简单,但却又是很重要的部分。绘图是最直观的观测拟合效果的方法。我们将原始数据real(n)用红色实线绘图,待拟合函数用红色虚线绘图。

 plot(f/(10^9),real(n),'r');
 hold on;
 plot(f/(10^9),n_r,'r--');
 hold on;

5、拟合选项设置

options = optimset('Display','iter','Tolx',1e-15,'TolFun',1e-15);

其中,‘Display’为显示级别,本次显示级别为‘iter’,在每次迭代时显示输出。
‘Tolx’为关于当前点 x 的终止容差,在当前点与先前点相差小于 TolX 时(相对于 x 的大小),迭代结束。本次当前点 x 终止容差为1e-15。
TolFun’为函数值的终止容差,在当前函数值与先前值相差小于 TolFun 时(相对于初始函数值),迭代结束。本次函数值的终止容差为1e-15。

6、进行拟合

[x,renorm]=lsqcurvefit(@nef_r,a0,f',real(n),lb,ub,options)

当然,多未知参数非线性函数的拟合并不是一蹴而就的。需要不断的调试拟合的初始值、上限和下限。这会是一个漫长的过程。

接下来需要啃的硬骨头就是调试过程了:
1、首先,我们需要知道未知参数的大致量级,可以根据函数内未知参数的实际意义出发得到大概量级。
2、粗调:因为每次拟合得到的未知参数都是无法精准控制的。所以可以另写一个.m文件,提前给予未知参数一个确定的值(当然这个值是在已知每个未知参数的量级的前提下去大胆尝试)代入到待拟合函数中,对比绘画出的红色实线图形与红色虚线图形形状。如果形状大致一样,就可以进行下一步的细调;若形状不一样,继续修改猜测值,直到图形大致一致为止。

  a0=[1.87  34.14  10.12  26.35  10.09  0.0224];

3、细调:细调的工作,我们就交给lsqcurvefit函数。将初始值设置为猜测值。将上下限稍微调大一些,当然初值得在上下限之间。再逐一缩小上限限,适当修改初始值,使resnorm值越小越好。注意:唯一的目的是使resnorm值越小。当拟合函数没问题以及resnorm值足够小时,实线与虚线应该是大致重合的。

我的大致代码以及拟合效果,未知参数和resnorm值如下图:
实现代码(部分)

拟合效果

请添加图片描述

程序设计流程图如下:
程序设计流程图

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三下伍除二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值