前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >利用matlab实现非线性拟合(下)

利用matlab实现非线性拟合(下)

作者头像
巴山学长
发布于 2021-05-08 07:20:32
发布于 2021-05-08 07:20:32
2.7K10
代码可运行
举报
文章被收录于专栏:巴山学长巴山学长
运行总次数:0
代码可运行

没看过上一篇的建议看一下前面的上篇。这一篇非线性拟合我就不废话,直接开始了。下面首先介绍几种matlab非线性拟合方法,之后将这几种方法进行对比研究。

如果你喜欢界面化的输入输出,那么可以尝试Curve Fitting App,它在matlab集成的App里面。

界面里常用的拟合方式都有,而且直接展示拟合效果,非常方便。非常适合鼠标直接拖拖拽拽点点点的操作方式。

除了界面拟合,下面介绍几种函数式拟合的方式。

  • 1 fit()函数

matlab中,fit()函数是一个比较通用的用于函数拟合的函数。它的优点就是非常的全面,可以用于各种种类的拟合。上面的App里,很多拟合种类都是间接调用了fit函数来实现的拟合。

对于非线性拟合,可以使用fit()函数中的Nonlinear Least Squares方法。其大概原理为,首先确定一个初始的点,计算该点的雅可比矩阵J,来近似线性化的判断该点周围的趋势,并将这个点向更小的方向移动。

因此,这个方法的一个缺点在于,对于初始点的选取非常敏感,最终结果只能在初始点附近的局部最小值点上,而不能保证全局最小值。

  • 2 nlinfit()函数

相比于前面的fit()函数,nlinfit()函数是matlab专门的非线性拟合函数。对于非稳健估计,采用的是Levenberg-Marquardt(LM)方法,也叫阻尼最小二乘法。对于稳健估计,采用的是Iteratively Reweighted Least Squares方法,也就是在Least Squares基础上,对每一个拟合点的权重进行调整的一种方法。这两者方法也都是基于雅克比矩阵的方法。

  • 3 lsqnonlin()函数和lsqcurvefit()函数

lsqnonlin()也是matlab中自带的一个非线性拟合函数。它给出了两种计算非线性拟合的方法,一种是比较经典之前介绍过的LM方法,一种是信赖域方法。信赖域法(trust region reflective)是通过Hessian 矩阵,逐步试探邻域内的最小化,来求解问题的。相比较之前的那些雅克比相关的方法,信赖域法会占用更多内存和速度,所以适用于中小规模的矩阵。

lsqcurvefit()函数和lsqnonlin()内容上相似,只是引用格式上有所不同。

  • 4 fsolve()函数

这也是一个求解非线性方程的函数,可以求解方程组或者矩阵形式,功能非常强大。默认的算法为trust-region-dogleg,俗称狗腿法,属于信赖域法。这里用到的功能比较基础,所以也不过多介绍了。

  • 5 粒子群算法

说了那么多,发现逐渐从如何非线性拟合,陷入到了最优化的深坑里。而且前面的那么多方法,很多都解决不了陷入到局部最优解的问题。实际上,这种问题如果进入了最优化领域,很多智能算法也可以被考虑进来。所以我也把粒子群PSO算法加入到了里面,尝试将结果收敛到全局最优解。


前面介绍的这些方法究竟效果如何,下面用实际例子比试一下。

第一个例子是 y=a.*exp(-b*(x-c).^2)+d,一个简单的高斯函数形式的非线性方程,其参数给定为:

a

b

c

d

3.8

2.1

4.4

-1.3

在已知函数形式,求解这四个参数条件下,6种不同的函数非拟合效果如下:

可以看到,这几种方法都能够较好的拟合出想要的结果。

第二个例子是一个指数增长的正弦函数,在很多线性系统中都可以测量到这种信号。函数的形式为:

y=a*x+b*sin(c*x).*exp(d*x)+e 。其给定的参数为:

a

b

c

d

e

-0.3

2.1

4.4

0.3

1.7

这个函数的拟合具有一定难度,拟合过程中会遇到非常多的局部解。

