2017-10-07 85 views
0

我不能得到這個棚車適合的工作...我得到「OptimizeWarning:參數的協方差無法估計 類別= OptimizeWarning)」,輸出係數不會超出開始的猜測。問題配件使用SciPy的的曲線擬合在Python棚車功能

import numpy as np 
from scipy.optimize import curve_fit 
def box(x, *p): 
    height, center, width = p 
    return height*(center-width/2 < x)*(x < center+width/2) 

x = np.linspace(-5,5) 
y = (-2.5<x)*(x<2.5) + np.random.random(len(x))*.1 

coeff, var_matrix = curve_fit(box, x, y, p0=[1,0,2]) 

輸出係數是[1.04499699,0.,2],而不是第三個甚至沒有改變。

我懷疑這個函數形式不適合curve_fit使用的levenberg-marquardt算法,這很麻煩,因爲我喜歡這個函數。在mathematica中,指定蒙特卡羅優化將是微不足道的。

+1

你所說的「工作」是什麼意思?這是一個警告,而不是一個錯誤,並告訴你一些關於估計值的信心。但是,當我運行你提供的代碼片段時,我對數據有合理的適應性。 – bnaecker

+0

我已經在上面添加了更多細節。基本上,係數不會超出初始猜測。 – ARN

+0

您發佈的代碼似乎缺少一些導入語句,無法運行。 –

回答

2

我懷疑這個函數形式是不適合由curve_fit

你是正確使用的Levenberg-Marquardt算法。通常,基於漸變的優化不太適合具有尖銳邊緣的函數。通過擾動函數參數來估計梯度,並觀察擬合質量的變化。然而,移動邊沿剛好在零梯度一點的結果,如果它不跨一個數據點:

enter image description here

  • 答:很容易適應的幅度,因爲高度的微小變化immediaterly導致殘差的變化。
  • B:很難擬合邊緣,因爲位置的小變化不會影響殘差(除非變化足夠大,使邊緣與數據點交叉)。

使用隨機方法應該會更好。 Scipy具有differential_evolution函數,它使用遺傳算法,因此與monte-carlo方法有關。但是,使用比curve_fit更簡單。你需要指定一個成本的功能和範圍的參數爲:

res = differential_evolution(lambda p: np.sum((box(x, *p) - y)**2), # quadratic cost function 
          [[0, 2], [-5, 5], [0.1, 10]]) # parameter bounds 

它仍然是一個班輪:)

coeff, var_matrix = curve_fit(box, x, y, p0=[1,0,2]) 

res = differential_evolution(lambda p: np.sum((box(x, *p) - y)**2), [[0, 2], [-5, 5], [0.1, 10]]) 

plt.step(x, box(x, *coeff), where='mid', label='curve_fit') 
plt.step(x, box(x, *res.x), where='mid', label='diff-ev') 
plt.plot(x, y, '.') 
plt.legend() 

enter image description here