如何将sympy衍生物与numpy数组表达式结合起来?

时间:2014-02-16 12:03:57

标签: python arrays numpy scipy sympy

我希望我能清楚地表达我的问题。

我正在使用scipy.optimize.minimize来查找某些实验数据的最大似然估计值。数据是2d(NxN)所以在我的笔记中,对数似然函数(我需要最大化的函数)看起来像这样:

formula

所以formula是一个二维数组,取决于我的特定模型,而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 * erfjbkgNxN数组。我知道编码的唯一方法就是如上所述,即将erfierfj写为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相对于四个拟合参数的导数。我获得了将Ax0y0bkgxy定义为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'

我怀疑erfierfj是1d-arrays而bkg是2d-array这一事实。

所以我的问题如下:我如何写下表达式,以便numpysympy不会发生冲突?是否有更好的方法来编写产品erfi * erfj并仍然获得我想要的2d数组?

0 个答案:

没有答案