插 值 |
|
已知在互不相同的多个点 处,函数) 分别取到函数值 构造一个最高次数不超过 的多项式 ,使其满足 然后用 来作为 的近似值,这种方法为插值法。如果要求近似函数(曲线或曲面)经过所已知的所有数据点,这类问题就是插值。 |
都是根据实际中一组已知数据来构造一个能够反映数据变化规律的近似函数的方法。
1、插值:是在离散数据的基础上补插连续函数,使得插值函数通过全部给定的离散样本点。插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值。总之,插值是求过一组已知点的近似函数。 拟合:是用一个连续函数(曲线)靠近给定的离散数据,使其与给定的数据相吻合。拟合也是根据一组已知点求近似函数,但不要求过已知点。 因此,插值和拟合都是根据一组已知样本点,求变化规律和特征相似的近似曲线的过程。但是插值要求近似曲线完全经过所有的给定数据点,而拟合只要求近似曲线在整体上尽可能接近数据点,并反映数据的变化规律和发展趋势。 2、插值也可以看作是一种特殊的拟合,是要求误差函数为0的拟合。由于数据点通常都带有误差,误差为0往往意味着过度拟合,过拟合模型对于训练集以外的数据的泛化能力往往是较差的。因此在实践中,插值多用于图像处理和缺失数据处理,拟合多用于实验数据处理。 3、当实验数据精度较高且数量较少是可以优先考虑插值, 而实验数据精度较低且数目较多,而数据整体上呈现一定的趋势时可以考虑拟合。 |
例1: 已知飞机下轮廓线上数据如下: |
x | 0 | 3 | 5 | 7 | 9 | 11 | 12 | 13 | 14 | 15 |
y | 0 | 1.2 | 1.7 | 2.0 | 2.1 | 2.0 | 1.8 | 1.2 | 1.0 | 1.6 |
matlab代码:
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_2=0:0.1:15;
y_f1=Lagrange(x0,y0,x_2);
y_f2=interp1(x0,y0,x_2);
y_f3=interp1(x0,y0,x_2,'spline');
subplot(3,1,1);
plot(x0,y0,'*',x_2,y_f1,'-');
grid;
title('拉格朗日插值');
subplot(3,1,2);
plot(x0,y0,'r^',x_2,y_f2,'-b');
grid;
title('线性插值');
subplot(3,1,3);
plot(x0,y0,'ro',x_2,y_f3,'-b');
grid;
title('三次样条插值');
总结:由图可知,拉格朗日插值出现外沿振荡现象,三次样条插值所得的曲线逼近函数值,线条也具有光滑性。所以采用三次样条插值效果更好。 |
例2:一组数据如下所示: |
1 | 2 | 3 | 4 | 5 | |
1 | 34 | 40 | 41 | 41 | 39 |
2 | 36 | 41 | 45 | 47 | 46 |
3 | 33 | 39 | 43 | 50 | 47 |
4 | 32 | 40 | 44 | 45 | 46 |
5 | 28 | 35 | 40 | 41 | 42 |
Matlab代码部分: |
x = 1:1:5;
y = 1:1:5;
z = [34 40 41 41 39
36 41 45 47 46
33 39 43 50 47
32 40 44 45 46
28 35 40 41 42];
x0 = 1:0.1:5;
y0 = 1:0.1:5;
mesh(x,y,z);
title('插值前二维图')
z0 = interp2(x,y,z,x0,y0','spline'); % 注意y_1'是转置(列向量)
mesh(x0,y0,z0);
title('三次样条插值');
例三:一组数据如下所示: |
x | 13 | 14 | 10 | 8 | 18 | 19 | 10 | 16 | 10 | 7 | 8 | 16 | 16 | 12 |
y | 0.7 | 14 | 2 | 15 | 2 | 13 | 9 | -1 | -8 | 0.3 | 6 | -7 | 8 | -3 |
z | 4 | 8 | 6 | 8 | 9 | 8 | 8 | 9 | 9 | 8 | 8 | 9 | 4 | 9 |
Matlab代码部分: |
1. x = [13 14 10 8 18 19 10 16 10 7 8 16 16 12];
2. y = [0.7 14 2 15 2 13 9 -1 -8 0.3 6 -7 8 -3];
3. z = [4 8 6 8 6 8 8 9 9 8 8 9 4 9];
4. %mesh(x,y,z)
5. [x0,y0] =meshgrid(5:0.1:20,-5:0.1:20)
6. z1 = griddata(x,y,z,x0,y0,'cubic');
7. mesh(x0,y0,z1)
8. title('三次插值图')
9. z2 = griddata(x,y,z,x0,y0,'linear');
10. mesh(x0,y0,z2)
11. title('线性插值图')
|
-
插值Python实现
-
-
一维插值
-
例1:飞机下轮廓线上数据Anaconda(Jupyter)
1. #导入第三方库
2. import numpy as np
3. import matplotlib.pyplot as plt
4. from scipy.interpolate import interp1d
5. from scipy.interpolate import lagrange
6. from six.moves import xrange
7.
8. x = [0,3,5,7,9,11,12,13,14,15]
9. y = [0,1.2,1.7,2.0,2.1,2.0,1.8,1.2,1.0,1.6]
10. f_x0 = interp1d(x,y,kind='cubic') #三次样条插值 注:f(x)是函数
11. f_x1 = lagrange(x,y) #拉格朗日插值
12. f_x2 = interp1d(x,y,kind='linear') #线性插值
13.
14. x_int = np.linspace(0,15,1000) #插值的数据点集x_int
15. y_int = f_x0(x_int) #调用函数f(x),计算x_int的函数值
16. y_intL = f_x1(x_int)
17. y_intlin = f_x2(x_int)
18.
19. #绘图
20. plt.scatter(x,y,c='b',marker='o',label= 'scatter')
21. plt.plot(x_int,y_int,c = 'r',label = 'cubic')
22. plt.plot(x_int,y_intlin,c = 'g',label = 'linear')
23. plt.legend(loc = 'lower right')
24. plt.show()
25.
26. plt.plot(x_int,y_intL,c = 'g',label = 'Largrange')
27. plt.legend(loc = 'lower right')
28. plt.show()
-
-
二维插值
-
例2:节点均匀Anaconda(Jupyter)
1. import numpy as np
2. import matplotlib.pyplot as plt
3. from scipy.interpolate import interp2d
4. import matplotlib as mpl
5.
6. x = np.linspace(1,5,5)
7. y = np.linspace(1,5,5)
8. xx,yy = np.meshgrid(x,y) # 生成网格点的坐标 xx,yy (二维数组)
9. z = [[34,40,41,41,39],
10. [36,41,45,47,46],
11. [33,39,43,50,47],
12. [32,40,44,45,46],
13. [28,35,40,41,42]]
14.
15. f_1 = interp2d(xx,yy,z,kind='cubic') # 三阶样条插值
16. xnew = np.linspace(1,5,100)
17. xnew_1 = np.linspace(1,5,5)
18. ynew = np.linspace(1,5,100)
19. ynew_1 = np.linspace(1,5,5)
20. znew =f_1(xnew,ynew) # 计算插值函数在f_1(xnew, ynew)所描述网格点集的函数值
21. znew_1 =f_1(xnew_1,ynew_1)
22.
23. #绘图
24. fig = plt.figure(figsize = (12,8))
25. ax1 = plt.subplot(1,2,1,projection='3d')
26. ax1.set_title("2-D original data")
27. ax1.plot_wireframe(xx,yy,znew_1,rstride = 2,cstride = 2,linewidth = 1)
28. surf1 = ax1.plot_surface(xx,yy,znew_1,rstride = 2,cstride = 2,cmap='rainbow')
29. xxnew, yynew = np.meshgrid(xnew, ynew) # 将一维数组 xnew, ynew 转换为网格点集(二维数组)
30. #print("\txxnew:{},yynew:{},znew:{}".format(xxnew.shape,yynew.shape,znew.shape))
31. ax2 = plt.subplot(1,2,2, projection='3d') # 3D 绘图要求 x,y,z 都是 n*m 二维数组
32. ax2.set_title("2-D cubic data")
33. ax2.plot_wireframe(xxnew, yynew,znew,rstride = 2,cstride = 2,linewidth = 1)
34. surf2 = ax2.plot_surface(xxnew,yynew,znew,rstride = 2,cstride = 2,cmap='rainbow')
35. plt.show()