其中前面的几种方法对于初始值的敏感度比较高,如果初始值选的比较接近原始解,也是可以得到较好的结果。其中nlinfit函数经常会报错,容错率较低。而PSO算法经常能够收敛到最优解(虽然不是每次都可以,偶尔也会陷入局部解)。

上图展示了PSO算法逐渐收敛到全局最优解的过程。

6种算法对比的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
clear
clc
%函数大比拼
close all

%初始设置
x = 0:0.1:10;
a = -0.3;
b = 2.1;
c = 4.4;
d = 0.3;
e = 1.7;

y = a*x+b*sin(c*x).*exp(d*x)+e;
noise = 0.05*abs(y-1).*randn(size(x));
y = y+noise;%加噪声函数

figure();%plot(x,y)
y_lim = [-40,40];

%% 1 fit()函数 Least Squares
ft = fittype( 'a*x+b*sin(c*x).*exp(d*x)+e', 'independent', 'x', 'dependent', 'y' );
OP1 = fitoptions( 'Method', 'NonlinearLeastSquares' );
OP1.StartPoint = 5*rand(1,5);%初始值,越靠近真实值越好
OP1.Lower = [-2,0,2,0,0];%参数的最小边界
OP1.Upper = [1,3,5,3,3];%参数的最大边界
%拟合
fitobject = fit(x',y',ft,OP1); 
a2=fitobject.a;
b2=fitobject.b;
c2=fitobject.c;
d2=fitobject.d;
e2=fitobject.e;
%展示结果
y1 = a2*x+b2*sin(c2*x).*exp(d2*x)+e2;
subplot(3,2,1)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y1,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('fit函数')

%% 2 nlinfit()函数 Levenberg-Marquardt %容易报错
modelfun = @(p,x)( p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5) );

OP2 = statset('nlinfit');
%opts.RobustWgtFun = 'bisquare';
p0 = 5*rand(1,5);
p = nlinfit(x,y,modelfun,p0,OP2);
%拟合
y2 = p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5);
subplot(3,2,2)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y2,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('nlinfit函数')

%% 3 lsqnonlin()函数 trust-region-reflective
modelfun = @(p)(p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5) -y) ;%这里和nlinfit()函数定义不一样
p0 = 5*rand(1,5);
OP3 = optimoptions(@lsqnonlin,'Algorithm','trust-region-reflective','MaxFunctionEvaluations',1e4,'MaxIterations',1e3);
[p,~] = lsqnonlin(modelfun,p0,[-2,0,2,0,0],[1,3,5,3,3],OP3);
y3 = p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5);
subplot(3,2,3)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y3,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('lsqnonlin函数')

%% 4 lsqcurvefit()函数 trust-region-reflective
modelfun = @(p,x)(p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5)) ;%这里和其它函数的定义也不一样
p0 = 5*rand(1,5);
OP4 = optimoptions('lsqcurvefit','Algorithm','trust-region-reflective','MaxFunctionEvaluations',1e4,'MaxIterations',1e3);
[p,~] = lsqcurvefit(modelfun,p0,x,y,[-2,0,2,0,0],[1,3,5,3,3],OP4);
y4 = p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5);
subplot(3,2,4)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y4,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('lsqcurvefit函数')

%% 5 fsolve()函数 %默认算法trust-region-dogleg
modelfun = @(p)(p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5) -y);
p0 = 5*rand(1,5);
OP5 = optimoptions('fsolve','Display','off');
p = fsolve(modelfun,p0,OP5);
y5 = p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5);
subplot(3,2,5)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y5,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('fsolve函数')

%% 6 粒子群PSO算法
fun = @(p) ( norm(p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5) -y) );%这里需要计算误差的平方和
OP6 = optimoptions('particleswarm','InertiaRange',[0.4,1.2],'SwarmSize',100);
[p,~,~,~]  = particleswarm(fun,5,[-5,-5,-5,-5],[5,5,5,5],OP6);%区间可以稍微放大一些,不怕
y6 = p(1)*x+p(2)*sin(p(3)*x).*exp(p(4)*x)+p(5);
subplot(3,2,6)
hold on
plot(x,y,'LineStyle','none','MarkerSize',15,'Marker','.','color','k')
plot(x,y6,'-','linewidth',1.5,'color','r')
hold off
box on
ylim(y_lim)
title('PSO算法')

