点击上方“算法数据侠”,选择“星标”公众号
第一时间获取最新推文与资源分享 小侠客们好呀,我是oubahe。上次的前菜——Lagrange插值相信难不倒聪明的小侠客们,是否还记得上次讲到Lagrange插值在每次有新的插值点增加时,整个Lagrange基函数就需要重新构建,这会大大增加计算量。还没有学习过常用的时序插值算法(一)的小侠客可以通过下方的传送门赶快脑补一波~常用的时序插值算法(一)
今天的插值算法相信很多小侠客在大学本科就已经在线性代数或者数值分析中学习过——大名鼎鼎的牛顿插值法(Newton Interpolation Method)。Newton插值与Lagrange插值不同的是,它引入了差商的概念,使其在插值节点增加时仍然能保持较高效率的计算。内容较短,争取十分钟以内学习完,begin~
01
— Newton插值原理假设插值节点为x0, x1, ... , xn,拟考虑函数组如下:
其中fk(x)是k次多项式,它们之间是线性无关的,因此可以使用它们来构造基函数。我们可以看到,该基函数的一个优点是当增加一个新的插值节点xn+1时,只需要在原有基函数的基础上增加一个新的函数fn+1(x)即可,其中: 那么,我们就得到了Newton插值多项式的表达式为:其中,ak=[y0, y1, ..., yk]表示差商,fk(x)为Newton插值的基函数。
下面简单介绍一下差商的流程。
假设我们已知的节点为x0, x1, ... , xn,那么得到关于节点xi, xj的一阶差商为:
关于节点xi, xj和xk的二阶差商为:
那么我们可以得到关于x0, x1, ..., xk的k阶差商为:
这一幕有些熟悉了嘛,利用差商的递推,我们就可以构造差商来计算差商啦,进而也就可以得到 得到了 N ewton插值 多项式N(x)。将数据集中缺失点的x值代入得到的N(x)便可以进行插值填充。 02 — 动手干下面是python版本的Newton插值算法具体实现,可以根据自己的数据集情况实操一下Newton插值填充流程哟。
import numpy as npdef difference_quotient(x_val, y_val): ''' this function is to calculate the difference quotient ''' assert len(x_val) == len(y_val) n = len(x_val) p = np.zeros((n, n+1)) p[:, 0] = x_val p[:, 1] = y_val for j in range(2, n+1): p[j-1: n, j] = (p[j-1: n, j-1] - p[j-2: n-1, j-1]) / (x_val[j-1: n] - x_val[: n+1-j]) q = np.diag(p, k=1) return p, qdef newton_interpolate(x_val, y_val, x): ''' this function is to compolish newton interpolate ''' _, q = difference_quotient(x_val, y_val) def basis(i): if i > 0: l_i = [(x - x_val[j]) for j in range(i)] else: l_i = [1] return reduce(operator.mul, l_i) * q[i] return sum(basis(i) for i in range(len(x_val)))
03
—
结语
但是,无论是Lagrange插值还是Newton插值,本质上还是用一个高阶多项式来尽可能地拟合所给的已知点分布原始函数。多项式插值有很明显的缺陷在于,若已知点太少,则插值出来的函数与原始函数偏离较大,返回的插值结果会对算法模型造成较大影响;另一方面,若已知点太多,则拟合的多项式阶数会迅速增加,太高的阶数容易导致插值在边缘处出现龙格现象。有没有一种插值算法来避免高次插值多项式这一缺陷呢?哈哈,后面即将登场的分段线性插值便可以解决上述问题,具体内容我们下次再聊。我是oubahe,下次再见咯~
码字虽少,原创不易。分享是快乐的源泉,来个素质三连 —>点击左下角分享 —> 右下角点赞—>右下角在看本文,可以汇聚好运气召唤神龙哟~