【问题标题】:extrapolating data with numpy/python用 numpy/python 推断数据
【发布时间】:2013-10-24 17:20:58
【问题描述】:

假设我有一个简单的数据集。也许以字典的形式,它看起来像这样:

{1:5, 2:10, 3:15, 4:20, 5:25}

(顺序总是升序的)。 我想做的是从逻辑上弄清楚下一个数据点最有可能是什么。在这种情况下,例如,它将是{6: 30}

最好的方法是什么?

【问题讨论】:

标签: python python-2.7 numpy scipy


【解决方案1】:

你也可以使用numpy的polyfit

data = np.array([[1,5], [2,10], [3,15], [4,20], [5,25]])
fit = np.polyfit(data[:,0], data[:,1] ,1) #The use of 1 signifies a linear fit.

fit
[  5.00000000e+00   1.58882186e-15]  #y = 5x + 0

line = np.poly1d(fit)
new_points = np.arange(5)+6

new_points
[ 6, 7, 8, 9, 10]

line(new_points)
[ 30.  35.  40.  45.  50.]

这使您可以很容易地更改多项式拟合的程度,因为函数polyfit 采用以下参数np.polyfit(x data, y data, degree)。显示的是线性拟合,其中返回的数组看起来像 fit[0]*x^n + fit[1]*x^(n-1) + ... + fit[n-1]*x^0 对于任何程度 npoly1d 函数允许您将此数组转换为一个函数,该函数返回任意给定值x 处的多项式值。

一般来说,没有很好理解的模型的推断最多只能得到零星的结果。


指数curve fitting

from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a * np.exp(-b * x) + c

x = np.linspace(0,4,5)
y = func(x, 2.5, 1.3, 0.5)
yn = y + 0.2*np.random.normal(size=len(x))

fit ,cov = curve_fit(func, x, yn)
fit
[ 2.67217435  1.21470107  0.52942728]         #Variables

y
[ 3.          1.18132948  0.68568395  0.55060478  0.51379141]  #Original data

func(x,*fit)
[ 3.20160163  1.32252521  0.76481773  0.59929086  0.5501627 ]  #Fit to original + noise

【讨论】:

  • 谢谢你的好先生,但如果你不介意我问,'fit'变量到底是什么?比如,它意味着什么?
  • @Crowz - 这是一个线性模型。正如 Ophion 的评论所提到的,它是 y = fit[0] * x + fit[1]
  • 是否有办法暗示模型遵循更指数化的路径?
  • @Crowz 你总是可以拟合指数;然而,指数拟合本质上更困难。请提供一个完整的示例来说明您正在尝试做的事情。
【解决方案2】:

正如answer 对相关问题所指出的那样,从 scipy 的 0.17.0 版开始,scipy.interpolate.interp1d 中有一个选项允许线性外推。在你的情况下,你可以这样做:

>>> import numpy as np
>>> from scipy import interpolate

>>> x = [1, 2, 3, 4, 5]
>>> y = [5, 10, 15, 20, 25]
>>> f = interpolate.interp1d(x, y, fill_value = "extrapolate")
>>> print(f(6))
30.0

【讨论】:

    【解决方案3】:

    在 Python 聊天中与您讨论后 - 您正在将数据拟合成指数。这应该是一个相对较好的指标,因为您不是在寻找长期外推。

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    
    def exponential_fit(x, a, b, c):
        return a*np.exp(-b*x) + c
    
    if __name__ == "__main__":
        x = np.array([0, 1, 2, 3, 4, 5])
        y = np.array([30, 50, 80, 160, 300, 580])
        fitting_parameters, covariance = curve_fit(exponential_fit, x, y)
        a, b, c = fitting_parameters
        
        next_x = 6
        next_y = exponential_fit(next_x, a, b, c)
        
        plt.plot(y)
        plt.plot(np.append(y, next_y), 'ro')
        plt.show()
    

    最右侧轴上的红点表示下一个“预测”点。

    【讨论】:

      【解决方案4】:

      由于您的数据近似线性,您可以执行 linear regression,然后使用该回归的结果来计算下一个点,使用 y = w[0]*x + w[1](保留链接示例中的符号 y = mx + b)。

      如果您的数据不是近似线性的,并且您没有其他一些回归理论形式,那么一般推断(使用多项式或样条曲线)的可靠性要低得多,因为它们可能会超出已知数据点有点疯狂.例如,查看接受的答案here

      【讨论】:

        【解决方案5】:

        使用scipy.interpolate.splrep

        >>> from scipy.interpolate import splrep, splev
        >>> d = {1:5, 2:10, 3:15, 4:20, 5:25}
        >>> x, y = zip(*d.items())
        >>> spl = splrep(x, y, k=1, s=0)
        >>> splev(6, spl)
        array(30.0)
        >>> splev(7, spl)
        array(35.0)
        >>> int(splev(7, spl))
        35
        >>> splev(10000000000, spl)
        array(50000000000.0)
        >>> int(splev(10000000000, spl))
        50000000000L
        

        How to make scipy.interpolate give an extrapolated result beyond the input range?

        【讨论】:

        • 小心使用样条线进行外推。他们倾向于在末端“过冲”。使用样条曲线很容易获得比您的数据大或小几个数量级的外推估计。它们非常适合插值,但对于外插来说却是一个非常糟糕的选择。
        猜你喜欢
        • 2021-08-24
        • 2015-11-01
        • 2016-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多