1 函数拟合
函数拟合在工程(如采样校正)和数据分析(如隶属函数确定)中都是非常有用的工具。我这里将函数拟合分为三类:分别是多项式拟合,已知函数类型的拟合和未知函数类型的拟合。matlab中关于函数的拟合提供了很多的拟合函数,这里不再一一介绍。仅对常用的多项式拟合和已知函数类型的拟合中一部分matlab函数的使用进行介绍。
1.1多项式拟合
对于
形式的拟合函数,其中
为待定系数。我们可以使用matlab中的polyfit
函数进行拟合。函数的调用形式为:
coef = polyfit(xx,yy,n);
其中xx,yy分别为已知的自变量和因变量数据,n为拟合的阶次。下面是一个使用的例子。
clear
clc %清除
%设置参数
xx = [1,2,3,4,5];
yy = [6.1,7.2,8.1,9.2,10.1];
n = 1; %选择一阶拟合
%下面代码不用修改
coef = polyfit(xx,yy,n);
%上面已经求出结果,下面是进行绘图显示
Fun = poly2sym(coef) %显示拟合函数
xmax = max(xx);
xmin = min(xx);
xnum = 2*length(x1)+50;
x = linspace(xmin,xmax,xnum);
y = polyval(coef,x);
plot(xx,yy,\'o\',x,y);
title(char(Fun))
运行完成后,会在matlab命令行窗口显示Fun=x+257/50
.同时会绘图如下:
上面这段代码可以直接拿来使用,只需要改动xx,yy,n
即可。后面的代码不需要修改。为了进一步方便使用,我简单的制作了一个GUI界面,同样只需要设定相关值,点击开始拟合就可以拟合了。
简单的GUI界面
如下所示:
1.2已知函数类型的拟合
我们在数据分析的时候经常遇到这种情况:知道了函数的隶属函数和隶属函数上的一些点,求隶属函数的待定系数。由于隶属函数基本都不是多项式的形式,于是我们就不能使用ployfit
函数了。这里我以拟合偏大型柯西分布隶属函数和对数隶属函数为例,介绍fit
和nlinfit
在已知函数类型时的拟合应用。
关于函数的具体用法我这里就不介绍了,大家可以在matlab中doc一下帮助文件,也可以上网查询相关介绍。如果着急使用又不想了解原理的话可以直接修改下面程序中需要拟合的数据和函数类型即可。
假设需要拟合的偏大型柯西分布隶属函数和对数函数组合的分段函数如下所示:
其中待定系数
同时给出已知数据点
分别采用fit
和nlinfit
对第二段偏大型柯西分布隶属函数拟合代码如下:
clear
clc %清除工作空间
syms x;
%公共参数设置
xx=[3,5]\'; %这里设置已知自变量向量(列向量)
yy = [0.8,1]\'; %对应因变量(列向量)
startPos = [1,1]; %设置系数的起始搜索点
%使用fit函数拟合的
%设置参数
f = \'(1+alpha*(x-belta)^(-2))^(-1)\'; %设置需要拟合的函数形式
funType=fittype(f,\'independent\',\'x\',...
\'coefficients\',{\'alpha\',\'belta\'}); %在independent后面设置自变量,在coefficients后面设置待定系数(多个值用{}括起来)
%使用nlinfit函数进行拟合的
%设置参数
f1 = @(coef,x)(1+coef(1)*(x-coef(2)).^(-2)).^(-1); %设置需要拟合的函数(内联函数形式)
%后面的代码不用改
%fit拟合相关代码
opt=fitoptions(funType);
set(opt,\'StartPoint\',startPos);
cfun=fit(xx,yy,funType,opt) %命令行显示结果
plot(cfun,\'r\',xx,yy,\'*\')
%nlinfit拟合相关代码
coef=nlinfit(xx,yy,f1,startPos);
disp(\'nlinfit拟合后的系数矩阵为:\');
disp(coef);
hold on
xmax = max(xx);
xmin = min(xx);
xnum = 2*length(xx)+50;
x = linspace(xmin,xmax,xnum);
y = f1(coef,x);
plot(x,y,\'g\');
legend(\'原始数据\',\'fit拟合\',\'nlinfit拟合\')
两种方法的拟合结果会在命令行中显示,同时给出拟合绘图结果如下图所示:
函数使用介绍:
- 只需要在参数设置的地方设置相关参数即可。
- nlinfit函数拟合时采用内联函数的形式,需要主要系数和自变量都是一个向量,自己要将向量的每个元素和实际系数对应好。
- fit拟合函数采用符号表达式的形式,所以函数看起来就顺眼多了。但是那些符号是自变量哪些是系数要写清楚。
- 事实上,这两个函数不仅支持单自变量拟合,还可以进行多自变量拟合,但是后面不需要改的代码也要自己该。因为plot绘制不了多变量图形。
函数特点介绍:
- 一般这种函数的拟合都采用的搜索算法,因此得到的解基本没用“最优解”(如果有最优解的话使用solve应该能解出来)。
- 搜索算法都比较依赖第一个初始搜索点,startPos的设置也非常关键。不同的起始搜索点得到的结果可能不一样。
- 当然搜索算法的不同得到的结果也可能不一样(比如上面两种)。这也是matlab中有那么多拟合函数的原因(还有lsqcurvefit,regress等)。将每个函数看出一个专家的话,这个诊断不出来,可以换一个专家看看。
照猫画虎我们可以对前面的对数函数进行拟合。修改设置参数部分代码如下:
%公共参数设置
xx=[1,3]\'; %这里设置已知自变量向量(列向量)
yy = [0.01,0.8]\'; %对应因变量(列向量)
startPos = [1,1]; %设置系数的起始搜索点
%使用fit函数拟合的
%设置参数
f = \'a*log(x)+b\'; %设置需要拟合的函数形式
funType=fittype(f,\'independent\',\'x\',...
\'coefficients\',{\'a\',\'b\'}); %在independent后面设置自变量,在coefficients后面设置待定系数(多个值用{}括起来)
%使用nlinfit函数进行拟合的
%设置参数
f1 = @(coef,x)coef(1)*log(x)+coef(2); %设置需要拟合的函数(内联函数形式)
同样命令空间会给出拟合后的结果以及显示拟合后的曲线。
可以看出这回两种方法拟合的结果完全一样,后面绘制的曲线已经完全挡住了先绘制的。采用不同的方法,不同的起始搜索位置得到了相同的结果往往说明这个结果非常接近全局最优点。
ps:关于函数形式未知的函数拟合,我好久都没用到过了也懒得总结。或许以后再用到时会将这一部分内容补上吧!或许吧~~其实如果我们不知道函数的形式,使用插值往往更好一些。因为函数的拟合往往都需要运气,并不一定能成功。而插值基本都会成功了。