MATLAB擬合和插值


定義

插值和擬合:

曲線擬合是指您擁有散點數據集並找到最適合數據一般形狀的線(或曲線)。

插值是指您有兩個數據點並想知道兩者之間的值是什么。中間的一半是他們的平均值,但如果你只想知道兩者之間的四分之一,你必須插值。

 

擬合

我們着手寫一個線性方程圖的擬合:

y=3x^3+2x^2+x+2

首先我們生成一組數據來分析:

x=-5:0.5:5;
e=50*rand(1,length(x))-25;%制造[-25,25]的隨機數作為誤差
y=3*x.^3+2*x.^2+x+2+e;%得到y值
plot(x,y,'.')

 

x =

  Columns 1 through 6

   -5.0000   -4.5000   -4.0000   -3.5000   -3.0000   -2.5000

  Columns 7 through 12

   -2.0000   -1.5000   -1.0000   -0.5000         0    0.5000

  Columns 13 through 18

    1.0000    1.5000    2.0000    2.5000    3.0000    3.5000

  Columns 19 through 21

    4.0000    4.5000    5.0000


y =

  Columns 1 through 6

 -350.0110 -248.6360 -169.3421  -89.5653  -88.2298  -57.7238

  Columns 7 through 12

  -32.5505    2.3308   11.5861    9.0123   -0.4538    5.7254

  Columns 13 through 18

   -2.1840   30.3596   20.4478   73.2138   88.1756  152.0492

  Columns 19 through 21

  236.2809  334.3864  411.0563

 

這時候x,y作為已知數據存在,要求我們擬合x,y的散點圖,這時候會用到polyfit這個函數。

語法

p = polyfit(x,y,n)
[p,S] = polyfit(x,y,n)
[p,S,mu] = polyfit(x,y,n)

說明

p = polyfit(x,y,n) 返回階數為 n 的多項式 p(x) 的系數,該階數是 y 中數據的最佳擬合(在最小二乘方式中)。p 中的系數按降冪排列,p 的長度為 n+1

[p,S] = polyfit(x,y,n) 還返回一個結構體 S,后者可用作 polyval 的輸入來獲取誤差估計值。

[p,S,mu] = polyfit(x,y,n) 還返回 mu,后者是一個二元素向量,包含中心化值和縮放值。mu(1) 是 mean(x),mu(2) 是 std(x)。使用這些值時,polyfit 將 x 的中心置於零值處並縮放為具有單位標准差 

 

plot(x,y,'.')%已知數據的散點圖
hold on
d=polyfit(x,y,2);%進行線性擬合,假設函數為二次函數
y1=d(1)*x.^2+d(2)*x+d(3);
plot(x,y1)//繪制猜測的函數

  

明顯不符合,我們繼續猜測

plot(x,y,'.')
hold on
d=polyfit(x,y,3);
y1=d(1)*x.^3+d(2)*x.^2+d(3)*x+d(4);
plot(x,y1)

擬合成功。

 

插值

一維插值

以上面的數據為例子 

 