参考资料:matlab官方文档

图片来源:由 hyhhyh21 在Pixabay上发布

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 巴山学长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
专门登录来点赞,太有用了。除了粒子群算法,其他算法是真的很容易陷入局部最小出不去。
专门登录来点赞,太有用了。除了粒子群算法,其他算法是真的很容易陷入局部最小出不去。
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
利用matlab实现非线性拟合(上)
一般而言,通过已有的数据点去推导其它数据点,常见的方法有插值和拟合。插值适用性较广,尤其是线性插值或样条插值已被广泛的应用。但是通过已知的函数去拟合数据,是连接理论与实验重要的桥梁,这一点是插值无法替代的。
巴山学长
2021/04/22
2.5K0
利用matlab实现非线性拟合(上)
利用matlab实现非线性拟合(补)
之前在群里看有人问过三维拟合的问题。回去思考了一下,感觉和之前的非线性拟合还是有很多共同之处的。所以,这次将之前PSO方法的非线性拟合代码改动了一下,将其更改为适用性更广的高维拟合。
巴山学长
2021/05/08
1.6K0
利用matlab实现非线性拟合(补)
Matlab中的画图函数
之前在进行Matlab编程时,画图总是非常重要的一部分,在这里整理一下常用的绘图函数,以作备用。
全栈程序员站长
2022/11/06
3.4K0
Matlab中的画图函数
从泰勒级数说傅里叶级数
泰勒中值定理:若函数f(x)在含有x0的某个开区间内具有直到(n+1)阶的导数,那么对于任一x∈(a,b),有:
巴山学长
2020/06/17
2.8K0
非线性可视化(2)非线性相图
这里举的例子都是自治系统方程的例子,也就是方程结果与t0的初始取值无关(时不变系统),不含外部周期性驱动力之类的与t相关的量。因为描述自治系统,只需要知道系统的空间上的各个变量的导数,然后组成相空间即可。而时变系统各个状态都会随时间变化,无法用静态的相图去定性分析。
巴山学长
2023/03/15
8930
非线性可视化(2)非线性相图
matlab二维彩图colormap调色_matlab如何自定义颜色
这个博客是自己的第一篇博客,瞎写实验中。。。 (2020年2月第一次更新,调整了一下格式,增加了常用的颜色图形式)
全栈程序员站长
2022/11/07
5.5K1
matlab二维彩图colormap调色_matlab如何自定义颜色
MATLAB非线性可视化之线性系统相图
我们在前面的多摆模型中,利用多摆的微分方程模型,求解出了多摆每时每刻的位置随时间的变化。当然那是一个高度复杂的非线性模型,难以上手分析。
巴山学长
2021/09/18
1.9K0
MATLAB非线性可视化之线性系统相图
Matlab机器人工具箱
因为需要用到和机器人相关的东西,就用到了这个工具箱,作者官网 http://www.petercorke.com/Robotics_Toolbox.html
全栈程序员站长
2022/08/13
7750
Matlab机器人工具箱
带你用matlab轻松搞定微分方程
之前过冷水有和大家分享热传导方程求解的方法,其本质上是微分方程的问题。考虑大多数读者对微分方程求解方法比较陌生,所以过冷水本期简单普及一下微分方程的求解问题。
巴山学长
2020/11/03
1.6K0
带你用matlab轻松搞定微分方程
【MATLAB 从零到进阶】day6 MATLAB绘图与可视化
图形窗口、线条、曲面和注释等都被看作是MATLAB中的图形对象,所有这些图形对象都可以通过一个被称为“句柄值”的东西加以控制,例如可以通过一个线条的句柄值来修改线条的颜色、宽度和线型等属性。这里所谓的“句柄值”其实就是一个数值,每个图形对象都对应一个唯一的句柄值,它就像一个指针,与图形对象一一对应。例如可以通过命令h = figure返回一个图形窗口的句柄值。
统计学家
2019/04/10
7690
【MATLAB 从零到进阶】day6 MATLAB绘图与可视化
MATLAB非线性可视化(引3)多摆模型
事实上,非线性存在于物理与工程中的各个领域。在机械中,就存在着大量的非线性现象。通过双摆和三摆的例子,来感受到一个小的扰动,随着时间的推移,到最终会带来多大的变化。
巴山学长
2023/03/15
6530
MATLAB非线性可视化(引3)多摆模型
曲线折叠
曲线折叠 clear ; close all; %正常绘图 x=0:0.005:5; y=exp(-6*x).*sin(x*40)*6+exp(5*x)*5e-11.*sin(x*20); figur
万木逢春
2019/04/30
1.7K0
曲线折叠
谐振子的动力学学运动
在力学的学习过程中经典分析力学是最基本的入门知识,过冷水之前和大家一起学习了两个小车通过弹簧链接起来的做来回摆动运动的运动轨迹学习。推文中直接给了一个微分方程组,然后解出微分方程组就得到了小车的演化轨迹。本期过冷水从零开始构建一个微分方程组,而不是单纯解微分方程。
巴山学长
2021/05/31
6540
谐振子的动力学学运动
Matlab线性插值
figure yi_nearest=interp1(t,p,x,'nearest');%最邻近插值法 plot(t,p,'ko'); hold on plot(x,yi_nearest,'g','LineWidth',1.5);grid on; title('Nearest Method');
AIHGF
2019/02/18
2.5K0
Matlab线性插值
统计回归拟合方程参数
一直以来过冷水都有给大家分享图像拟合的知识、从泰勒级数说傅里叶级数、Matlab多项式拟合初探,本期过冷水给大家讲讲统计回归做拟合。
巴山学长
2020/09/29
4540
统计回归拟合方程参数
matlab画折线图
p=‘plot_scale.xlsx’; a=xlsread§; x=a(1,:);%x轴上的数据,第一个值代表数据开始,第二个值代表间隔,第三个值代表终止 susan=a(2,:);%a数据y值 HarrisLaplace=a(3,:); MSCP=a(4,:); CPDA=a(5,:); HeYung=a(6,:); FastCPDA=a(7,:); DOG=a(8,:); GCM=a(9,:); ANDD=a(10,:); MSRJ=a(11,:); ZhangSun=a(12,:); WEAE=a(13,:); New_Curvature=a(14,:); ASJ=a(15,:); Superpoint=a(16,:); SOGGDD=a(17,:); % figure(1);
全栈程序员站长
2022/07/01
6240
Matlab学习
此 MATLAB 函数 清除命令行窗口中的所有文本,让屏幕变得干净。运行 clc
裴来凡
2022/05/29
1.4K0
Matlab学习
matlab绘图(五)
过冷水有段时间没有和大家分享MATLAB的编程知识了,皆因懒。本期给大家分享一点关于绘图的小技巧,经常有朋友让我帮忙绘图,感觉在我这里是小事,在他们那就是很特别的技能,有时候朋友的特殊绘制要求,也让我犯难。现将自己平时的绘图经验做个小结,主要是关于matlab绘图的一些注意点——公式输入、多轴绘图、交点标记、箭头绘制,通过实际案例给大家讲讲具体的使用。
巴山学长
2020/02/17
1.2K0
matlab绘图(五)
Matlab画图常用的线条符号、颜色
4 、若要同时改变颜色及图线型态(Line style),也是在坐标对后面加上相关字串即可
全栈程序员站长
2022/07/01
2.8K0
matplotlib
r表示不需要转义,raw(生的),LATEX用法,python中使用latex,需要在文本的后面加上$,\pi会转义为pi
h3110_w0r1d
2024/02/19
1540
matplotlib
相关推荐
利用matlab实现非线性拟合(上)
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验