Scipy leastsq() 函数的开销
我正在开发一个图像分析程序,发现程序的瓶颈在于多次尝试将一个2D高斯函数拟合到一个小窗口(20x20像素)上。执行时间的90%都花在这段代码上。
我使用的是scipy食谱中提供的代码来解决这个问题:
def gaussian(height, center_x, center_y, width_x, width_y):
"""Returns a gaussian function with the given parameters"""
width_x = float(width_x)
width_y = float(width_y)
return lambda x,y: height*exp(
-(((center_x-x)/width_x)**2+((center_y-y)/width_y)**2)/2)
def moments(data):
"""Returns (height, x, y, width_x, width_y)
the gaussian parameters of a 2D distribution by calculating its
moments """
total = data.sum()
X, Y = indices(data.shape)
x = (X*data).sum()/total
y = (Y*data).sum()/total
col = data[:, int(y)]
width_x = sqrt(abs((arange(col.size)-y)**2*col).sum()/col.sum())
row = data[int(x), :]
width_y = sqrt(abs((arange(row.size)-x)**2*row).sum()/row.sum())
height = data.max()
return height, x, y, width_x, width_y
def fitgaussian(data):
"""Returns (height, x, y, width_x, width_y)
the gaussian parameters of a 2D distribution found by a fit"""
params = moments(data)
errorfunction = lambda p: ravel(gaussian(*p)(*indices(data.shape)) -
data)
p, success = optimize.leastsq(errorfunction, params, maxfev=50, ftol=1.49012e-05)
return p
通过将errorfunction()和gaussian()这两个函数合并,我成功将执行时间缩短了一半。这样每次leastsq()调用errorfunction()时,只需要调用一个函数,而不是两个。
这让我觉得剩下的执行时间大部分是因为函数调用的开销,因为leastsq()算法在调用errorfunction()时会产生额外的时间消耗。
有没有办法减少这种函数调用的开销呢?我对此感到困惑,因为leastsq()需要一个函数作为输入。
如果我的描述让人困惑,我先在这里道个歉。我是机械工程师,现在正在学习Python。如果还有其他信息能帮助到你,请告诉我。
1 个回答
1
因为指数函数是单调的,你可以用高斯函数的对数作为你的误差函数,比如:
def log_gaussian(height, center_x, center_y, width_x, width_y):
"""Returns a gaussian function with the given parameters"""
width_x = float(width_x)
width_y = float(width_y)
log_height = log(height)
return lambda x,y: (log_height -
(((center_x-x)/width_x)**2 - ((center_y-y)/width_y)**2)/2)
这样做的话,每次迭代只需要调用一次对数函数,而不是每处理一行数据就调用一次指数函数。