拉格朗日从原理到优化实现

1.拉格朗日的推导

在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法。许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过实验和观测来了解。如对实践中的某个物理量进行观测,在若干个不同的地方得到相应的观测值,拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。这样的多项式称为拉格朗日(插值)多项式。

1.1 推导流程如下:

线性插值
二次线性插值=拉格朗日插值
n次插值
线性插值
基函数
各点占比,在某一点上就是某一点占比为1其他为0

1.1.1主要思路:

通过简单的一次插值以及复杂一点的二次插值(就是我们所说的拉格朗日插值)最后推导到n次插值。

1.1.2对流程图的解释

  1. 基函数:
    1. 在数学中,基函数是函数空间一组特殊的基的元素。对于函数空间中的连续函数都可以将所要插的y值表示成一系列基函数的线性组合;表示如下:

    2. 对比在向量空间中,每个向量都可以表示成基向量的线性组合一样;

    3. 所以总结来看讲到基函数你就应该想到以下几点:

      1. 最终由基映射的结果是什么?——a.在基函数就是要插入的值;b.最终合成的向量;
      2. 基函数对应的变量是什么?——a.在基函数就是已知的各个x值;b.基本的单位向量;
    4. 基向量图示:
      在这里插入图片描述

1.1.3 详细推导过程

1、线性插值(一次插值)
  • 直线可以表现为下面两种形式:

y = L 1 ( x ) = y k + y k + 1 − y k x k + 1 − x k ( x − x k ) 点 斜 式 y = L 1 ( x ) = x − x k + 1 x k − x k + 1 y k + x − x k x k + 1 − x k y k + 1 两 点 式 \begin{array}{c} y=L_{1}(x)=y_{k}+\frac{y_{k+1}-y_{k}}{x_{k+1}-x_{k}}\left(x-x_{k}\right) {点斜式} \\ y=L_{1}(x)=\frac{x-x_{k+1}}{x_{k}-x_{k+1}} y_{k}+\frac{x-x_{k}}{x_{k+1}-x_{k}} y_{k+1}{两点式} \end{array} y=L1(x)=yk+xk+1xkyk+1yk(xxk)y=L1(x)=xkxk+1xxk+1yk+xk+1xkxxkyk+1

  • 通过初高中知识去回忆上面的两个式子,首先计算斜率: k = y − y k x − x k = y k + 1 − y k x k + 1 − x k k = \frac{{y - {y_k}}}{{x - {x_k}}} = \frac{{{y_{k + 1}} - {y_k}}}{{{x_{k + 1}} - {x_k}}} k=xxkyyk=xk+1xkyk+1yk,再回忆常用的公式: y = k ( x − x k ) + y k y = k(x - {x_k}) + {y_k} y=k(xxk)+yk;这时候就与上面的式子一对应了;

  • 图示:

    线性插值

2、拉格朗日插值(二次插值)

我们把两点式作为一个通用的推理式子,从意义上来说就是我们把两个点作为两个基,需要做的就是找出所插入的式子每个基各占多少。再结合到上面的两点式可以得到最终的通用式:
y = l 1 x 1 + l 2 x 2 + . . . + l n x n y = {l_1}{x_1} + {l_2}{x_2} + ... + {l_n}{x_n} y=l1x1+l2x2+...+lnxn
那么我们现在来思考一下,如果插入点是 x 1 x_1 x1本身,那么其他项肯定就是0不然结果就不对了,并且结合已知的零点(可以肯定已知的点都是函数的零点),但是本身值肯定不能算算进去就变成0了,所以有以下式子:
l k − 1 ( x ) = A ( x − x k ) ( x − x k + 1 ) l_{k-1}(x)=A\left(x-x_{k}\right)\left(x-x_{k+1}\right) lk1(x)=A(xxk)(xxk+1)
又因为 l k − 1 ( x ) l_{k-1}(x) lk1(x)的取值为0或者1,而这时只能取1,所以最终的 A A A结果是:
l k − 1 ( x ) = ( x − x k ) ( x − x k + 1 ) ( x k − 1 − x k ) ( x k − 1 − x k + 1 ) l_{k-1}(x)=\frac{\left(x-x_{k}\right)\left(x-x_{k+1}\right)}{\left(x_{k-1}-x_{k}\right)\left(x_{k-1}-x_{k+1}\right)} lk1(x)=(xk1xk)(xk1xk+1)(xxk)(xxk+1)
将其带入通用式就是最终的结果。

