温馨提示:本文共有3748字,阅读并理解全文大概需要15-20分钟
插值算法
数模比赛中,常常需要根据已知的函数点进行数据、模型的处理和分析,而有时候现有的数据是极少的,不足以支撑分析的进行,这时就
需要使用一些数学的方法,“模拟产生”一些新的但又比较靠谱的值来满足需求,这就是插值的作用。
【问题引入】
一维插值问题:
已经有n+1个节点(
x
i
x_i
xi,
y
i
y_i
yi),其中
x
i
x_i
xi互不相同,不妨假设
a
=
x
0
<
x
1
<
…
…
<
x
n
=
b
a=x_0<x_1<……<x_n=b
a=x0<x1<……<xn=b,求任一插值点
x
∗
x^*
x∗(≠
x
i
x_i
xi)处的插值
y
∗
y^*
y∗。
(思路:构造函数
y
=
f
(
x
)
y=f(x)
y=f(x),使得
f
(
x
)
f(x)
f(x)过所有节点,求
f
(
x
∗
)
f(x^*)
f(x∗)即可得到
y
∗
y^*
y∗)
一、插值法的定义
通俗来说就是根据平面上已有的点来拟合出一个函数过所有这些点,然后我们就可求得这个函数其他位置的点的数据了,这样就在原样本点的基础上扩展了样本空间。
那么具体如何求这个插值函数就是插值法的重点了。
1.插值函数一共有三种:
- 若 P ( x ) P(x) P(x)是次数不超过 n n n的代数多项式,即: P ( x ) = a 0 + a 1 x + … … + a n x n P(x)=a_0+a_1x+……+a_nx^n P(x)=a0+a1x+……+anxn(则称为插值多项式)
- 若 P ( x ) P(x) P(x)是分段多项式,就成为分段插值
- 若 P ( x ) P(x) P(x)是三角多项式,就成为三角插值
由于三角插值一般要用到傅里叶变化等的复杂数学工具,所以这里暂时只讨论多项式插值和分段插值。在比赛中用的最多的是分段插值
2.多项式插值法原理
定理:设有
n
+
1
n+1
n+1个互不相同的节点(
x
i
,
y
i
x_i,y_i
xi,yi) (
i
=
0
,
1
,
2
…
…
n
i=0,1,2……n
i=0,1,2……n)
则存在唯一的多项式:
L
n
(
x
)
=
a
0
+
a
1
x
+
a
2
x
2
+
…
…
+
a
n
x
n
\begin{align} L_n(x)=a_0+a_1x+a_2x^2+……+a_nx^n \end{align}
Ln(x)=a0+a1x+a2x2+……+anxn
使得
L
n
(
x
j
)
=
y
j
L_n(x_j)=y_j
Ln(xj)=yj(
j
=
0
,
1
,
2
,
…
…
,
n
j=0,1,2,……,n
j=0,1,2,……,n)
有兴趣的小伙伴可以研究一下证明:
3.分段插值法原理:
分段线性插值就是相邻两点之间用直线(一次函数)连接,分段二次插值就是相邻几个点之间用抛物线(二次函数)连接,分段三次插值就是相邻若干点之间用三次函数连接。
4.具体如何求插值函数呢?
(1)多项式插值法之:拉格朗日插值法(了解即可,实际基本不用)
在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫∙路易斯∙拉格朗日命名的一种多项式插值方法。在若干个不同的地方得到相应的观测值,拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。
- 两个点:
(
x
0
,
y
0
)
,
(x_0,y_0),
(x0,y0),,
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1)
- 三个点:
(
x
0
,
y
0
)
,
(x_0,y_0),
(x0,y0),,
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1),
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2)
3.四个点:
( x 0 , y 0 ) , (x_0,y_0), (x0,y0),, ( x 1 , y 1 ) (x_1,y_1) (x1,y1), ( x 2 , y 2 ) (x_2,y_2) (x2,y2), ( x 3 , y 3 ) (x_3,y_3) (x3,y3)
拉格朗日多项式插值法存在的问题:
高次插值会产生龙格现象,即在两端处波动极大,产生明显的震荡。在不熟悉曲线运动趋势的前提下,不要轻易使用高次插值。
(2)多项式插值法之:牛顿插值法(了解即可,实际基本不用)
评价:
与拉格朗日插值法相比,牛顿插值法的计算过程具有继承性。(牛顿插值法每次插值只和前n项的值有关,这样每次只要在原来
的函数上添加新的项,就能够产生新的函数)但是牛顿插值也存在龙格现象的问题。
两种插值法的另一个缺点:
上面讲的两种插值仅仅要求插值多项式在插值节点处与被插函数有相等的函数值,而这种插值多项式却不能全面反映被插值函数的性态。
然而在许多实际问题中,不仅要求插值函数与被插值函数在所有节点处有相同的函数值,它也需要在一个或全部节点上插值多项式与被插函数有相同的低阶甚至高阶的导数值。对于这些情况,拉格朗日插值和牛顿插值都不能满足。
(3)三次样条插值算法(重点掌握)
三次样条多项式满足的条件:
(4)埃尔米特(Hermite)插值法(了解即可,实际基本不用)
(5)分段插值法之:分段三次埃尔米特插值法(重点掌握)
直接使用Hermite插值得到的多项式次数较高,也存在着龙格现象,因此在实际应用中,往往使用分段三次 Hermite 插值多项式 (PCHIP),是由埃尔米特插值法根据分段思想改进得来的。
用一句话简述就是:找最近的四个点用一个三次函数进行拟合。
二、基于MATLAB的插值算法实践:
1.分段三次埃尔米特插值法
Matlab有内置的函数(实现过程已经帮我们封装好了,会调用就行了):
p = pchip(x,y, new_x)
x是已知的样本点的横坐标;y是已知的样本点的纵坐标;new_x是要插入处对应的横坐标。
返回的p就是横坐标为new_x,根据拟合函数算出来的那些纵坐标。
例如:
x = ‐pi:pi; %构成一个等差数列,公差为1.
y = sin(x);
new_x = ‐pi:0.1:pi;
p = pchip(x,y,new_x);
plot(x, y, 'o', new_x, p, 'r‐')
我们可以看一下已知点一共有几个:
所以已知点一共有7个。
而插值的点有多少呢?
插值的点是以0.01为公差的,所以这个点是很多的。
最后插值完后绘制出的图像如图:
plot函数用法:
plot(x1,y1,x2,y2)
线方式: ‐ 实线 :点线 ‐. 虚点线 ‐ ‐ 波折线
点方式: . 圆点 +加号 * 星号 x x形 o 小圆
颜色: y黄; r红; g绿; b蓝; w白; k黑; m紫; c青
2.三次样条插值
Matlab有内置的函数:
p = spline (x,y, new_x)
x是已知的样本点的横坐标;y是已知的样本点的纵坐标;new_x是要插入处对应的横坐标。
返回的p就是横坐标为new_x,根据拟合函数算出来的那些纵坐标。
例如:
x = ‐pi:pi;
y = sin(x);
new_x = ‐pi:0.1:pi;
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’) %标注显示在东南方向
插值结果对比
说明:
legend(string1,string2,string3, …)
分别将字符串1、字符串2、字符串3……标注到图中,每个字符串对应的图标为画图时
的图标。
‘Location’用来指定标注显示的位置
可以看出,三次样条生成的曲线更加光滑。在实际建模中,由于我们不知道数据的生成过程,因此这两种插值都可以使用。
3.n维数据的插值(了解)
p = interpn(x1,x2,...,xn, y, new_x1,new_x2,...,new_xn, method)
y是已知的样本点的纵坐标坐标
new_x1,new_x2,…,new_xn是要插入点的横坐标
method是要插值的方法
‘linear’:线性插值(默认算法);
‘cubic’:三次插值;
‘spline’:三次样条插值法;(最为精准)
‘nearest’:最邻近插值算法。
例:
x = ‐pi:pi; y = sin(x);
new_x = ‐pi:0.1:pi;
p = spline(x, y, new_x);
等价于 p = interpn (x, y, new_x, ’spline’);
plot(x, y, 'o', new_x, p, 'r‐')
三、插值算法用于短期预测:
根据过去10年的中国人口数据,预测接下来三年的人口数据:
年份 | 人口(万) |
---|---|
2009 | 133126 |
2010 | 133770 |
2011 | 134413 |
2012 | 135069 |
2013 | 135738 |
2014 | 136427 |
2015 | 137122 |
2016 | 137866 |
2017 | 138639 |
2018 | 139538 |
population=[133126,133770,134413,135069,135738,136427,137122,137866,138639, 139538];
year = 2009:2018;
p1 = pchip(year, population, 2019:2021) %分段三次埃尔米特插值预测
p2 = spline(year, population, 2019:2021) %三次样条插值预测
figure(4);
plot(year, population,'o',2019:2021,p1,'r*-',2019:2021,p2,'bx-')
legend('样本点','三次埃尔米特插值预测','三次样条插值预测','Location','SouthEast')
四、建模实例
这个先挖个坑,之后再写