matlab进行非线性拟合常用最小二乘法实现,适用于:已经求解出函数,但含有未知数,不过已经收集到了一系列数据

1.lsqcurvefit

格式:[x, resnorm,r,flag]=lsqcurvefit(fun, c0,xdata,ydata)

c0为初始解向量;xdata,ydata为数据;

fun为待拟合函数(句柄函数),resnorm=sum ((fun(c,xdata)-ydata).^2),即在xdata处残差的平方和;flag为终止迭代的条件。

例:确定模型中的参数,已知数据点:

xdata = [3.6,7.7,9.3,4.1,8.6,2.8,1.3,7.9,10.0,5.4];

ydata = [16,150.5,260.1,22.5,206.5,9.9,2.7,165.5,325.0,54.5];

句柄函数举例:

xdata=[3.6,7.7,9.3,4.1,8.6,2.8,1.3,7.9,10.0,5.4]; 
ydata=[16,150.5,260.1,22.5,206.5,9.9,2.7,165.5,325.0,54.5];
c0=[0 0 0];
f_h=@(c, x) c(1)*x.^2 + c(2)*x.*sin(x) + c(3)*x.^3;
[c,resnorm,r]=lsqcurvefit(f_h,c0,xdata,ydata);
plot(xdata,f_h(c,xdata),xdata,ydata,'o');

自定义函数举例:

xdata=[3.6,7.7,9.3,4.1,8.6,2.8,1.3,7.9,10.0,5.4]; 
ydata=[16,150.5,260.1,22.5,206.5,9.9,2.7,165.5,325.0,54.5];
c0=[0 0 0];
[c,resnorm,r]=lsqcurvefit(@cal,c0,xdata,ydata);
plot(xdata,cal(c,xdata),xdata,ydata,'o');

function y = cal(c,x)
y = c(1)*x.^2 + c(2)*x.*sin(x) + c(3)*x.^3;
end

2.fittype

使用fittype函数可以自定义拟合函数,可以满足线性拟合和非线性拟合。fittype函数具有很灵活的配置,基本满足各种复杂场景。

fittpye 函数内部参数 ' independent ' 指定哪些变量为自变量,相对的 ' coefficients ' 指定哪些变量为未知量,如:

ft = fittype('自定义函数','independent ','x');

ft = fittype('自定义函数','coefficients',{'k','r'});

需要注意的是,fit 函数内的自变量与因变量都需要是列矩阵,如果初始数据为行矩阵的话,需要转置一下

fit 后面可以加参数来指定拟合参数的初始值,如:

fo = fit( x , y , ft , 'startpoint' , [0 0]);

1.做多项式拟合:

x=[1;1.5;2;2.5;3];
y=[0.9;1.7;2.2;2.6;3];
ft=fittype('poly2');
fo=fit(x,y,ft);
plot(x,fo(x))  % or plot(fo, x, y);

2.做非线性拟合:

线性化拟合:

x=[0.2,0.5,0.8,1.1,1.2,1.5,1.8,2];
y=[2.35,1.38,0.81,0.62,0.78,1.43,2.25,3.18];
ex= {'x^2','sin(x)','1'};
ft=fittype(ex);
fo=fit(x',y',ft);
plot(x,fo(x),x,y,'o');

非线性化拟合:

x=[0.2,0.5,0.8,1.1,1.2,1.5,1.8,2];
y=[2.35,1.38,0.81,0.62,0.78,1.43,2.25,3.18];
ex= {'x^2','sin(x)','1'};
ft=fittype('a*x^2+b*sin(x)+c','independent','x');
fo=fit(x',y',ft);
plot(x,fo(x),x,y,'o');

例:在某次阻尼振荡实验中测得18组数据点,试确定其振动方程。(使用匿名函数实现)

x=[0,0.4,1.2,2,2.8,3.6,4.4,5.2,6,7.2,8,9.2,10.4,11.6,12.4,13.6,14.4,15];

y=[1,0.85,0.29,-0.27,-0.53,-0.4,-0.12,0.17,0.28,0.15,-0.03,-0.15,-0.07,0.059,0.08,0.032,-0.015,-0.02];

解:由物理背景知:

x=[0,0.4,1.2,2,2.8,3.6,4.4,5.2,6,7.2,8,9.2,10.4,11.6,12.4,13.6,14.4,15]';  %注意这里的转置
y=[1,0.85,0.29,-0.27,-0.53,-0.4,-0.12,0.17,0.28,0.15,-0.03,-0.15,-0.07,0.059,0.08,0.032,-0.015,-0.02]';  %注意这里的转置
f_h=@(a,k,w,x) a.*cos(k.*x).*exp(w.*x);
ft=fittype(f_h);
fo=fit(x,y,ft)
xx=0:0.1:20;
yy=fo(xx);
plot(x,y,'r*',xx,yy,'b-');

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