我正在嘗試使用scipy.optimize.leastsq
,該函數使用預分配的內存來存儲殘差。我有數以百萬計的非線性擬合,時間非常關鍵。我在C
中編寫了擬合函數,並且我注意到,當fit函數簡單地返回對作爲輸入獲取的緩衝區內存的引用時,scipy.optimize.leastsq
無法正常工作。當我發現問題可以在純粹的Python
中複製時,我以爲我搞砸了Py_INCREF
。下面是一些說明問題的實體模型代碼(實際問題有不同的適合的功能和複雜得多):在scipy.optimize.leastsq中使用預分配的緩衝區內存函數擬合函數
import numpy as np
import scipy.optimize as opt
# the mock-up data to be fitted
x = np.arange(5.)
noise = np.array([0.0, -0.02, 0.01, -0.03, 0.01])
y = np.exp(-x) + noise
# preallocate the buffer memory
buf = np.empty_like(x)
# fit function writing residuals to preallocated memory and returning a reference
def dy(p, x, buf, y):
buf[:] = p[0]*np.exp(-p[1]*x) - y
return buf
# starting values (true values are [1., 1.])
p0 = np.array([1.2, 0.8])
# leastsq with dy(): DOESN'T WORK CORRECTLY
opt.leastsq(dy, p0, args=(x, buf, y))
# -> (array([ 1.2, 0.8]), 4)
爲了使它正常工作,我必須包裝擬合函數爲一體,使一個副本:
# wrapper that calls dy() and returns a copy of the array
def dy2(*args):
return dy(*args).copy()
# leastsq with dy2(): WORKS CORRECTLY
opt.leastsq(dy2, p0, args=(x, buf, y))
# -> (array([ 0.99917134, 1.03603201]), 1)
......但使一個副本顯然使用緩衝存儲器擺在首位!作爲一個側面說明,opt.fmin
也有像這樣的緩衝存儲器的工作(但在實際中速度過慢我的應用程序):
def sum2(p, x, buf, y):
dy(p, x, buf, y)
return buf.dot(buf)
opt.fmin(sum2, p0, args=(x, buf, y))
# Optimization terminated successfully.
# Current function value: 0.001200
# Iterations: 32
# Function evaluations: 63
# -> array([ 0.99915812, 1.03600273])
任何想法,爲什麼scipy.optimize.leastsq
作品正確地dy2()
而不是與dy()
在上面的例子?
你確定內部沒有重用緩衝區嗎?從'leastsq'代碼中調用minpack函數'_minpack._lmdif'和'_minpack._lmder',除此之外,除了參數檢查之外,沒有任何計算。我會假設他們在內部這樣做。所以你不需要預先分配它。 – Bort