我希望我能清楚地表达我的问题。
我正在使用scipy.optimize.minimize
来查找某些实验数据的最大似然估计值。数据是2d(NxN)所以在我的笔记中,对数似然函数(我需要最大化的函数)看起来像这样:
所以是一个二维数组,取决于我的特定模型,而n ij 是测量的二维数据。在代码中,我以这种方式编写了相同的函数:
def logll(params, *args):
A, x0, y0, bkg = params
pico, F = args
x, y = np.arange(pico.shape[0]), np.arange(pico.shape[1])
erfi = erf((x + 1 - x0) / F) - erf((x - x0) / F)
erfj = erf((y + 1 - y0) / F) - erf((y - y0) / F)
lambda_p = A * F**2 * np.pi * erfi[:, np.newaxis] * erfj / 4 + bkg
return - np.sum(pico * np.log(lambda_p) - lambda_p)
这里需要注意的重要一点是,我的数据是二维数组的一部分,因此产品erfi * erfj
和bkg
是NxN
数组。我知道编码的唯一方法就是如上所述,即将erfi
和erfj
写为1d数组并将它们相乘为erfi[:, np.newaxis] * erfj
以获得正确的数组。
这一切都运转得很好,我可以通过调用
找到我的估算器minimize(logll, x0=[A, x0, y0, bkg], args=(peak, F), method='Powell')
无论如何,这个鲍威尔方法还不够快,所以我想使用像Newton-CG
那样的速度更快的方法。缺点是它需要jacobian和hessian,为此我必须根据我的4个参数区分logll
。我不想手工完成,所以我尝试了sympy
。我不得不从我的表达式中取出[:, np.newaxis]
部分,但其他部分则表明衍生产品很好。
jacobian ll_jac
是1d数组,包含logll
相对于四个拟合参数的导数。我获得了将A
,x0
,y0
,bkg
,x
和y
定义为sympy
的符号,然后进行区分这样:
logll.diff(A)
logll.diff(x0)
logll.diff(y0)
logll.diff(bkg)
粗体ll_hess
是二维数组,包含关于四个参数的logll的二阶导数,我通过这样做得到它
logll.diff(A, A)
logll.diff(A, x0)
等等。在进行任何区分之前,我必须从[:, np.newaxis]
表达式中取消logll
部分才能使sympy
起作用。
所以,最后,随着雅各比和粗麻布的到来,我尝试了
minimize(logll, x0=[A, x0, y0, bkg], args=(peak, F),
method='Newton-CG', jac=ll_jac, hess=ll_hess)
我收到以下错误:
File "/usr/lib/python2.7/site-packages/scipy/optimize/_minimize.py", line 351, in minimize
**options)
File "/usr/lib/python2.7/site-packages/scipy/optimize/optimize.py", line 1365, in _minimize_newtoncg
update = alphak * pk
TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'
我怀疑erfi
和erfj
是1d-arrays而bkg
是2d-array这一事实。
所以我的问题如下:我如何写下表达式,以便numpy
和sympy
不会发生冲突?是否有更好的方法来编写产品erfi * erfj
并仍然获得我想要的2d数组?