2013-10-16 228 views
7

假設我有一個簡單的數據集。也許在字典的形式,它應該是這樣的:用numpy外推數據/ python

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

(順序總是遞增)。 我想要做的是從邏輯上弄清楚下一個數據點最有可能是什麼。在這種情況下,例如,它會是{6: 30}

什麼是最好的方法來做到這一點?

+0

[?如何使scipy.interpolate給予超出輸入範圍的外推結果(HTTP的可能重複。com/questions/2745329/how-to-make-scipy-interpolate-give-an-extrapolated-result-beyond-the-input-range) – Yoann

+1

詞典是無序集合,所以你的「順序總是上升」的註釋可能是這是一個危險的假設,因爲'd'中的鍵將遍歷鍵,但是Python看起來合適,而不是按照你創建的順序。 – Jaime

+1

我的意思是說數據更多,因爲在每個數字上更高的鍵具有數值上更高的值 – corvid

回答

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() 

右上角的紅點表示下一個「預測」點。

1

由於數據是近似線性你可以做一個linear regression,然後使用結果從該回歸來計算下一個點,使用y = w[0]*x + w[1](保持從鏈接的示例的符號爲Y = mx + b中)。

如果你的數據不是線性的,而且你沒有其他的迴歸理論形式,那麼一般的外推法(使用多項式或樣條曲線)就不那麼可靠了,因爲它們可能比已知數據有點瘋狂點。例如,請參閱接受的答案here

0

使用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?

+4

請謹慎使用樣條進行外插。他們傾向於在最後「超調」。使用樣條線可以非常容易地得到外推估計大於或小於數據的數量級。它們非常適合插值,但是推斷的選擇非常糟糕。 –

5

您還可以使用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 
+0

謝謝你,先生,但如果你不介意我問,'fit'變量究竟是什麼?如在中,它意味着什麼? – corvid

+1

@Crowz - 這是一個線性模型。正如Ophion的評論所述,它是'y = fit [0] * x + fit [1]'。 –

+0

會有一種方法來暗示一個遵循更多指數路徑的模型嗎? – corvid

3

正如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