3、n次拉格朗日插值

一次插值是将两个点进行计算,而2次插值是将3个点进行插值,n个插值就是将n+1个节点进行插值。

2.两种拉格朗日差值形式

拉格朗日插值
1朴素的
1.1优化计算,添加某项形成某一整体
1.2方便从n个到n+1个点过渡计算
2重心的

2.1 朴素的拉格朗日插值

假如有 n + 1 n+1 n+1个点,每个点形如 ( 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),...,假设任意两个x都不相同,那么最后得到的多项式肯定是:
L ( x ) = ∑ j = 0 n ( y i ∏ i = 0 , i ≠ j n x − x i x j − x i ) L(x)=\sum_{j=0}^{n}\left(y_{i} \prod_{i=0, i \ne j}^{n} \frac{x-x_{i}}{x_{j}-x_{i}}\right) L(x)=j=0nyii=0,i=jnxjxixxi

2.2 重心的拉格朗日插值

从朴素转换为中心的:
L ( x ) = ∑ j = 0 n ( y i ∏ i = 0 , i ≠ j n x − x i x j − x i ) → L ( x ) = l ( x ) ∑ j = 0 n x − x j w j y j L(x) = \sum\limits_{j = 0}^n {\left( {{y_i}\prod\limits_{i = 0,i \ne j}^n {\frac{{x - {x_i}}}{{{x_j} - {x_i}}}} } \right)} \to L(x) = l(x)\sum\limits_{j = 0}^n {\frac{{x - {x_j}}}{{{w_j}}}} {y_j} L(x)=j=0nyii=0,i=jnxjxixxiL(x)=l(x)j=0nwjxxjyj
其中:
l ( x ) = ∏ i = 0 n x − x i l(x) = \prod\limits_{i = 0}^n {x - {x_i}} l(x)=i=0nxxi

w = ∏ i = 0 , i ≠ j n x j − x i w = \prod\limits_{i = 0,i \ne j}^n {{x_j} - {x_i}} w=i=0,i=jnxjxi

在这里我们需要把 l ( x ) l(x) l(x) w w w看做是一个整体(那么在计算的时候就相当于每次计算这两项都进行了保存),所以在进行从n个点到n+1个点过渡时就只需要对这两个式子多出得第n个点相应的操作。

2.3 优化技巧

发现每一个连乘的分子乘上一个二项式能变成一个统一的多项式,所以处理的时候直接用不需要的那个二项式去除那个多项式就行(下面的常数计算)

3.不使用的情况

为什么不用拉格朗日插值法来拟合大量的一维数据(比如机器学习上面)?

  • 答:容易产生过拟合,且处理过程时间比较长。

  • 例子:如果有n个样本 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x n , y n ) (x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n) (x1,y1),(x2,y2),,(xn,yn),拉格朗日多项式的次数就是 n − 1 n-1 n1,表达式为: y = a 0 + a 1 x + a 2 x 2 + a 3 x 3 + ⋯ + a n x n y=a_0+a_1x+a_2x^2+a_3x^3+\cdots+a_{n}x^{n} y=a0+a1x+a2x2+a3x3++anxn

    • n个点我们需要计算出 a 0 , a 1 , . . . , a n a_0,a_1,...,a_n a0,a1,...,an这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()

参考文章

  1. 为什么不用拉格朗日插值法来拟合一维数据?
  2. 拉格朗日百度百科
  3. 拉格朗日插值python实现
  4. 朴素的,和重心拉个朗日插值
  5. 现代数值分析-拉格朗日插值章节
  6. 基函数百度百科
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值