x=-5:0.5:5;
e=50*rand(1,length(x))-25;%制造[-25,25]的隨機數作為誤差
y=3*x.^3+2*x.^2+x+2+e;%得到y值
%插值
x2=-5:0.1:5;
y2=interp1(x,y,'x2,'spline');
plot(x2,y2,'r+')

 

二維插值

語法

[X,Y] = meshgrid(x,y)

[X,Y] = meshgrid(x)

[X,Y,Z] = meshgrid(x,y,z)

[X,Y,Z] = meshgrid(x)

說明

[X,Y] = meshgrid(x,y) 基於向量 x 和 y 中包含的坐標返回二維網格坐標。X 是一個矩陣,每一行是 x 的一個副本;Y 也是一個矩陣,每一列是 y 的一個副本。坐標 X 和 Y 表示的網格有 length(y) 個行和 length(x) 個列。

[X,Y] = meshgrid(x) 與 [X,Y] = meshgrid(x,x) 相同,並返回網格大小為 length(x)×length(x) 的方形網格坐標。

[X,Y,Z] = meshgrid(x,y,z) 返回由向量 x、y 和 z 定義的三維網格坐標。X、Y 和 Z 表示的網格的大小為 length(y)×length(x)×length(z)。

[X,Y,Z] = meshgrid(x) 與 [X,Y,Z] = meshgrid(x,x,x) 相同,並返回網格大小為 length(x)×length(x)×length(x) 的三維網格坐標。

 

我們先繪制一個三維的圖像

[x,y]=meshgrid(-5:1:5,-10:2:10);
z=12-x.^3-y.^3;
surf(x,y,z)

給人的感覺是很“粗糙”的,這時候我們使用插值,增加數據。

[x0,y0]=meshgrid(-5:0.2:5,-10:0.4:10);
z0=interp2(x,y,z,x0,y0,'spline');
surf(x0,y0,z0)

 

 

例題

例1

1、 已知以下實驗測量數據,

1

1.5

2.5

3

4.5

-0.86

13.66

90.25

152.57

473.70

(1) 請畫出以上數據的散點圖;

(2) 請用合適的多項式擬合上述數據;

(3) 請用三次樣條一次插值以上數據.

2、 已知網格化數據如下:

         

-1

-0.5

0

0.5

1

-2

1.77

1.12

0.32

0.44

-2.35

-1

1.62

1.29

0.94

-1.49

-0.78

0

0.23

-1.01

-0.74

1.08

-0.13

1

-0.61

-0.41

-0.63

-0.05

1.44

2

-2.94

-0.22

0.56

0.17

1.73

                               

              

               

 

 

 

 

 

請用三次樣條二次插值法插出更光滑精細的曲面.  

答案

%1-(1)
clc,clear
x=[1 1.5	2.5 3 4.5];
y=[-0.86	13.66 90.25 152.57 473.70];
plot(x,y,'.');

%1-(2)
d=polyfit(x,y,1);
y1=d(1)*x+d(2);
plot(x,y,'.');
plot(x,y1);%對比線性圖與散點圖,發現不匹配
d=polyfit(x,y,2);
y1=d(2)*x.^2+d(2)*x+d(3);
plot(x,y,'.');
plot(x,y1);%對比線性圖與散點圖,發現匹配成功,擬合完成

%1-(3)
x=[1 1.5 2.5 3 4.5];
y=[-0.86	13.66 90.25 152.57 473.70];
x1=[1:0.1:4.5];
y1=interp1(x,y,x1,'spline');
plot(x,y,x1,y1);

%2
[x1,y1]=meshgrid(-2:1:2,-1:0.5:1);
z1=[1.77 1.21 0.32 0.44 -2.35;1.62 1.29 0.94 -1.49 -0.78;0.23 -1.01 -0.74 1.08 -0.13;...
-0.61 -0.41 -0.63 -0.05 1.44;-2.94 -0.22 0.56 0.17 1.73];
surf(x1,y1,z1)
[x,y]=meshgrid(-1:0.1:1, -2:0.2:2);
z=interp2(x1,y1,z1,x,y,'spline');
surf(x,y,z)

 

例2

數據:點擊下載

實際任務就是sheet2中中的元素,只給了單周的元素數據,沒有給偶數周,這就需要我們插值出來

 

答案

clc,clear
%% 讀取數據
ydatas = xlsread('data1.xls',2,'C5:J17');
% 清除無效數據
ydatas(9:10,:)=[];

%% 繪圖准備
% y坐標軸名稱
yname = ["周數","輪蟲(10^6/L)","溶氧(mg/l)","COD(mg/l)","水溫(℃)","PH值","鹽度","透明度(cm)","總鹼度","氯離子","透明度","生物量"];
% yname = {'輪蟲(10^6/L)','溶氧(mg/l)','COD(mg/l)','水溫(℃)','PH值','鹽度','透明度(cm)','總鹼度','氯離子','透明度','生物量'};
% x坐標
xdatas =  1:2:15;
xval = 1:15;

%% 線性插值
figure(1)
yval1 = [];
for index=1:11
    tmp = interp1(xdatas,ydatas(index,:),xval,'linear');
    yval1 = [yval1;tmp];
    subplot(3,4,index)
    plot(xdatas,ydatas(index,:),'*',xval,tmp,'--r')
    xlabel('時間/周');
    ylabel(yname(index+1))
    legend('原始數據','線性插值數據')
end

%% 三次樣條插值
figure(2)
yval2 = [];
for index=1:11
    tmp = interp1(xdatas,ydatas(index,:),xval,'spline');
    yval2 = [yval2;tmp];
    subplot(3,4,index)
    plot(xdatas,ydatas(index,:),'*',xval,tmp,'--r')
    xlabel('時間/周');
    ylabel(yname(index+1))
    legend('原始數據','三次樣條插值數據')
end

%% 三次多項式插值
figure(3)
yval3 = [];
for index=1:11
    tmp = interp1(xdatas,ydatas(index,:),xval,'pchip');
    yval3 = [yval3;tmp];
    subplot(3,4,index)
    plot(xdatas,ydatas(index,:),'*',xval,tmp,'--r')
    xlabel('時間/周');
    ylabel(yname(index+1))
    legend('原始數據','三次多項式插值數據')
end
%% 數據存儲
new_data1 = [xval;yval1];
new_data1 = [yname',new_data1];
xlswrite('output.xls',new_data1,'Sheet1');
new_data2 = [xval;yval2];
new_data2 = [yname',new_data2];
xlswrite('output.xls',new_data2,'Sheet2');
new_data3 = [xval;yval3];
new_data3 = [yname',new_data3];
xlswrite('output.xls',new_data3,'Sheet3');

輸出結果數據:https://www.lanzous.com/iau54la

 

例3

數據下載:點擊下載

 

答案

clc,clear
%%
xdatas = xlsread('data2.xlsx','A2:A11');
ydatas = xlsread('data2.xlsx','B2:B11');
a=polyfit(xdatas,ydatas,1);
y1=a(1)*xdatas+a(2);
subplot(3,2,1)
plot(xdatas,y1,'r-',xdatas,ydatas,'*')
title('一次擬合');
xlabel('年份');
ylabel('人口/萬');
y1_datas = a(1)*xdatas+a(2);
ssr1 = sum((y1_datas-mean(ydatas)).^2);
sst1 = sum((ydatas-mean(ydatas)).^2);
r1_sq = ssr1/sst1;
txt = ['R^2=' num2str(r1_sq)];
text(2010,138000,txt)

%%
b=polyfit(xdatas,ydatas,2);
y2=b(1)*xdatas.^2+b(2)*xdatas+b(3);
subplot(3,2,2)
plot(xdatas,y2,'r-',xdatas,ydatas,'*')
title('二次擬合');
xlabel('年份');
ylabel('人口/萬');
y2_datas = b(1)*xdatas.^2+b(2)*xdatas+b(3);
ssr2 = sum((y2_datas-mean(ydatas)).^2);
sst2 = sum((ydatas-mean(ydatas)).^2);
r2_sq = ssr2/sst2;
txt = ['R^2=' num2str(r2_sq)];
text(2010,138000,txt)

%% 
c=polyfit(xdatas,ydatas,3);
y3=c(1)*xdatas.^3+c(2)*xdatas.^2+c(3)*xdatas+c(4);
subplot(3,2,3)
plot(xdatas,y3,'r-',xdatas,ydatas,'*')
title('三次擬合');
xlabel('年份');
ylabel('人口/萬');
y3_datas = c(1)*xdatas.^3+c(2)*xdatas.^2+c(3)*xdatas+c(4);
ssr3 = sum((y3_datas-mean(ydatas)).^2);
sst3 = sum((ydatas-mean(ydatas)).^2);
r3_sq = ssr3/sst3;
txt = ['R^2=' num2str(r3_sq)];
text(2010,138000,txt)

%%
d=polyfit(xdatas,ydatas,4);
y4=d(1)*xdatas.^4+d(2)*xdatas.^3+d(3)*xdatas.^2+d(4)*xdatas+d(5);
subplot(3,2,4)
plot(xdatas,y4,'r-',xdatas,ydatas,'*')
title('四次擬合');
xlabel('年份');
ylabel('人口/萬');
y4_datas = d(1)*xdatas.^4+d(2)*xdatas.^3+d(3)*xdatas.^2+d(4)*xdatas+d(5);
ssr4 = sum((y4_datas-mean(ydatas)).^2);
sst4 = sum((ydatas-mean(ydatas)).^2);
r4_sq = ssr4/sst4;
txt = ['R^2=' num2str(r4_sq)];
text(2010,138000,txt)

%%
e=polyfit(xdatas,ydatas,5);
y5=e(1)*xdatas.^5+e(2)*xdatas.^4+e(3)*xdatas.^3+e(4)*xdatas.^2+e(5)*xdatas+e(6);
subplot(3,2,5)
plot(xdatas,y5,'r-',xdatas,ydatas,'*')
title('五次擬合');
xlabel('年份');
ylabel('人口/萬');
y5_datas = e(1)*xdatas.^5+e(2)*xdatas.^4+e(3)*xdatas.^3+e(4)*xdatas.^2+e(5)*xdatas+e(6);
ssr5 = sum((y5_datas-mean(ydatas)).^2);
sst5 = sum((ydatas-mean(ydatas)).^2);
r5_sq = ssr5/sst5;
txt = ['R^2:' num2str(r5_sq)];
text(2010,138000,txt)

通過對數據擬合,對比確定系數,反應擬合效果,確定出最佳擬合函數為四次擬合函數:y = 0.26*x^4-2.06*x^3+6.21*x^2-8.32*x+4.19


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM