2015-02-09 73 views
2

我有兩個列表,我試圖做一個形式之間的指數擬合y = a * e ^(bx)。我使用的方法類似於here的第二個答案,但是結果與我從excel測試中得知的結果不匹配。這裏是我的代碼:2列表之間的指數擬合

import numpy as np 
from scipy.optimize import curve_fit 
exp_constants = [62.5, 87.5, 112.5, 137.5, 162.5, 187.5, 212.5, 237.5, 262.5, 287.5] 
means = [211.94, 139.30, 80.09, 48.29, 26.94, 12.12, 3.99, 1.02, 0.09, 0.02] 
def func(x1, a, b): 
    return a * np.exp(b * x1) 
popt, pcov = curve_fit(func, exp_constants, means) 

當返回popt[0]popt[1]我分別得到3.222e-127和1.0。但是,當用excel檢查時,正確的指數方程應該是y = 7231.3e ^( - 0.04x)。我對curve_fit方法不是很熟悉,在代碼中是否缺少某些東西,或者有更好的方法來獲得正確的指數擬合?

編輯:這是用下面的代碼所做的情節:

plt.figure() 
plt.plot(exp_constants, means, 'ko', label="Data") 
plt.plot(exp_constants, func(exp_constants, *popt), 'r-', label="Fitted Curve") 
plt.legend() 
plt.show 

plot

+0

你有你的繪圖配合和數據點? – 2015-02-09 16:22:57

+0

是的,看編輯添加到原始問題 – mbreezy 2015-02-09 16:55:53

回答

5

我想這個問題是你沒有爲參數提供的初始猜測,所以as per the manualcurve_fit使用[1,1]作爲猜測。然後優化可能會陷入局部最小值。你應該做的另一件事是改變你的xdataydata名單numpy的陣列,如圖this answer

import numpy as np 
from scipy.optimize import curve_fit 
exp_constants = np.array([62.5, 87.5, 112.5, 137.5, 162.5, 187.5, 212.5, 
          237.5, 262.5, 287.5]) 
means = np.array([211.94, 139.30, 80.09, 48.29, 26.94, 12.12, 3.99, 
        1.02, 0.09, 0.02]) 
def func(x1, a, b): 
    return a * np.exp(b * x1) 
guess = [100, -0.1] 
popt, pcov = curve_fit(func, exp_constants, means, p0 = guess) 

猜測的確切值並不重要,但你可能應該至少具有順序幅度和正確的符號,以便優化可以收斂到最佳值。我剛剛使用了一些接近你提到的「正確答案」的隨機數字。當你不知道該猜測什麼時,你可以做一個polyfit(xdata, log(ydata), 1)和一些基本的數學運算來獲得一個初始值,如this answer對你所鏈接的問題所示。

快速的情節:

x = np.linspace(exp_constants[0], exp_constants[-1], 1000) 
plt.plot(exp_constants, means, 'ko', x, popt[0]*np.exp(popt[1]*x), 'r') 
plt.show() 

結果:

enter image description here

+0

感謝您的解釋,一切似乎現在正常工作! – mbreezy 2015-02-09 19:25:44