2017-03-03 103 views
2

我想寫一些非常基本的Python代碼,輸出基於輸入和輸出樣本的數字。因此,例如,如果:從曲線擬合Python估計值

x = [1, 2, 3, 4, 5] 
y = [2, 5, 10, 17, 26] 

z = np.interp(7, xp, yp) 
print(z) ##expected 50, actual was 26 

我想有辦法找到這些值映射在一起的最佳擬合函數,這樣我可以通過它的另一個x值,並得到y值的粗略近似。我嘗試閱讀scipy.optimize.curve_fit,但據我所知,這不是我應該使用的,因爲這使用了預定義的函數,在我的情況下我沒有。

注意,我沒有限制函數是否應該是線性/週期/二次等,因爲我的值會有所不同,但我的假設是,大部分函數應該是線性的。

我也試過numpy.interp但我只是得到y陣列中的最後一個值,無論我輸入的是x

編輯:經過與Cleb的答案混亂,然後與肯尼特的原始方法進行比較,這裏是我的發現。 enter image description here這裏最準確的技術應該是最接近紅線的功能。綠線代表kennytm的方法(二次迴歸是我嘗試的最準確的方法),黑線代表Cleb的技術(UnivariateSpline)。看起來,因爲UnivariateSpline沒有事先知道底層模型,所以在適應函數的值時會稍微好一些,這會使函數的值更精確一些。

+2

您正在尋找的概念是[插入](https://en.wikipedia.org/wiki/Interpolation)。例如,請參閱[scipy插入教程](https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html)以獲取['scipy中可用的一些工具的描述.interpolate'包](https://docs.scipy.org/doc/scipy/reference/interpolate.html)。 –

+0

對於一維數據的線性插值,['numpy.interp()'](https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html)可能就是你需要的一切。 –

+0

@warrenweckesser我不認爲這是,我只是試過了。檢查我最後的編輯。 – ninesalt

回答

2

另一種選擇是使用樣條,例如, scipy.interpolate.UnivariateSpline,如果你不關心底層模型(例如線性,立方體等)和過度擬合。

然後,你可以這樣做:

from scipy.interpolate import UnivariateSpline 

x = [1, 2, 3, 4, 5] 
y = [2, 5, 10, 17, 26] 
spl = UnivariateSpline(x, y) 

要在x=7得到的估計,你現在可以簡單地做:

spl(7) 

返回你所期望的值:

array(49.99999999999993) 

該方法避免了模型的定義。

+0

這不是我不一定關心模型,而只是我不確定。我會嘗試你的方法,並且將它與kennytm答案的準確性進行比較。你會說你的方法有多準確? – ninesalt

+0

@ Swailem95:不確定一個人是否可以普遍回答你的問題;它將取決於你處理的數據。我總是將你的實際數據與樣條一起繪製,看看它是否「有意義」。讓我知道你的比較結果! – Cleb

+1

檢查我最後的編輯。 – ninesalt

2

我試過閱讀約scipy.optimize.curve_fit,但據我所知,這不是我應該使用的,因爲這使用了一個預定義的函數,在我的情況下,我沒有。

其實scipy.optimize.curve_fit的功能是你想要的模型。你說你想要的線性迴歸,那麼你用:

def linear(x, a, b): 
    return a*x + b 

fit_params, _ = scipy.optimize.curve_fit(linear, xp, yp) 
print(linear(7, *fit_params)) 
# 36.0 

的二次迴歸等類似:

def quadratic(x, a, b, c): 
    return a*x*x + b*x + c 

fit_params, _ = scipy.optimize.curve_fit(quadratic, xp, yp) 
print(quadratic(7, *fit_params)) 
# 50.000000000004555 

(的curve_fit第二返回值是輸出的協變矩陣,它給出了一個粗略的圖片配合有多好)


如果你只是想以適應最小二乘多項式,你可以只use numpy.polyfit

linear_coeff = numpy.polyfit(xp, yp, deg=1) 
print(numpy.polyval(linear_coeff, 7)) 
# 35.999999999999986 

quadratic_coeff = numpy.polyfit(xp, yp, deg=2) 
print(numpy.polyval(quadratic_coeff, 7)) 
# 50.000000000000085 
+1

要將多項式擬合到數據集,另一個選項是'numpy.polyfit()'。 –

+0

如果我不知道數據是線性的還是二次的?就我而言,我有一套從1980年到2014年的年份,每年都映射到不同的價值(功耗),價值並不總是明顯的趨勢。 – ninesalt

+2

@ Swailem95嗯OP說「大部分功能應該是線性的」。我認爲如果你不知道你的數據是什麼樣的,scipy是不夠的。 – kennytm