在scipy中的矢量化入门式logsumexp

时间:2018-01-23 06:46:20

标签: python numpy scipy vectorization

给定2D numpy数组A和1D数组c,我想用条目计算2D数组B B[i, j] = scipy.special.logsumexp(np.append(c, A[i, j]))

我可以用矢量化方式而不是使用双循环吗?

2 个答案:

答案 0 :(得分:2)

为什么不简单地使用np.log(np.sum(np.exp(c)) + np.exp(A))

[根据Paul Panzer的评论更新]

_c = np.broadcast_to(c, (*A.shape, *c.shape))
B = scipy.special.logsumexp(np.append(_c, A[...,np.newaxis], axis=-1), axis=-1)

答案 1 :(得分:2)

要模仿logsumexp的行为,您需要做的就是在取max之前减去其参数的exp, sum, log(检查source code)然后重新在最后添加它。因此,您可以执行以下操作:

>>> import numpy as np
>>> from scipy import special
>>> 
>>> A = np.random.uniform(900, 1100, (4, 4))
>>> c = np.random.uniform(950, 1050, (7,))
>>> 
>>> cm = np.max(c)
>>> mask = A > cm
>>> B = np.empty_like(A)
>>> B[mask] = A[mask] + np.log(np.exp(np.subtract.outer(cm, A[mask])).sum(axis=-1) + 1)
>>> B[~mask] = cm + np.log(np.exp(c - cm).sum() + np.exp(A[~mask] - cm))
>>> 
# compute via logsumexp for reference
>>> cA = np.empty((8, 4, 4))
>>> cA[:-1] = c[:, None, None]
>>> cA[-1] = A
>>> special.logsumexp(cA, axis=0)
array([[ 1048.88855012,  1048.88854955,  1069.83524808,  1048.88854955],
       [ 1048.88854955,  1048.88854955,  1048.88877212,  1048.93142975],
       [ 1048.88854955,  1067.59166572,  1048.88854955,  1069.78737913],
       [ 1048.88854955,  1048.88854955,  1098.61910373,  1072.76058998]])
>>> B
array([[ 1048.88855012,  1048.88854955,  1069.83524809,  1048.88854955],
       [ 1048.88854955,  1048.88854955,  1048.88877212,  1048.93142975],
       [ 1048.88854955,  1067.59166572,  1048.88854955,  1069.78737914],
       [ 1048.88854955,  1048.88854955,  1098.61910374,  1072.76058999]])