【问题】在比赛中,常常需要根据已知的函数点进行数据,模型的处理和分析,而有时候现有的数据又是极少的,不足以支撑分析的进行,这时候就需要使用一些数学的方法,“模拟产生”一些新的但又比较靠谱的值来满足需求,这就是插值的作用。
【引出】一维插值问题
已经有n+1个节点 ( x i , y i ) ( i = 0 , 1 , ⋯ , n ) (x_i,y_i)(i=0,1,\cdots,n) (xi,yi)(i=0,1,⋯,n)其中 x i x_i xi互不相同,不妨假设 a = x 0 < x 1 < ⋯ < x n = b a=x_0a=x0<x1<⋯<xn=b,求任一插值点 x ∗ ( ≠ x i ) x^*(\neq x_i) x∗(=xi)处的插值。
思路:构造函数 y = f ( x ) y=f(x) y=f(x),使得 f ( x ) f(x) f(x)经过所有已知的节点,求 f ( x ∗ ) f(x^*) f(x∗)即可得到 y ∗ y^* y∗
插值法的定义
设函数 y = f ( x ) y=f(x) y=f(x)在区间 [ a , b ] [a,b] [a,b]上有定义,且已知在点 a ≤ x 0 < x 1 < ⋯ < x n ≤ b a\leq x_0a≤x0<x1<⋯<xn≤b上的函数值分别为: y 0 , y 1 , ⋯ , y n y_0,y_1,\cdots,y_n y0,y1,⋯,yn若存在一个简单函数 P ( x ) P(x) P(x),使得 P ( x i ) = y i , ( i = 0 , 1 , ⋯ , n ) P(x_i)=y_i ,(i=0,1,\cdots,n) P(xi)=yi,(i=0,1,⋯,n)则称 P ( x ) 为 f ( x ) P(x)为f(x) P(x)为f(x)的插值函数,点 x 0 , x 1 , ⋯ , x n x_0,x_1,\cdots,x_n x0,x1,⋯,xn称为插值节点, f ( x ) f(x) f(x)叫做被插值函数,包含插值节点的区间 [ a , b ] [a,b] [a,b]称为插值区间,求插值函数 P ( x ) P(x) P(x)的方法称为插值法。
一般的多项式插值
- 插值法的原理:
- 定理:设有n+1个不同的节点 ( x i , y i ) , ( i = 0 , 1 , ⋯ , n ) (x_i,y_i),(i=0,1,\cdots,n) (xi,yi),(i=0,1,⋯,n)则存在唯一的多项式: L n ( x ) = a 0 + a 1 x + a 2 x 2 + ⋯ + a n x n L_n(x)=a_0+a_1x+a_2x^2+\cdots+a_nx^n Ln(x)=a0+a1x+a2x2+⋯+anxn使得 L n ( x j ) = y j ( j = 0 , 1 , ⋯ , n ) L_n(x_j)=y_j(j=0,1,\cdots,n) Ln(xj)=yj(j=0,1,⋯,n)
- 证明:n+1个方程解n+1个未知量 ( a 0 , a 1 , ⋯ , a n ) (a_0,a_1,\cdots,a_n) (a0,a1,⋯,an)构造方程组: { a 0 + a 1 x 0 + a 2 x 0 2 + ⋯ + a n x 0 n = y 0 a 0 + a 1 x 1 + a 2 x 1 2 + ⋯ + a n x 1 n = y 1 ⋯ a 0 + a 1 x n + a 2 x n 2 + ⋯ + a n x n n = y n \left\{\begin{matrix} a_0+a_1x_0+a_2x_0^2+\cdots+a_nx_0^n=y_0\\ a_0+a_1x_1+a_2x_1^2+\cdots+a_nx_1^n=y_1\\ \cdots\\ a_0+a_1x_n+a_2x_n2+\cdots+a_nx_n^n=y_n \end{matrix}\right. ⎩⎪⎪⎨⎪⎪⎧a0+a1x0+a2x02+⋯+anx0n=y0a0+a1x1+a2x12+⋯+anx1n=y1⋯a0+a1xn+a2xn2+⋯+anxnn=yn令: A = [ 1 x 0 ⋯ x 0 n 1 x 1 ⋯ x 1 n ⋮ ⋮ ⋱ ⋮ 1 x n ⋯ x n n ] , X = [ a 0 a 1 ⋮ a n ] , Y = [ y 0 y 1 ⋮ y n ] A=\begin{bmatrix} 1 & x_0 & \cdots & x_0^n\\ 1 & x_1 & \cdots & x_1^n\\ \vdots & \vdots & \ddots & \vdots\\ 1 & x_n & \cdots & x_n^n \end{bmatrix},X=\begin{bmatrix} a_0\\ a_1\\ \vdots\\ a_n \end{bmatrix},Y=\begin{bmatrix} y_0\\ y_1\\ \vdots\\ y_n \end{bmatrix} A=⎣⎢⎢⎢⎡11⋮1x0x1⋮xn⋯⋯⋱⋯x0nx1n⋮xnn⎦⎥⎥⎥⎤,X=⎣⎢⎢⎢⎡a0a1⋮an⎦⎥⎥⎥⎤,Y=⎣⎢⎢⎢⎡y0y1⋮yn⎦⎥⎥⎥⎤(A为范德蒙德行列式)方程组的矩阵形式如下: A X = Y AX=Y AX=Y由于 ∣ A ∣ = ∏ i = 1 n ∏ j = 0 n − 1 ( x i − x j ) ≠ 0 |A|=\prod_{i=1}^{n}\prod_{j=0}^{n-1}(x_i-x_j)\neq 0 ∣A∣=∏i=1n∏j=0n−1(xi−xj)=0所以该方程组有唯一解。从而 L n ( x ) = a 0 + a 1 x + a 2 x 2 + ⋯ + a n x n L_n(x)=a_0+a_1x+a_2x^2+\cdots+a_nx^n Ln(x)=a0+a1x+a2x2+⋯+anxn唯一存在,证毕。
- 只要n+1个节点互异,满足上面插值条件的多项式是唯一存在的。
- 如果不限制多项式的次数,插值多项式并不唯一。
- 拉格朗日插值法——一种多项式插值法
- 两个点: ( x 0 , y 0 ) , ( x 1 , 1 ) (x_0,y_0),(x_1,_1) (x0,y0),(x1,1)插值函数为 y = x − x 1 x 0 − x 1 y 0 + x − x 0 x 1 − x 0 y 1 y=\frac{x-x_1}{x_0-x_1}y_0+\frac{x-x_0}{x_1-x_0}y_1 y=x0−x1x−x1y0+x1−x0x−x0y1
- 三个点: ( x 0 , y 0 ) , ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_0,y_0),(x_1,y_1),(x_2,y_2) (x0,y0),(x1,y1),(x2,y2)插值函数为 y = ( x − x 1 ) ( x − x 2 ) ( x 0 − x 1 ) ( x 0 − x 2 ) y 0 + ( x − x 0 ) ( x − x 2 ) ( x 1 − x 0 ) ( x 1 − x 2 ) y 1 + ( x − x 0 ) ( x − x 1 ) ( x 2 − x 0 ) ( x 2 − x 1 ) y 2 y=\frac{(x-x_1)(x-x_2)}{(x_0-x_1)(x_0-x_2)}y_0+\frac{(x-x_0)(x-x_2)}{(x_1-x_0)(x_1-x_2)}y_1+\frac{(x-x_0)(x-x_1)}{(x_2-x_0)(x_2-x_1)}y_2 y=(x0−x1)(x0−x2)(x−x1)(x−x2)y0+(x1−x0)(x1−x2)(x−x0)(x−x2)y1+(x2−x0)(x2−x1)(x−x0)(x−x1)y2
- 四个点:……
- 缺点:龙格现象(Range phenomenon)
高次插值会产生龙格现象,即在两端处波动极大,产生明显的震荡,在不熟悉曲线的运动趋势的前提下,最好不要使用高次插值。
【解决办法】分段低次插值
插值多项式次数高,精度未必提高,反而误差可能越大。
- 分段低次插值
- 分段低次插值主要是指分段线性插值和分段二次插值。
- 分段线性插值:选取跟节点x最近的两个已知节点,求出经过这两个节点的直线即为节点x的插值函数
- 分段二次插值:选取跟节点x最近的三个节点 x i − 1 , x i , x i + 1 x_{i-1},x_i,x_{i+1} xi−1,xi,xi+1进行二次插值,即在每一个区间 [ x i − 1 , x i + 1 ] [x_{i-1},x_{i+1}] [xi−1,xi+1]上取: f ( x ) = L 2 ( x ) f(x)=L_2(x) f(x)=L2(x)。在几何上就是每段都用抛物线代替 f ( x ) f(x) f(x),故又叫做分段抛物插值。
- 牛顿插值法
- f ( x ) = f ( x 0 ) + f [ x 0 , x 1 ] ( x − x 0 ) + f [ x 0 , x 1 , x 2 ] ( x − x 0 ) ( x − x 1 ) + ⋯ + f [ x 0 , x 1 , ⋯ , x n − 2 , x n − 1 ] ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 2 ) ] + f [ x 0 , x 1 , ⋯ , x n ] ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) f(x)=f(x_0)+f[x_0,x_1](x-x_0)+f[x_0,x_1,x_2](x-x_0)(x-x_1)+\cdots+f[x_0,x_1,\cdots,x_{n-2},x_{n-1}](x-x_0)(x-x_1)\cdots(x-x_{n-2})]+f[x_0,x_1,\cdots,x_n](x-x_0)(x-x_1)\cdots(x-x_{n-1}) f(x)=f(x0)+f[x0,x1](x−x0)+f[x0,x1,x2](x−x0)(x−x1)+⋯+f[x0,x1,⋯,xn−2,xn−1](x−x0)(x−x1)⋯(x−xn−2)]+f[x0,x1,⋯,xn](x−x0)(x−x1)⋯(x−xn−1)
- 差商的定义:称 f [ x 0 , x k ] = f ( x k ) − f ( x 0 ) x k − x 0 f[x_0,x_k]=\frac{f(x_k)-f(x_0)}{x_k-x_0} f[x0,xk]=xk−x0f(xk)−f(x0)为函数关于点 x 0 , x k x_0,x_k x0,xk的一阶差商(亦称均差)。
- 二阶差商: f [ x 0 , x 1 , x 2 ] = f [ x 1 , x 2 ] − f [ x 0 , x 1 ] x 2 − x 0 f[x_0,x_1,x_2]=\frac{f[x_1,x_2]-f[x_0,x_1]}{x_2-x_0} f[x0,x1,x2]=x2−x0f[x1,x2]−f[x0,x1]
- k阶差商: f [ x 0 , x 1 , ⋯ , x k ] = f [ x 1 , ⋯ , x k − 1 , x k ] − f [ x 0 , x 1 , ⋯ , x k − 1 ] x k − x 0 f[x_0,x_1,\cdots,x_k]=\frac{f[x_1,\cdots,x_{k-1},x_k]-f[x_0,x_1,\cdots,x_{k-1}]}{x_k-x_0} f[x0,x1,⋯,xk]=xk−x0f[x1,⋯,xk−1,xk]−f[x0,x1,⋯,xk−1] ( x k − 1 , x k 可 以 不 相 邻 ) (x_{k-1},x_k可以不相邻) (xk−1,xk可以不相邻)
- 与拉格朗日插值法相比,牛顿插值法的计算过程具有继承性。(牛顿插值法每次插值只和前n项的有关,这样每次只要在原来的函数上添加新的项,就能够产生新的函数)但是牛顿插值法也存在龙格现象。
-
拉格朗日插值法与牛顿插值法的另一个缺点
这两种插值仅仅要求插值多项式在插值节点处与被插函数有相等的函数值,而这种插值多项式却不能全面反映被插值函数 f ( x ) f(x) f(x)的性态。
然而在许多实际问题中,不仅仅要求插值函数 P ( x ) P(x) P(x)与被插值函数 f ( x ) f(x) f(x)在所有的节点处具有相同的函数值,它也需要在一个或者全部节点上插值多项式与被插函数有相同的低阶甚至高阶的导数值。
对于这些情况,拉格朗日插值法和牛顿插值法都不能满足。
埃尔米特(Hermite)插值(多项式插值)
-
基本思路:不但要求在节点上函数值相等,而且还要求对应的导数值也相等。
φ ( x i ) = y i , ( i = 0 , 1 , ⋯ , n ) φ ′ ( x i ) = y i ′ , ( i = 0 , 1 , ⋯ , n ) \begin{aligned} \varphi (x_i)=y_i,(i=0,1,\cdots,n)\\ \varphi ^{'}(x_i)=y_i^{'},(i=0,1,\cdots,n) \end{aligned} φ(xi)=yi,(i=0,1,⋯,n)φ′(xi)=yi′,(i=0,1,⋯,n)保持插值曲线在节点处有切线(光滑),使插值函数与被插值函数的密和程度更好。
-
Hermite插值法的原理:
设 f ( x ) f(x) f(x)在区间 [ a , b ] [a,b] [a,b]上有n+1个互异节点 a = x 0 < x 1 < x 2 < ⋯ < x n = b a=x_0a=x0<x1<x2<⋯<xn=b,定义在 [ a , b ] [a,b] [a,b]上函数 f ( x ) f(x) f(x)在节点上满足: f ( x i ) = y i , f ′ ( x i ) = y i ′ , ( i = 0 , 1 , 2 , ⋯ , n ) f(x_i)=y_i,f^{'}(x_i)=y_i^{'},(i=0,1,2,\cdots,n) f(xi)=yi,f′(xi)=yi′,(i=0,1,2,⋯,n)(2n+2个条件)可唯一确定一个次数不超过2n+1的多项式 H 2 n + 1 ( x ) = H ( x ) H_{2n+1}(x)=H(x) H2n+1(x)=H(x)满足: H ( x j ) = y j , H ′ ( x j ) = y j ′ , ( j = 0 , 1 , 2 , ⋯ , n ) H(x_j)=y_j,H^{'}(x_j)=y^{'}_j,(j=0,1,2,\cdots,n) H(xj)=yj,H′(xj)=yj′,(j=0,1,2,⋯,n)其余项为: R ( x ) = f ( x ) − H ( x ) = f ( 2 n + 2 ) ( ξ ) ( 2 n + 2 ) ! ω 2 n + 2 ( x ) R(x)=f(x)-H(x)=\frac{f^{(2n+2)}(\xi)}{(2n+2)!}\omega_{2n+2}(x) R(x)=f(x)−H(x)=(2n+2)!f(2n+2)(ξ)ω2n+2(x)
-
分段三次埃尔米特插值
- 直接使用Hermite插值得到的多项式的次数较高,也存在着龙格现象,因此在实际应用中,往往使用分段三次Hermite插值多项式(PCHIP)
- 使用方法:调用Matlab内置函数
p=pchip(x,y,new_x)
x是已知样本点的横坐标,y是已知样本点的纵坐标,new_x是要插入处对应的横坐标,p是插入处对应的纵坐标。
【例子】x=-pi:pi;
new_x=-pi:0.1:pi;
y=sin(x);
p=pchip(x,y,new_x);
plot(x,y,'o',new_x,p,'r-.')
三次样条插值
-
基本原理:
设 y = f ( x ) y=f(x) y=f(x)在点 x 0 , x 1 , x 2 , ⋯ , x n x_0,x_1,x_2,\cdots,x_n x0,x1,x2,⋯,xn处的1值为 y 0 , y 1 , y 2 , ⋯ , y n y_0,y_1,y_2,\cdots,y_n y0,y1,y2,⋯,yn,若·函数 S ( x ) S(x) S(x)满足下列条件:
(1) S ( x i ) = f ( x i ) = y i , i = 0 , 1 , 2 , ⋯ , n S(x_i)=f(x_i)=y_i,i=0,1,2,\cdots,n S(xi)=f(xi)=yi,i=0,1,2,⋯,n
(2)在每个子区间 [ x i , x i + 1 ] ( i = 0 , 1 , 2 , ⋯ , n − 1 ) [x_i,x_{i+1}](i=0,1,2,\cdots,n-1) [xi,xi+1](i=0,1,2,⋯,n−1)上 S ( x ) S(x) S(x)是三次多项式
(3) S ( x ) S(x) S(x)在 [ a , b ] [a,b] [a,b]上二阶连续可微
则称 S ( x ) S(x) S(x)为函数 f ( x ) f(x) f(x)的三次样条插值函数。
-
构造方法: S ( x ) S(x) S(x)除了满足基本的插值条件 S ( x i ) = f ( x i ) S(x_i)=f(x_i) S(xi)=f(xi)之外还应具有以下形式: S ( x ) = { S 0 ( x ) , x ∈ [ x 0 , x 1 ] S 1 ( x ) , x ∈ [ x 1 , x 2 ] ⋮ S n − 1 ( x ) , x ∈ [ x n − 1 , x n ] , S i ( x ) ∈ C 3 ( [ x i , x i + 1 ] ) S(x)=\left\{\begin{matrix} S_0(x),x\in [x_0,x_1]\\ S_1(x),x\in [x_1,x_2]\\ \vdots\\ S_{n-1}(x),x\in [x_{n-1},x_{n}] \end{matrix}\right.,S_i(x)\in C^{3}([x_i,x_{i+1}]) S(x)=⎩⎪⎪⎪⎨⎪⎪⎪⎧S0(x),x∈[x0,x1]S1(x),x∈[x1,x2]⋮Sn−1(x),x∈[xn−1,xn],Si(x)∈C3([xi,xi+1])并且满足条件: { S i − 1 ( x i ) = S i ( x i ) , 插 值 的 连 续 性 S i − 1 ′ ( x i ) = S i ′ ( x i ) 一 阶 微 分 的 连 续 性 S i − 1 ′ ′ ( x i ) = S i ′ ′ ( x i ) 二 阶 微 分 的 连 续 性 \left\{\begin{matrix} S_{i-1}(x_i)=S_i(x_i),插值的连续性\\ S_{i-1}^{'}(x_i)=S_i^{'}(x_i)一阶微分的连续性\\ S_{i-1}^{''}(x_i)=S_i^{''}(x_i)二阶微分的连续性 \end{matrix}\right. ⎩⎨⎧Si−1(xi)=Si(xi),插值的连续性Si−1′(xi)=Si′(xi)一阶微分的连续性Si−1′′(xi)=Si′′(xi)二阶微分的连续性
-
使用方法:matlab内置函数:
p=spline(x,y,new_x)
x是已知点的横坐标,y是已知点的纵坐标,new_x是要插入处点的横坐标,p是要插入处点的纵坐标。
x=-pi:pi;
new_x=-pi:0.1:pi;
y=sin(x);
p1=pchip(x,y,new_x);
p2=spline(x,y,new_x);
plot(x,y,'o',new_x,p1,'r-',new_x,p2,'b-')
legend('样本点','三次埃尔米特插值','三次样条插值','Location','SouthEast')
%三次样条插值更加光滑,更接近被插值函数sin(x)
由图可以看出:三次样条插值生成的曲线更加光滑,在实际建模中,由于我们不知道题目中数据的生成过程,因此三次埃尔米特插值与三次样条插值都可以使用。
n维数据的插值
p=interpn(x1,x2,…,xn,y,new_x1,new_x2,…,new_xn,method)
x1,x2,…,xn是已知样本点的横坐标,y是对应的纵坐标,new_x1,new_x2,…,new_xn是要插入点的横坐标,p是对应的纵坐标。
method 是要插值的方法:
- ‘linear’:线性插值(默认方法)
- ‘cubic’:三次插值
- ‘spline’:三次样条插值(最为精准)
- ‘nearest’:最邻近插值算法
【拓展】
上面学的插值算法有时候可以用来短期预测。