首页 文章

Scipy leastsq()函数开销

提问于
浏览
4

我正在研究一个图像分析程序,我已经缩小了我的瓶颈,试图将2D高斯镜片多次安装到一个小窗口(20x20)像素上 . 在此代码中花费了90%的执行时间 .

我正在使用scipy cookbook中给出的代码来解决这个问题:

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

    由于exp是单调的,你可以使用高斯的对数作为误差函数,例如:

    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)
    

    这将导致每次迭代调用1次对数,而不是每次迭代对每个数据集行进行1次调用 .

相关问题