添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
爱旅游的绿豆  ·  Error while ...·  3 月前    · 
重感情的脸盆  ·  Managing ...·  4 月前    · 
51Nod A* AC自动机 BFS BZOJ Codeforces DP FFT HDU KMP LCA LCT LIS LOJ Manacher Matplotlib NumPy POJ Python SciPy SymPy Sympy Trie UOJ WQS二分 dsu on tree git hash hihoCoder kruskal重构树 two-pointers 三分 主席树 乱搞 二分图 交互题 决策单调性 凸包 分块 分数规划 分治 单调栈 单调队列 博弈论 压位 双联通分量 可并堆 后缀数组 启发式分裂 启发式合并 复杂度分析 妙题 容斥 对偶图 差分 差分约束系统 并查集 强连通分量 扫描线 拓扑排序 数位DP 数学 数据库 数模 整体二分 最大权闭合子图 最小生成树 最短路 期望DP 构造 树形DP 树状数组 树链剖分 概率DP 模拟 水题 洛谷 点分治 状压DP 矩阵 矩阵树定理 离线 线性筛 线段树 线段树分治 结论题 网络流 莫队 虚树 计数题 计蒜客 贪心 递推 链表 随机

拉格朗日插值(Lagrange)

拉格朗日插值的 \(f(x)\) \(n-1\) 次多项式, \(n\) 为数据点个数

可以证明,任意 \(n\) 个数据点的 \(n-1\) 次插值函数存在且唯一

具体来说, \[ f(x)=\sum_{i=0}^n l_i(x)y_i \\ l_i(x)=\prod_{j=0,j\neq i}^n \frac {x-x_j} {x_i-x_j} \] 由此公式容易用Python实现拉格朗日插值

但是一次性将所有数据点进行插值,次数过高,不仅复杂度高,误差也大,因此常进行分段插值,即用分段函数表示 \(f(x)\)

样条插值(spline)

单纯的分段插值得到的函数性质往往不够好(光滑性)

对于划分: \(\Delta:a=x_0<x_1<\dots<x_n=b\) \(m\) 阶样条插值函数需要满足:

  • 在每个小区间 \([x_i,x_{i+1}](i=0,1,\dots,n-1)\) 上是 \(m\) 次多项式
  • 在区间 \([a,b]\) 上具有 \(m-1\) 阶导数
  • 显然阶梯插值为0阶样条插值,折线插值为1阶样条插值

    一般直接使用 scipy.interpolate 实现的样条插值

    scipy.interpolate 求解插值问题

    一维插值( interp1d

    interp1d(x,y,kind='linear')

    前两个参数为数据点向量,kind指定插值方法:

    返回一个插值函数,可以传入 \(x\) 返回 \(f(x)\) ,也可以传入 \(\vec x\) 返回 \(f(\vec x)\)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.interpolate import interp1d
    x = np.arange(0, 25, 2)
    y = np.array([12, 9, 9, 10, 18, 24, 28, 27, 25, 20, 18, 15, 13])
    xnew = np.linspace(0, 24, 500)
    f0 = interp1d(x, y, 0) # 'zero'
    y0 = f0(xnew)
    f1 = interp1d(x, y)
    y1 = f1(xnew)
    f3 = interp1d(x, y, 'cubic')
    y3 = f3(xnew)
    f5 = interp1d(x, y, 5)
    y5 = f5(xnew)
    plt.rc('font', size=16)
    plt.rc('font', family='SimHei')
    plt.subplot(221), plt.plot(xnew, y0), plt.xlabel("(A)分段阶梯插值")
    plt.subplot(222), plt.plot(xnew, y1), plt.xlabel("(B)分段线性插值")
    plt.subplot(223), plt.plot(xnew, y3), plt.xlabel("(C)三次样条插值")
    plt.subplot(224), plt.plot(xnew, y5), plt.xlabel("(D)五次样条插值")
    plt.savefig("interp1d.png", dpi=500), plt.show()

    二维插值( interp2d

    interp2d(x,y,z,kind='linear') 接受网格分布的数据点进行插值

    x,y为坐标向量,z为数据矩阵

    返回一个插值函数,输入x,y向量即可获得数据矩阵

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    from IPython.core.pylabtools import figsize
    import matplotlib.pyplot as plt
    import numpy as np
    from scipy.interpolate import interp2d
    from mpl_toolkits import mplot3d
    z = np.loadtxt("data.txt")
    x = np.arange(0, 1500, 100)
    y = np.arange(1200, -100, -100) # 文件里的y是倒序输入的
    f = interp2d(x, y, z, kind='cubic')
    xn = np.linspace(0, 1400, 141)
    yn = np.linspace(0, 1200, 121)
    zn = f(xn, yn)
    plt.rc('font', size=16)
    plt.subplot(1, 2, 1)
    plt.contour(xn, yn, zn)
    plt.xlabel('$x$'), plt.ylabel('$y$', rotation=90)
    ax = plt.subplot(1, 2, 2, projection='3d')
    X, Y = np.meshgrid(xn, yn)
    ax.plot_surface(X, Y, zn, cmap='viridis')
    ax.set_xlabel('$x$'), ax.set_ylabel('$y$'), ax.set_zlabel('$z$')
    plt.savefig('interp2d.png', dpi=500), plt.show()

    散点插值( griddata

    若数据点并无分布规律,可用 griddata 进行插值

    可处理任意D维的数据点

    griddata(points, values, xi, method='linear')

    points 为数据点位置(D维向量)的序列, values 为数据点值的序列

    xi 为需要插值的空间,形式与 points 相同,或用格点坐标矩阵的D元组表示

    method 插值方法: 'nearest','linear','cubic' 分别对应0,1,3阶插值

    返回 xi 中的数据值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from mpl_toolkits import mplot3d
    import matplotlib.pyplot as plt
    import numpy as np
    from scipy.interpolate import griddata
    x = np.array([129, 140, 103.5, 88, 185.5, 195, 105,
    157.5, 107.5, 77, 81, 162, 162, 117.5])
    y = np.array([7.5, 141.5, 23, 147, 22.5, 137.5, 85.5, -
    6.5, -81, 3, 56.5, -66.5, 84, -33.5])
    z = -np.array([4, 8, 6, 8, 6, 8, 8, 9, 9, 8, 8, 9, 4, 9])
    xy = np.array([x, y]).T
    xn = np.linspace(x.min(), x.max(), 100)
    yn = np.linspace(y.min(), y.max(), 100)
    X, Y = np.meshgrid(xn, yn)
    zn = griddata(xy, z, (X, Y), method='nearest')
    ax = plt.subplot(121, projection='3d')
    ax.plot_surface(X, Y, zn, cmap='viridis')
    ax.set_xlabel('$x$'), ax.set_ylabel('$y$'), ax.set_zlabel('$z$')
    plt.subplot(122)
    a = plt.contourf(X, Y, zn, 8, cmap=plt.cm.Spectral)
    plt.clabel(plt.contour(xn, yn, zn))
    plt.colorbar(a)
    plt.savefig('griddata.png', dpi=500), plt.show()