要计算的数量是log(k!)
,其中k
可以是4000甚至更高,但当然日志会补偿。我试着计算sum(log(k))
,这是相同的。
所以,我有一个大的整数数组,我想有效地计算sum(log(k))
。这是我的尝试:
integers = np.asarray([435, 535, 242,])
score = np.sum(np.log(np.arange(1,integers+1)))
这可以工作,除了np.arange
会为每个整数生成一个不同大小的数组,所以当我运行它时,它会给我一个错误(它应该)。
这个问题可以很容易地通过for
循环解决,如下所示:
scores = []
for i in range(integers.shape[0]):
score = np.sum(np.log(np.arange(1,integer[i]+1)))
scores.append(score)
但是那太慢了。我实际的integers
有数百万的值需要计算。
是否有一个有效的实现,基本上不需要一个for循环?我在想一个lambda
函数或类似的东西,但我不确定如何应用它。任何帮助都是感激的!
math.lgamma怎么样?函数是阶乘,lgamma
是log。
你不需要先计算阶乘再计算对数
也有gammaln
在SciPy
代码,Python 3.9 x64 win10
import numpy as np
from scipy.special import gammaln
startf = 1 # start of factorial sequence
stopf = 400 # end of of factorial sequence
q = gammaln(range(startf+1, stopf+1)) # n! = G(n+1)
print(q)
看起来很合理
你可以这样矢量化:
mi = integers.max()
ls = np.log(np.arange(2, mi + 1))
到目前为止的两个优化:您只需要范围到最大值,因为其他数字已经覆盖了,并且您不需要log(1)
。
现在取累加和:
cs = np.cumsum(ls)
所需的元素可以直接索引:
result = cs[integers - 2]
如果这是你需要做很多次的事情,并且你知道上界,这个解决方案将比使用math.lgmamma
或scipy.special.gammaln
要快得多,一旦你预先计算了cs
的上界。
如果这是一次调用,下面是必须的一行代码:
np.cumsum(np.log(np.arange(2, np.max(integers))))[integers - 2]
如果内存是一个问题(我认为它也使他们更快),你可以做大多数的操作在原地:
mi = integers.max()
cs = np.arange(2, mi + 1)
np.cumsum(np.log(cs, out=cs), out=cs)