基本介绍
首先介绍一下插值和拟合的概念
插值:求过已知有限个数据点的近似函数。
拟合:已知有限个数据点,求近似函数,不要求过已知数据点,只要求在某种意义下它在这些点上的总偏差最小。
插值和拟合都是要根据一组数据构造一个函数作为近似,由于近似的要求不同,二者的数学方法上是完全不同的。而面对一个实际问题,究竟应该用插值还是拟合,有时容易确定,有时则并不明显。
这是书上的举的一个例子
插值函数经过样本点,拟合函数一般基于最小二乘法尽量靠近所有样本点穿过。常见插值方法有 拉格朗日插值法 、 分段插值法 、 样条插值法:
拉格朗日插值
拉格朗日插值多项式:当节点数 n 较大时,拉格朗日插值多项式次数较高,可能收敛不一致,且计算复杂。
高次插值带来误差的震动现象称为 “龙格现象” 。
然后接着,我们就需要看一个拉格朗日插值多项式
上式称为n次 Lagrange 插值多项式,由方程(3)解的唯一性,n +1个节点的n次Lagrange 插值多项式存在唯一。
分段插值
分段插值:虽然收敛,但光滑性较差。
简单地说,将每两个相邻的节点用直线连起来,如此形成的一条折线就是分段线性插值函数,记作In(x) ,它满足 In(xi) = yi ,且In(x) 在每个小区间[xi ,xi+1 ] 上是线性函数(i= 0,1,…,n)
用In(x)计算x 点的插值时,只用到x 左右的两个节点,计算量与节点个数n无关。但n越大,分段越多,插值误差越小。实际上用函数表作插值计算时,分段线性插值就足够了,如数学、物理中用的特殊函数表,数理统计中用的概率分布表等。
样条插值
许多工程技术中提出的计算问题对插值函数的光滑性有较高要求,如飞机的机翼外形,内燃机的进、排气门的凸轮曲线,都要求曲线具有较高的光滑程度,不仅要连续,而且要有连续的曲率,这就导致了样条插值的产生。
样条插值:由于样条插值可以使用低阶多项式样条实现较小的插值误差,这样就避免了龙格现象。
概念
所谓样条(Spline)本来是工程设计中使用的一种绘图工具,它是富有弹性的细木条或细金属条。绘图员利用它把一些已知点连接成一条光滑曲线(称为样条曲线),并使连接点处有连续的曲率。
二次样条函数
三次样条函数
利用样条函数进行插值,即取插值函数为样条函数,称为样条插值。例如分段线性插值是一次样条插值。同时也有存在二次、三次样条插值。
线性插值与样条插值
样例 1
某电学元件的电压数据记录在 0~2.25πA 范围与电流关系满足正弦函数,分别用线性插值和样条插值方法给出经过数据点的数值逼近函数曲线。
import numpy as np import pylab as pl from scipy import interpolate import matplotlib.pyplot as plt x = np.linspace(0, 2*np.pi + np.pi/4,10) y = np.sin(x) x_new = np.linspace(0,2*np.pi+np.pi/4,100) f_linear = interpolate.interp1d(x,y) tck = interpolate.splrep(x,y) y_bspline = interpolate.splev(x_new,tck) # 可视化 plt.xlabel(u'安培/A') plt.ylabel(u'伏特/V') plt.plot(x, y,"o",label=u'原始数据') plt.plot(x_new, f_linear(x_new),label=u'线性插值') plt.plot(x_new, y_bspline,label=u'B-spline插值') plt.legend() plt.show()
高阶样条插值
随着插值节点增多,多项式次数也增高,插值曲线在一些区域出现跳跃,并且越来越偏离原始曲线,1901 年被发现并命名为 Tolmé Runge 现象。也就是龙格现象
样例2:
某电学元件的电压数据记录在 0~10A 范围与电流关系满足正弦函数,分别用 0-5 阶样条插值方法给出经过数据点的数值逼近函数曲线。
# 创建数据点集 import numpy as np x = np.linspace(0, 10, 11) y = np.sin (x) # 绘制数据点集 import pylab as pl pl.figure(figsize =(12,9)) pl.plot(x, y, 'ro') # 根据 kind 创建 interp1d 对象 f 、计算插值结果 xnew = np.linspace(0, 10,101) from scipy import interpolate for kind in ['nearest', 'zero', 'linear', 'quadratic', 5]: f = interpolate.interp1d(x, y, kind = kind) ynew = f(xnew) pl.plot(xnew , ynew , label = str(kind)) pl.xticks(fontsize =20) pl.yticks(fontsize =20) pl.legend(loc='lower right') pl.show()
从最后可视化的图中可以看出,5阶样条更加接近正弦曲线,但 x 范围更大以后 5 阶的龙格现象也越明显