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:關於函數形式未知的函數擬合,我好久都沒用到過了也懶得總結。或許以后再用到時會將這一部分內容補上吧!或許吧~~其實如果我們不知道函數的形式,使用插值往往更好一些。因為函數的擬合往往都需要運氣,並不一定能成功。而插值基本都會成功了。