知乎盐选 | MATLAB 从基础到精通 - 7.4 拟合和插值

7.4 拟合和插值

拟合和插值在数据处理中是非常重要的,两者都可以通过离散的函数数据点,估计出函数在任意点的值,所不同的是:拟合可以确定函数准确的表达式,通过调整函数的系数,使得函数在已知点的估计值与真实情况下已知点的值差距最小;而插值通过函数在有已知点处的取值状况,估算出函数在其他点处的近似值。

拟合和插值是离散函数逼近的有效方法,通过本节的学习读者将掌握简单的数据拟合和插值方法,今后在实际应用中可根据不同的问题采用不同的方法。

7.4.1 拟合基础

在科学实验中我们往往需要研究某些变量间是否存在什么关系,是否可以建立稳定的函数表达式,这样通过一些变量即可预测某些关键参数。于是,往往在实验中我们会获取一组离散的观测数据,如(x1,y1),(x2,y2),…,(xn,yn),数据拟合要解决的问题即确定一函数 y=f(x)能较为准确地表达这些变量间的关系。

数据拟合主要是要找到能较好反映观测数据的近似函数,寻求整体误差最小。逼近离散数据的数值拟合常采用的拟合方法为最小二乘拟合,而根据拟合模型的类型可以分为线性拟合和非线性拟合,下面具体讲述如何在 MATLAB 中进行线性拟合和非线性拟合。

7.4.2 线性拟合

本节关于线性拟合的内容主要介绍常用的多项式拟合,其他的拟合方法将在曲线拟合章节中详细讲述。多项式拟合主要用于拟合函数表达式为多项式的数值拟合问题,即确定满足已知数据点的多项式函数的系数。在 MATLAB 中,用函数 polyfit()来求解多项式的系数,之前介绍的多项式求值函数 polyval()即可方便地计算出任意点上的函数近似值。

多项式拟合函数 polyfit()的调用格式如下。

● p=polyfit(x,y,n):其中 x 和 y 为待拟合数据点的值,n 为离散数据需要逼近的多项式的阶数,返回参数 p 为拟合的多项式的系数向量,长度为 n+1。

【例 7.45】多项式拟合。

x=0:0.1:1
y=[-0.4,1.5,3.3,6,8,5.4,7.6,7.96,8.4,9.3,11.2];
plot(x,y,'k.','markersize',10)
p1=polyfit(x,y,3)
s1=polyval(p1,x)
hold on;
plot(x,s1,'-');

执行上述程序,生成如图 7.7 所示的多项式拟合的效果图。

加载中...

图 7.7 多项式拟合效果图

7.4.3 非线性拟合

函数 nlinfit()和 lsqcurvefit()可用于求解 MATLAB 的非线性拟合问题,下面详细介绍其使用方法。

函数 nlinfit()的调用格式如下。

● beta = nlinfit(x,y,fun,beta0):x 和 y 为观测数据的自变量和因变量,fun 为待拟合的模型表达式,可以为 y=f(x)的 M 文件的函数名,或者由 inline()函数表示,beta0 是模型初始参数的估计值,计算后获得的返回值 beta 为最小二乘估计得出的模型最佳系数。

● [beta,r,J] = nlinfit(x,y,fun,beta0):曲线拟合后的返回参数 r 为拟合的残差,而 J 为残差 r 对 a 的 Jacobi 向量构成的矩阵。

● [...] = nlinfit(x, y, fun, beta0, options):参数 options 对拟合过程进行设置,其中包括 MaxIter(最大叠代次数)、TolFun(函数残数平方和允许值)、TolX(拟合系数允许的误差值)和 Display(控制拟合过程的显示,其中 off 表示不显示输出、iter 显示每次迭代的结果、final 只显示最终结果、notify 只在函数不收敛的时候显示结果)。

函数 lsqcurvefit()的调用格式如下。

[a, rnorm, r, exitflag]=lsqcurvefit(fun, a0, X,Y, lb,ub,options):其中 fun 为待拟合的模型表达式,可以为 y=f(x)的 M 文件的函数名,或者由 inline()函数表示,a0 为模型系数的初始估计值,lb 和 ub 分别为拟合系数的预估下界和上界,参数 options 用于拟合过程设置,同函数 nlinfit(),函数返回的参数中 a 为拟合估计系数,rnorm 为误差平方和,r 为拟合模型的残差,exitflag 为运行情况。

【例 7.46】非线性拟合。

(1)创建非线性拟合函数。

function f=myfun1(a,x)

f=a(1)+a(2)\*exp(-0.02\*a(3)*x)

(2)利用函数 nlinfit()进行非线性拟合。

