2016-11-27 53 views
0

這篇文章建立在我剛纔的問題曲線擬合優化SciPy的Python的numpy的

我有一些X數據和一些Y數據,Y數據可以適合作爲X數據的加權和,和我的問題是找到最適合的係數。

我現在明白了一種方法,但我意識到它可能不是最好的或最佳的方式。

但是,我所擁有的X數據有時可能會發生偏移,因此只有在將X的每列向上或向下移動N個增量後才能獲得最佳擬合。

我試圖看看np.roll是否可以用來做到這一點,但我卡住了,因爲我的函數現在需要np.roll的係數和整數值,可用於向上或向下移動列N以改善適合度。

我認爲我的主要問題是不明白如何將這兩種不同的參數傳遞給curvefit - 可能嗎?

也許np.roll不是最好的方法嗎?所以任何建議的另一種方式也將不勝感激。

在我下面的例子中,將第二列移動-1會使Xdata更適合Ydata。

xdata = np.array([[1.0, 1.0],[1.0, 1.0], [2.0, 3.0], [4.0, 2.0], [2.0, 1.0],[1.0, 1.0]]) 

ydata = np.array([3.0, 5.0, 6.0, 9.0, 5.0, 3.0]) 


def fitfunc(xdata, *params): 
    ctx = 0.0 

    # y is not yet defined by somehow I would like it to take the values passed in the second np.array defined in c below 
    # the for loop should just run twice in this example 

    for n in range(len(params)): 
     ctx = params[n]*np.roll(xdata[:,n], y, axis=0) + ctx 
    return ctx, y 

#initial guesses for fitting parameters 
c = (np.array([0.6, 0.3]), np.array([1, 1])) # the second np.array is what I would like to pass a y's 

# fit data using SciPy's Levenberg-Marquart method 
nlfit, nlpcov = scipy.optimize.curve_fit(fitfunc, xdata, ydata, p0=(c), sigma=None) 

print (nlfit) 

謝謝你提前爲任何幫助

+0

您是否嘗試使用形式爲y = mx + b的線性模型,並且想要包含常數項b,從而將線路上下移動?或者,您的數據是一組時間序列,您不確定要使用哪些x變量的滯後(可能由np.roll暗示)? – David

+0

我的數據是光譜。所以Xdata數組可能是兩列按列排列的光譜矩陣。從我之前關於這個主題的問題中,我相信我的Xdata可以將我的ydata描述爲X * a + X * b ... etc = Ydata。我想在試圖優化擬合時上下移動我的x數據列的原因是,實驗性錯誤意味着這樣的轉變在實際數據中是常見的,因此,以及將Xdata的每列與係數相乘,I'希望有一些方法可以嘗試Xdata列彼此間的相對轉換,以找到最適合的方式。 – steve

+0

我希望澄清我希望實現的目標? np.roll只是我認爲我可以實現列之間相對移動的一種方式。所涉及的光譜有幾千個點,所以我的想法是,從一端向另一端滾動幾個點,反之亦然,以獲得更好的配合可能是實現這一目標的一種方式。 – steve

回答

0

curve_fit預計的參數,你可以,但是你想在fitfunc使用單個陣列。在這個例子中,我們有p列,每列都有一個斜率和一個移位,所以最後我們需要一個2 * p元素的參數數組。初始參數陣列需要看起來像這樣:

c = np.array([0.6, 0.3, 1, 1]) 

內部fitfunc,我分裂參數數組成:

  • slope_params,斜率參數陣列,使用params[:cols],這需要第一p元素,和
  • shift_params,一個移位參數數組,使用params[cols:],它取最後的p個元素。

fitfunc全碼:

def fitfunc(xdata, *params): 
    # Get number of columns in data 
    cols = xdata.shape[1] 

    # Get slope parameters 
    slope_params = params[:cols] 

    # Get shift parameters and convert to int 
    shift_params = [int(round(n)) for n in params[cols:]] 

    # Calculate fit 
    ctx = 0.0 
    for n in range(len(slope_params)): 
     ctx = slope_params[n] * np.roll(xdata[:,n], shift_params[n], axis=0) + ctx 

    # Show progress 
    print(params) 

    return ctx 

請注意,我們必須轉變參數轉換爲整數,使用[int(round(n)) for n in params[cols:]]

使用這種與curve_fit不會改變在所有位移參數,並且給出一個警告:

(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0) 
(0.60000000894069672, 0.29999999999999999, 1.0, 1.0) 
(0.59999999999999998, 0.30000000447034836, 1.0, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0000000149011612, 1.0) 
(0.59999999999999998, 0.29999999999999999, 1.0, 1.0000000149011612) 
(-0.40816307558733345, 3.6326528012731845, 1.0, 1.0) 
(-0.40816306950522968, 3.6326528012731845, 1.0, 1.0) 
(-0.40816307558733345, 3.6326528554039292, 1.0, 1.0) 
(-0.40816307558733345, 3.6326528012731845, 1.0000000149011612, 1.0) 
(-0.40816307558733345, 3.6326528012731845, 1.0, 1.0000000149011612) 
(-0.40816327556523363, 3.632653071646589, 1.0, 1.0) 
OptimizeWarning: Covariance of the parameters could not be estimated 
    category=OptimizeWarning) 
[-0.40816328 3.63265307 1.   1.  ] 

您可能能夠調整優化設置,以獲得更好的成績,但我不認爲這是你的問題最有前途的方法。

+0

感謝您解釋如何最有用地看到這個機制,並且毫無疑問會對其他人有用,即使您認爲對我來說也不會解決原始問題 – steve