【问题标题】:Interpolation Python插值 Python
【发布时间】:2019-05-08 11:19:12
【问题描述】:

我的问题很简单,但是我似乎找不到快速的解决方案。

我想插入在x_model 坐标处定义的y_model 数组

x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600.,
    625.,  650.,  675.,  700.])
y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
     2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
     1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
     2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
     5.84126935e-05])

到新的,x_data 坐标:

x_data = np.array([412., 443., 490., 510., 555., 670.])

所以我应该得到一个包含 6 个元素的简单一维 y-data 数组。

我想到了这样的事情,你怎么看?

from scipy import interpolate

f                  = interpolate.interp1d(x_model, y_model, kind = 'linear')
y_data             = f(x_data)

最初是根据主要提出的问题寻求解决方案,将问题限制为线性插值。 然而,在讨论过程中,一些作者正确地指出,对于这样的问题,线性拟合是不够的。

非线性曲线拟合应该更合适吗?

【问题讨论】:

  • 有理由不使用最小二乘拟合吗?您似乎正在寻找比线性拟合所需的更复杂的方法。
  • 实际问题是什么?你遇到问题了吗?
  • 不,最小二乘可能会更好,你是对的@allo
  • @MadPhysicist,我一直在寻找最合适的(数学和编程方面)方法来解决这个看似简单的问题。在更复杂的情况下,线性插值可能会失败,所以我得到了一些很好的建议,使其在数学上更正确
  • 我将其添加为答案并链接了包含简单插值示例的文档。

标签: python arrays numpy scipy interpolation


【解决方案1】:

Numpy 有 interp 函数可以为你做这件事。 您可以简单地调用:

y_data = np.interp(x_data,x_model,y_model)

你可以在这里找到 numpy.interp() 的文档: https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html

【讨论】:

  • super,它提供了与上一个等效的解决方案!我想知道两种方法之间是否存在一些差异。谢谢!
  • 不客气。请考虑接受答案。
【解决方案2】:

最简单的方法是使用最小二乘法拟合线性函数。 numpy 中的一个简单实现是numpy.linalg.lstsq

然后,您可以使用函数lambda x: m*x+c 与计算出的斜率m 和偏移量c 来获取任何x 的线上y 值。

numpy 文档包含一个示例,这看起来几乎就像您问题中的示例。


我上面的回答是针对线性插值的情况。

关于从线性插值到一般插值的编辑:您需要知道要拟合的函数。您是否假设您的数据是线性的?

您可以对每个点集拟合一个线性函数,但结果可能很糟糕,要么是因为没有线性关系,要么是因为它是嘈杂的数据。如果不知道什么函数可能合适或噪声量有多大,就无法轻松拟合函数。

对于高阶多项式也是如此,除了您可以将 rror 从欠拟合(非线性函数的线性回归)更改为过拟合(具有与给定点匹配的过于复杂的函数,但不适用于插值)。

【讨论】:

    【解决方案3】:

    如果您希望能够检查您的线性回归并稍微调整一下,我建议您使用scikit-learn's linear regression. 代码如下:

    import numpy as np
    from sklearn.linear_model import LinearRegression
    
    x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600.,
        625.,  650.,  675.,  700.])
    y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
         2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
         1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
         2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
         5.84126935e-05])
    
    lr = LinearRegression()
    lr.fit(x_model[:, None], y_model)
    
    x_data = np.array([412., 443., 490., 510., 555., 670.])
    y_data = lr.predict(x_data[:, None])
    print(y_data)
    
    

    请注意,我必须在拟合或预测时为x 添加一个维度,因为线性回归需要一个二维数组。

    【讨论】:

      【解决方案4】:

      做到这一点的“科学”方法是将线性函数拟合到现有数据点,然后在新的 x_values 上计算函数。这具有多个优点,包括可能使用每个数据点的不确定性,以及内插值的错误传播的可能性。 (f.e 与非常好的包 'uncertainties' 结合使用)您还可以轻松更改模型函数,它不必是线性的,但可以是任何函数...

      import numpy as np
      import matplotlib.pyplot as plt
      from scipy.optimize import curve_fit
      
      
      x_model = np. array([ 400.,  425.,  450.,  475.,  500.,  525.,  550.,  575.,  600., 625.,  650.,  675.,  700.])
      y_model = np.array([  3.30395705e-03,   3.07586379e-03,   2.90207925e-03,
           2.81385536e-03,   2.78152394e-03,   2.14072505e-03,
           1.64075861e-03,   9.81255709e-04,   3.61950352e-04,
           2.15834081e-04,   1.35457654e-04,   8.22104550e-05,
           5.84126935e-05])
      
      x_data = np.array([412., 443., 490., 510., 555., 670.])
      
      
      def linFunc(x, k, d):
          return k*x+d
      
      
      cop, cov = curve_fit(linFunc, x_model, y_model)
      
      
      xplot = np.linspace(min(x_model), max(x_model), 10**4)
      
      plt.figure()
      plt.plot(x_model, y_model, 'ro', label = 'original data')
      plt.plot(xplot, linFunc(xplot, *cop), 'r--', label = "fittet function")
      plt.plot(x_data, linFunc(x_data, *cop), 'bo', label = "interpolated values")
      
      print(linFunc(x_data, *cop))
      

      【讨论】:

      • 另外,您可以使用 np.polyfit 和 scipy.stats.linregress 来避免必须定义自己的线函数。
      • 只是为了明确一点:这只能在您的整个数据集由一个相同的函数描述时使用!
      • 一方面,您没有指定判断正确性的标准。另一方面,您的问题专门针对插值,而不是回归或拟合。如果建议编辑问题,但此时它会使人们花费时间编写的所有答案都无效,因此提出另一个更具体的问题会更合适。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2013-03-31
      • 2012-08-27
      相关资源
      最近更新 更多