x=1:10:100;
y=[4.54,4.99,5.35,5.65,5.90,6.10,6.26,6.39,6.50,6.59];
a0=[0.2,0.05,0.05];
options=statset('MaxIter', 100, 'TolFun', 1e-4,'Display','final')
a=nlinfit(x, y, 'myfun1', a0, options) % 利用函数 nlinfit()进行非线性拟合
f= myfun1(a,x)

拟合后的结果如下。

a =
-40.7170 45.5431 -0.0235
f =
Columns 1 through 6

4.8476  5.0624  5.2783  5.4953  5.7132  5.9322

Columns 7 through 10

6.1522  6.3732  6.5953  6.8184

(3)利用函数 lsqcurvefit()进行非线性拟合。

x=1:10:100;
y=[4.54,4.99,5.35,5.65,5.90,6.10,6.26,6.39,6.50,6.59];
a0=[0.2,0.05,0.05];
a=lsqcurvefit ('myfun1',a0,x,y) % 利用函数 lsqcurvefit()进行非线性拟合
f= myfun1(a,x)

拟合后的结果如下。

a =
-1.5718 6.4484 -0.1457
f =
Columns 1 through 6

4.8955  5.0867  5.2835  5.4862  5.6948  5.9096

Columns 7 through 10

6.1308  6.3585  6.5929  6.8343

7.4.4 插值基础

在生产实践中,有时自变量与因变量间的函数关系并不能写出明确的函数表达式,或者表达式很复杂,此时为了得出函数在若干点的函数值可以通过数据插值的方法。插值是通过已知的观测点(xi,yi)建立一个简单的、连续的解析模型 g(x),用于逼近已知的观测点,从而推测非观测点处的状况。常用的插值方法有拉格朗日插值、牛顿插值、三次样条插值、分段线性插值法等。

插值主要用于根据已知点估计未知点,和拟合的不同点在于:插值给出的是数据点,而非拟合的模型;插值函数应通过所有给定的已知数据点,而拟合是要让数据点很好地逼近函数,控制模型整体的误差最小。

插值问题一般分为一维插值、二维插值和高维插值问题,下面从这几个角度详细地叙述如何利用 MATLAB 实现数据插值。

1.一维插值

在 MATLAB 中,函数 interp1()可用于一维数据插值,其调用格式如下。

● yi = interp1(x,y,xi):参数 x 和 y 为已知的数据点,xi 为需要通过插值获取的点,默认的插值方法为 linear(线性插值),yi 为通过一维插值函数获得的点 xi 处的 yi 值。

● yi = interp1(y,xi):插值的数据点中 x 取 1:length(y),返回插值点 xi 处的 yi 值。

● yi = interp1(x,y,xi,method):指定插值的方法,常用的插值方法有 nearest(最邻近点插值)、linear(线性插值)、spline(三次样条插值)、cubic(立方插值)和 pchip(三次 Hermite 插值)。

● yi = interp1(x,y,xi,method,'extrap'):对于超过已知点 x 范围的插值点 xi 执行外插值方法 extrap。

● yi = interp1(x,y,xi,method,extrapval):对于超过已知点 x 范围的插值点 xi 取确定的插值点,一般为 NaN 或 0。

下面对各种数据插值方法做简单介绍。

● nearest(最邻近点插值):插值点估计函数值为已知点中最接近插值点的值,该算法是最快的插值方法,但是数据平滑最差,插值后的数据是不连续的。

● linear(线性插值):插值点估计函数值通过线性函数计算所得,该算法执行速度较快,有较高的插值精度,为插值函数的默认设置。

● spline(三次样条插值):插值点估计函数值通过三次多项式计算所得,该算法精度高,能获得最平滑的插值曲线,但执行速度最慢。

● cubic(立方插值)或 pchip(三次 Hermite 插值):插值点估计函数值通过 Hermite()函数计算所得,该算法较慢,但精度高,平滑度好。

综上,不同的插值算法的原理不同,可能会得到不同精度的解,在使用中用户应根据问题的实际需要选择合适的插值方法。

【例 7.47】一维插值。

x=1:10:100;
y=[4.54,4.99,5.35,5.65,5.90,6.10,6.26,6.39,6.50,6.59];
t=1:1:100;
y1=interp1(x,y,t,'nearest');
subplot(2,2,1);
plot(x,y,'r*',t,y1)
title(『最邻近点插值』)
y2=interp1(x,y,t,'linear');
subplot(2,2,2);
plot(x,y,'r*',t,y2,'b:')
title(『线性插值』)
y3=interp1(x,y,t,'spline');
subplot(2,2,3);
plot(x,y,'r*',t,y3)
title(『样条插值』)
y4=interp1(x,y,t,'cubic');
subplot(2,2,4);
plot(x,y,'r*',t,y4,'k-')
title(『三次插值』)

执行上述程序,生成如图 7.8 所示的不同的一维插值效果图。

加载中...

图 7.8 不同的一维插值效果

2.二维插值

MATLAB 中提供了函数 interp2()和 griddata()用于二维数据的插值,其中函数 interp2()主要用于二维网格数据的插值,而函数 griddata()可对任意分布的数据进行二维插值。

函数 interp2()的调用格式如下。

● zi = interp2(x,y,z,xi,yi):x 和 y 为已知数据点在 x 轴和 y 轴上的坐标点,z 为相应已知点上的函数值,要求已知点 x 和 y 大小相同、单调,xi 和 yi 为插值点,要求 xi 和 yi 必须在已知点 x 和 y 范围内,如果查过范围,将得到「NaN」值,参数 zi 为插值函数范围的插值结果。

● zi = interp2(z,xi,yi):x 和 y 默认情况下分别为数据 z 对应的行号和列号。

● zi = interp2(x,y,z,xi,yi,method):参数 method 用于指定二维插值的方法,包括 nearest(最邻近点插值)、linear(线性插值,默认)、spline(三次样条插值)和 cubic(立方插值)。

● zi = interp2(...,method, extrapval):设置当插值点超过已知点后的插值的值为 extrapval。

【例 7.48】二维插值网格插值。

[x,y,z]=peaks(10);
mesh(x,y,z)
[xi,yi]=meshgrid(-10:0.5:10,-10:0.5:10);
z1=interp2(x,y,z,xi,yi,'nearest');
z2=interp2(x,y,z,xi,yi,'linear');
z3=interp2(x,y,z,xi,yi,'spline');
z4=interp2(x,y,z,xi,yi,'cubic');
subplot(2,2,1)
mesh(xi,yi,z1)
title(『最邻近点插值』)
subplot(2,2,2)
mesh(xi,yi,z2)
title(『线性插值』)
subplot(2,2,3)
mesh(xi,yi,z3)
title(『样条插值』)
subplot(2,2,4)
mesh(xi,yi,z4)
title(『三次插值』)

执行上述程序,生成如图 7.9 所示的不同的二维网格插值效果图。

加载中...

图 7.9 不同的二维网格插值效果

函数 griddata()的调用格式如下。

● zi = griddata(x,y,z,xi,yi):x 和 y 是已知数据组,z 是相对应的已知点上的函数值,xi 和 yi 是需要插值的数据点,zi 为函数返回的插值结果。

● [...] = griddata(...,method):设置二维数据插值的方法包括 nearest(最邻近点插值)、linear(线性插值,默认)、cubic(立方插值)和 v4(MATLAB 4.0 版本中提供)。

【例 7.49】利用函数 griddata()进行二维插值。

[x,y]=meshgrid(-10:2:10,-15:1:10);
z=x.^2+y.^2;
[xi,yi]=meshgrid(-2:0.1:2,-5:0.1:5);
z1=griddata(x,y,z,xi,yi,'nearest');
z2=griddata(x,y,z,xi,yi,'linear');
z3=griddata(x,y,z,xi,yi,'cubic');
z4=griddata(x,y,z,xi,yi,'v4');
subplot(2,2,1)
surf(xi,yi,z1)
title(『最邻近点插值』)
subplot(2,2,2)
surf(xi,yi,z2)
title(『线性插值』)
subplot(2,2,3)
surf(xi,yi,z3)
title(『三次插值』)
subplot(2,2,4)
surf(xi,yi,z4)
title(『v4 插值』)

执行上述程序,生成如图 7.10 所示的不同的二维插值效果图。

加载中...

图 7.10 不同的二维插值效果

3.高维插值

MATLAB 支持三维插值及三维以上的插值,可以通过函数 interp3(三维插值函数)、interpn(n 维插值函数)和 ndgrid(n 维网格数据插值)实现。其使用方法与 interp2 类似,直接通过实例向读者演示这些函数的使用。

【例 7.50】高维插值。

[x,y,z,v] = flow(10);
[xi,yi,zi] = meshgrid(-1:0.05:1, -1:0.05:1, -1:0.05:1);
vi = interp3(x,y,z,v,xi,yi,zi);
slice(xi,yi,zi,vi,[0.6 0.8],0.5,[-0.2 0.2])

执行上述程序,生成如图 7.11 所示的高维插值效果图。

加载中...

图 7.11 高维插值效果


原网址: 访问
创建于: 2023-08-17 09:58:13
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论