如何调试scipy.optimize.minimize梯度方法错误/警告

时间:2015-08-06 20:24:47

标签: python statistics scipy

我正在为2d数据编写适合的例程。简而言之,我有5x5像素数据可以用这个参数函数建模(A,x0,y0,fwhm):

from scipy.special import erf

def lambda_g(A, x0, y0, fwhm, bkg, size):
    fwhm *= 0.6
    x, y = np.arange(size), np.arange(size)
    derfx = erf((x + 1 - x0) / fwhm) - erf((x - x0) / fwhm)
    derfy = erf((y + 1 - y0) / fwhm) - erf((y - y0) / fwhm)
    return 0.25 * A * fwhm**2 * np.pi * derfx[:, np.newaxis] * derfy

因此模拟数据可以是:

sim = lambda A, x0, y0, fwhm, bkg: lambda_g(A, x0, y0, fwhm, 5) + np.random.normal(bkg, bkg/100, (5, 5))

无论如何,我希望你还和我在一起。我想使用最大似然优化拟合数据,以获得参数A,x0,y0,bkg。所以我计算了loglikelihood函数,以及jacobian。他们在这里:

def logll(parameters, *args):
    A, x0, y0, bkg = parameters
    fwhm, area = args

    lambda_p = lambda_g(A, x0, y0, fwhm, area.shape[0]) + bkg
    return -np.sum(area * np.log(lambda_p) - lambda_p)


def ll_jac(parameters, *args):
    A, x0, y0, bkg = parameters
    fwhm, area = args

    size = area.shape[0]
    x, y = np.arange(size), np.arange(size)

    dexpx = np.exp(-((x + 1 - x0)/(fwhm*0.6))**2) - np.exp(-((x - x0)/(fwhm*0.6))**2)
    dexpy = np.exp(-((y + 1 - y0)/(fwhm*0.6))**2) - np.exp(-((y - y0)/(fwhm*0.6))**2)
    derfx = erf((x + 1 - x0) / (fwhm*0.6)) - erf((x - x0) / (fwhm*0.6))
    derfy = erf((y + 1 - y0) / (fwhm*0.6)) - erf((y - y0) / (fwhm*0.6))
    factor = 1 - area/(lambda_g(A, x0, y0, fwhm, size) + bkg)

    jac = np.zeros(4)
    # dL/d(A)
    # The derivative of lambda_g is lambda_g(A=1)
    jac[0] = -np.sum(factor*lambda_g(1, x0, y0, fwhm, size))

    # dL/d(x0) y dL/d(y0)
    # 0.3 = 0.5*0.6
    jac12 = 0.3*A*fwhm*np.sqrt(np.pi)
    jac[1] = jac12*np.sum(dexpx[:, np.newaxis]*derfy*factor)
    jac[2] = jac12*np.sum(dexpy[:, np.newaxis]*derfx*factor)

    # dL/d(bkg)
    jac[3] = -np.sum(factor)

    return jac

拟合例程如下:

from scipy.ndimage.measurements import center_of_mass
from scipy.optimize import minimize

def fit_area(area, fwhm):

    # First guess of parameters
    bkg = np.min(area)
    A = area[np.floor(area.shape[0]/2), np.floor(area.shape[1]/2)] - bkg
    A /= 0.65
    x0, y0 = center_of_mass(area)

    results = minimize(logll, [A, x0, y0, bkg], args=(fwhm, area),
                       method='CG', options={'disp': True})
    return results.x

只要我选择“Powell”之类的方法,就不需要渐变。我想使用渐变方法,因为它应该更快。 使用我的渐变,我得到警告Desired error not necessarily achieved due to precision loss.并且结果非常糟糕。如果我让scipy估计渐变,我也会得到警告但效果很好。最后,Powell方法不会发出警告并返回更好的结果。

我即将退出渐变方法并坚守Powell。在那之前我有什么可以尝试的吗?

0 个答案:

没有答案