1.拉格朗日的推导
在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法。许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过实验和观测来了解。如对实践中的某个物理量进行观测,在若干个不同的地方得到相应的观测值,拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。这样的多项式称为拉格朗日(插值)多项式。
1.1 推导流程如下:
1.1.1主要思路:
通过简单的一次插值以及复杂一点的二次插值(就是我们所说的拉格朗日插值)最后推导到n次插值。
1.1.2对流程图的解释
- 基函数:
-
在数学中,基函数是函数空间一组特殊的基的元素。对于函数空间中的连续函数都可以将所要插的y值表示成一系列基函数的线性组合;表示如下:
-
对比在向量空间中,每个向量都可以表示成基向量的线性组合一样;
-
所以总结来看讲到基函数你就应该想到以下几点:
- 最终由基映射的结果是什么?——a.在基函数就是要插入的值;b.最终合成的向量;
- 基函数对应的变量是什么?——a.在基函数就是已知的各个x值;b.基本的单位向量;
-
基向量图示:
-
1.1.3 详细推导过程
1、线性插值(一次插值)
- 直线可以表现为下面两种形式:
-
通过初高中知识去回忆上面的两个式子,首先计算斜率: ,再回忆常用的公式: ;这时候就与上面的式子一对应了;
-
图示:
2、拉格朗日插值(二次插值)
我们把两点式作为一个通用的推理式子,从意义上来说就是我们把两个点作为两个基,需要做的就是找出所插入的式子每个基各占多少。再结合到上面的两点式可以得到最终的通用式:
那么我们现在来思考一下,如果插入点是
本身,那么其他项肯定就是0不然结果就不对了,并且结合已知的零点(可以肯定已知的点都是函数的零点),但是本身值肯定不能算算进去就变成0了,所以有以下式子:
又因为
的取值为0或者1,而这时只能取1,所以最终的
结果是:
将其带入通用式就是最终的结果。
3、n次拉格朗日插值
一次插值是将两个点进行计算,而2次插值是将3个点进行插值,n个插值就是将n+1个节点进行插值。
2.两种拉格朗日差值形式
2.1 朴素的拉格朗日插值
假如有
个点,每个点形如
,假设任意两个x都不相同,那么最后得到的多项式肯定是:
2.2 重心的拉格朗日插值
从朴素转换为中心的:
其中:
在这里我们需要把 和 看做是一个整体(那么在计算的时候就相当于每次计算这两项都进行了保存),所以在进行从n个点到n+1个点过渡时就只需要对这两个式子多出得第n个点相应的操作。
2.3 优化技巧
发现每一个连乘的分子乘上一个二项式能变成一个统一的多项式,所以处理的时候直接用不需要的那个二项式去除那个多项式就行(下面的常数计算)
3.不使用的情况
为什么不用拉格朗日插值法来拟合大量的一维数据(比如机器学习上面)?
-
答:容易产生过拟合,且处理过程时间比较长。
-
例子:如果有n个样本 ,拉格朗日多项式的次数就是 ,表达式为:
-
n个点我们需要计算出 这n个系数,并且在数据高低起伏过大的地方容易产生过拟合;
-
4.二次的拉格朗日插值代码实现
# 实现拉格朗日差值
# -*-coding:utf-8 -*-
import numpy as np
from scipy import interpolate
import pylab as pl #pylab是matplotlib的一个模块
# 自定义函数实现拉格朗日差值
# a:变量x的插入值,x、y代表已知的值
def h(x,y,a):
ans=0.0
# 实现累加,得到最终的结果y
for i in range(len(y)):
t=y[i]
# 实现累乘,得到系数l(x)
for j in range(len(y)):
if i !=j:
t*=(a-x[j])/(x[i]-x[j])
ans +=t
return ans
x=[1,0]
y=[0,2]
print(h(x,y,1.1))
a=interpolate.lagrange(x,y)
print(a)
print('insert 1.1 is:')
print(a(1.1))
# 调用库函数实现拉格朗日差值
x=np.linspace(0,10,11)
#x=[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
y=np.sin(x)
xnew=np.linspace(0,10,101)
pl.plot(x,y,"ro")
for kind in ["nearest","zero","slinear","quadratic","cubic"]:#插值方式
#"nearest","zero"为阶梯插值
#slinear 线性插值
#"quadratic","cubic" 为2阶、3阶B样条曲线插值
f=interpolate.interp1d(x,y,kind=kind)
# ‘slinear’, ‘quadratic’ and ‘cubic’ refer to a spline interpolation of first, second or third order)
ynew=f(xnew)
pl.plot(xnew,ynew,label=str(kind))
pl.legend(loc="lower right")
pl.show()
参考文章