我正在为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。在那之前我有什么可以尝试的吗?