擬合和插值
在實際中,常常要處理由實驗或測量所得到的一些離散數據。插值與擬合方法就是要通過這些數據去確定某一類知函數的參數或尋求某個近似函數,使所得到的近似函數與E知數據有較高的擬合精度。
插值
如果要求這個近似函數(曲線或曲面)經過所已知的所有數據點,則稱此類問題爲插值問題。(不需要函數
表達式)
擬合
如果不要求近似函數通過所有數據點,而是要求它能較好地反映數據變化規律的近似函數的方法稱爲數據擬合。(必須有函數表達式),近似函數不一定(曲線或曲面)通過所有的數據點。(在這種情況下,通常要求觀測數據相對比較準確,即不考慮觀測誤差的影響。)
插值和擬合的異同
(1)聯繫
都是根據實際中一-組已知數據來構造一個能夠反映數據變化規律的近似函數的方法。
(2)區別
插值問題不一定得到近似函數的表達形式, 僅通過插值方法找到末知點對應的值。數據擬合要求得到一個具體的近似函數的表達式。
觀測數據能否正確揭示某些變量之間的關係,往往取決於兩個方面
-
其一是觀測數據的準確性或準確程度,這是因爲在獲取觀測數據的過程中一般存在隨機測量誤差,導致所討論的變量成爲隨機變量。
-
其二是對觀測數據處理方法的選擇,即到底是採用插值方法還是用擬合方法,插值方法之中、擬合方法之中又選用哪一種插值或擬合技巧來處理觀測數據。
數據擬合
對於情況較複雜的實際問題(因素不易化簡,作用機理不詳)可直接使用數據組建模,尋找簡單的因果變量之間的數量關係,從而對未知的情形作預報。這樣組建的模型爲擬合模型。擬合模型的組建主要是 處理好觀測數據的誤差,使用數學表達式從數量上近似因果變量之間的關係。擬合模型的組建是通過對有關變量的觀測數據的觀察、分析和選擇恰當的數學表達方式得到的。
在科學計算中經常要根據給定函數的實驗數據,需要用比較簡單和合適的函數來逼近(或擬合)實驗數據。這種逼近的特點是:
(a) 適度的精度是需要的;
(b) 實驗數據有小的誤差;
© 對於某些問題,可能有某些特殊的信息能夠用來選擇實驗數據的數學模型。
數據擬合基本方法
最小二乘法
一函數表達式爲
其中 是一組事先選定的線性無關的函數, 是一組待定係數。尋求係數 使得 與 的距離 的平方和最小。這種準則稱爲最小二乘準則,其求係數的方法稱爲線性最小二乘擬合方法。
係數求法
若記
問題歸結爲,求使得J最小
具體怎麼弄 不推導,會用就行MATLAB就行,來直接看例子吧。
函數求法
一般先畫出數據的散點圖,通過散點圖的大體形狀來確定函數。
人們常用的曲線有
(1)直線
(2)多項式
(3)雙曲線(一支) ,擬合前作變量 替換t=1/x,求解a1,a2較簡單。
(4)指數曲線 ,擬合前作變量代換則指數曲線轉化爲線性函數,求解a1,a2較簡單。
MATLAB求解
語法 p = plotfit(x.y,n) 返回次數爲n的多項式p(x)的係數,該階數是y中數據的最佳擬合(在最小二乘方式中)。p中的係數按降冪排列,p的長度爲n+1
多項式在x處的值y可用下面的函數計算 y=polyval(a,x)
示例: 1949年- -1994年我國人口數據資料如下:
年份xi | 1949 | 1954 | 1959 | 1964 | 1969 | 1974 | 1979 | 1984 | 1989 | 1994 |
---|---|---|---|---|---|---|---|---|---|---|
人口數yi | 5.4 | 6.0 | 6.7 | 7.0 | 8.1 | 9.1 | 9.8 | 10.3 | 11.3 | 11.8 |
建模分析我國人口增長的規律,預報1999年我國人口數。
clear;
x= [1949 1954 1959 1964 1969 1974 1979 1984 1989 1994] ;
y=[5.4 6.0 6.7 7.0 8.1 9.1 9.8 10.3 11.3 11.8 ];
a=polyfit(x,y,1);
x1=1949:10:1994;
y1=a(2)+a(1)*x1; %模型一
b=polyfit(x,log(y),1);
y2=exp(b(2))*exp(b(1)*x1); %模型二
plot(x,y,'*')
hold on
plot(x1,y1,'--r')
hold on
plot(x1,y2,'-k')
legend('原曲線','模型一曲線','二曲線')
在MATLAB工作區都是可以看到a(1),a(2)的值的,a(2)也就是下面的a,a(1)就是下面的b
非線性最小二乘擬合
非線性最小二乘法是假設f (x)是待定係數的任意非線性函數,在最小二乘準則下求其係數
例如常用的雙曲線和指數曲線就是非線性最小二乘擬閤中最常用的非線性函數,只不過在上面使用中將它們轉變成線性最小二乘擬合方法。
例如當實驗數據具有單調性和凸性時,可選擇下述適當的數學模型y = f (x)來擬合實驗數據。其中a、b 爲參數。在有可能的情況下,一般將非線性擬合函數轉化爲線性擬合函數求解。
Matlab的提供了兩個求非線性最小二乘擬合的函數:lsqcurvefit和lsqnonlin。兩個命令都要先建立M-文件fun.m,在其中定義函數f(x),但兩者定義f(x)的方式是不同的,可參考例題.
用下面一組數據擬合 函數 中的參數a,b,k
該問題就是求最優解
lsqcurvefit函數求解
- 先建立函數的.m文件
function f=curvefun1(x,tdata)
f=x(1)+x(2)*exp(-0.02*x(3)*tdata)
%其中 x(1)=a; x(2)=b;x(3)=k;
- lsqcurvefit求解
tdata=100:100:1000;
cdata=1e-03*[4.54,4.99,5.35,5.65,5.90,6.10,6.26,6.39, 6.50,6.59];
plot (tdata,cdata,'*')
hold on
x0=[0.2,0.05,0.05];
x = lsqcurvefit ('curvefun1',x0,tdata,cdata)
f = curvefun1(x,tdata)
plot (tdata,f)
工作區中x的值爲,分別代表 a b k
0.00694062292915721 -0.00293659350172876 0.0809312312491527
lsqnonlin函數
function f=curvefun2(x)
tdata=100:100:1000;
cdata=1e-03*[4.54,4.99,5.35,5.65,5.90,6.10,6.26,6.39,6.50,6.59];
f=x(1)+x(2)*exp(-0.02*x(3)*tdata)- cdata
clc;clear;
x0=[0.82,0.5,0.05];
x=lsqnonlin('curvefun2',x0)
f= curvefun2(x)
x
插值
當數據量不夠,需要補充,且認定已有數據可信時,通常利用函數插值方法。
實際問題當中碰到的函數f (X)是各種各樣的,有的表達式很複雜,有的甚至給不出數學的式子,只提供了一些離散數據,讓我們用這些離散數據來預測其他值。
插值方法
在實際問題中所遇到的插值問題一般分爲 一維插值問題和二維插值問題。
常見的有:
(1)拉格朗日插值(lagrange插值)
(2)分段線性插值
(3) Hermite
(4)三次樣條插值。
拉格朗日插值(高次多項式插值):
- 曲線光滑;誤差估計有表達式
- 收斂性不能保證(振盪現象)
- 用於理論分析,實際意義不大
分段線性插值:
- 收斂性良好
- 只用兩個節點,且線性,簡單實用
- 曲線不光滑
三次樣條插值:(*)
- 曲線2階光滑,收斂性有保證
- 實際中應用廣泛
- 誤差估計較難
常見的插值函數
函數 | 說明 |
---|---|
interp1 | 一維數據插值(表查找) |
interp2 | meshgrid格式的二維網格數據的插值 |
interp3 | meshgrid格式的三維網格數據的插值 |
griddata | 插入二維或三維散點數據 |
一維插值
如圖,有n+1個節點&(x_j,y_j),(j=0…n)&,這些節點是找不到某些函數來對其擬合,或者函數極爲複雜,現在要求任意一點的值
拉格朗日插值
已知函數f(x)在個點處的函數值爲 。求一n次多項式函數Pn(x),使其滿足
解決此問題的拉格朗日插值多項式公式爲
其中$L_i(x) $爲n次多項式
稱爲拉格朗日插值基函數
如兩點一次(線性)插值多項式:
三點二次(拋物)插值多項式:
分段線性插值
計算量與n無關;
n越大,誤差越小.
三次樣條插值
g(x)爲被插值函數。
用MATLAB作插值計算
一維插值函數:
- : 處的插值結果
- x y 是插值節點
- 是被插值點
- method是插值方法
插值方法有:
‘nearest’ :最鄰近插值
‘linear’ : 線性插值;
‘spline’ : 三次樣條插值;
‘cubic’ : 立方插值。
缺省時: 分段線性插值。
下面來看下這些方法的一些區別
注意:所有的插值方法都要求x是單調的,並且不能夠超過x的範圍
例:在1-12的11小時內,每隔1小時測量一次溫度,測得的溫度依次爲:5,8,9,15,25,29,31,30,22,25,27,24。試估計每隔1/10小時的溫度值。
clear
hours=1:12;
temps=[5 8 9 15 25 29 31 30 22 25 27 24];
h=1:0.1:12;
t=interp1(hours,temps,h,'spline')
t1=interp1(hours,temps,h,'line')
plot(hours,temps,'+',h,t,'r :',h,t1,'b')
legend('原值','三次樣條','線性')
xlabel('Hour'),ylabel('Degrees Celsius')
t(1:10:100)
t1(1:10:100)
這隻輸出了每隔一小時測量的溫度
5.6242 8.0544 9.3052 15.9739 25.7091 29.2136 31.1755 29.2905 21.7705 25.4456
5.3000 8.1000 9.6000 16.0000 25.4000 29.2000 30.9000 29.2000 22.3000 25.2000
例 已知飛機下輪廓線上數據如下,求x每改變0.1時的y值。
這裏用了三種插值的方法
clear
clc
x0=[0 3 5 7 9 11 12 13 14 15 ];
y0=[0 1.2 1.7 2.0 2.1 2.0 1.8 1.2 1.0 1.6 ];
x=0:0.1:15;
y1=lagr1(x0,y0,x);
y2=interp1(x0,y0,x);
y3=interp1(x0,y0,x,'spline');
subplot(3,1,1)
plot(x0,y0,'*',x,y1,'r')
grid
title('lagrange')
subplot(3,1,2)
plot(x0,y0,'*',x,y2,'r')
grid
title('piecewise linear')
subplot(3,1,3)
plot(x0,y0,'*',x,y3,'r')
grid
title('spline')
y1(1:10:150)
y2(1:10:150)
y3(1:10:150)
y1(1:10:150)
0 -15.9238 -5.4272 1.2000 2.2666 1.7000 1.6249 2.0000 2.2040 2.1000 1.9904 2.0000 1.8000 1.2000 1.0000
y2(1:10:150)
0 0.4000 0.8000 1.2000 1.4500 1.7000 1.8500 2.0000 2.0500 2.1000 2.0500 2.0000 1.8000 1.2000 1.0000
y3(1:10:150)
0 0.4665 0.8649 1.2000 1.4767 1.7000 1.8740 2.0000 2.0773 2.1000 2.0668 2.0000 1.8000 1.2000 1.0000
二維插值
第一種(網格節點):
第二種(散亂節點):
用MATLAB作網格節點數據的插值
- z: 被插值點的函數值
- x0,y0,z0: 插值節點
- x,y : 被插值點
- mrthod 插值方法
插值方法:
‘nearest’ 最鄰近插值
‘linear’ 雙線性插值
‘cubic’ 雙三次插值
缺省時, 雙線性插值
要求x0,y0單調;x,y可取爲矩陣,或x取行向量,y取爲列向量,x,y的值分別不能超出x0,y0的範圍。
例:測得平板表面3*5網格點處的溫度分別爲: 82 81 80 82 84 79 63 61 65 81 84 84 82 85 86
試作出平板表面的溫度分佈曲面z=f(x,y)的圖形。
注意interp2(x,y,temps,xi,yi’ yi得轉化爲他的轉置矩陣( yi’ )纔行)
x=1:5;
y=1:3;
temps=[82 81 80 82 84;79 63 61 65 81;84 84 82 85 86];
mesh(x,y,temps)
pause(1.5) %暫停1.5秒繼續運行
xi=1:0.2:5;
yi=1:0.2:3;
figure(2)
z1i=interp2(x,y,temps,xi,yi','nearest'); %最近鄰插值
mesh(xi,yi,z1i)
xlabel('X'),ylabel('Y'),zlabel('Z')
pause(1.5)
figure(3)
z2i=interp2(x,y,temps,xi,yi'); %雙線性插值
mesh(xi,yi,z2i)
xlabel('X'),ylabel('Y'),zlabel('Z')
pause(1.5)
figure(4)
z3i=interp2(x,y,temps,xi,yi','cubic'); %雙三次插值
mesh(xi,yi,z3i)
xlabel('X'),ylabel('Y'),zlabel('Z')
原圖
最近鄰插值
雙線性插值
雙三次插值
clear
x=1200:400:4000;
y=1200:400:3600;
z=[1130 1250 1280 1230 1040 900 500 700;
1320 1450 1420 1400 1300 700 900 850;
1390 1500 1500 1400 900 1100 1060 950;
1500 1200 1100 1350 1450 1200 1150 1010;
1500 1200 1100 1550 1600 1550 1380 1070;
1500 1550 1600 1550 1600 1600 1600 1550;
1480 1500 1550 1510 1430 1300 1200 980];
subplot(221)
meshz(x,y,z)
xlabel('X'),ylabel('Y'),zlabel('Z')
title('原圖')
subplot(222)
x1 = 1200:50:4000;
y1 = 1200:50:3600;
z1 = interp2(x,y,z,x1,y1','nearest');
surfc(x1,y1,z1)
title('最近鄰插值')
subplot(223)
z2 = interp2(x,y,z,x1,y1');
surfc(x1,y1,z2)
title('雙線性插值')
subplot(224)
z3 = interp2(x,y,z,x1,y1','cubic');
surfc(x1,y1,z3)
title('雙三次插值')
用MATLAB作散點數據的插值計算
- cz 被插值點的函數值
- x y z 是插值節點
- cx cy 是被插值點
- method是插值方法
-
要求cx取行向量,cy取爲列向量。
插值方法有:
‘nearest’ 最鄰近插值
‘linear’ 雙線性插值
‘cubic’ 雙三次插值
‘v4’- Matlab提供的插值方法
缺省時, 雙線性插值
clear
x=[129 140 103.5 88 185.5 195 105.5 157.5 107.5 77 81 162 162 117.5];
y=[7.5 141.5 23 147 22.5 137.5 85.5 -6.5 -81 3 56.5 -66.5 84 -33.5];
z=[-4 -8 -6 -8 -6 -8 -8 -9 -9 -8 -8 -9 -4 -9];
cx=75:0.5:200;
cy=-70:0.5:150;
cz=griddata(x,y,z,cx,cy','cubic');
mesh(cx,cy,cz),rotate3d
xlabel('X'),ylabel('Y'),zlabel('Z')
%pause
figure(2),contour(cx,cy,cz,[-5 -5]);grid
hold on
plot(x,y,'+')
xlabel('X'),ylabel('Y')
[a,b]=find(cz>-5)