我一直在采样来自不同分布的随机数,只是意识到与其他分布相比,numpy二项式随机数有多慢。例如
%timeit for x in range(100): np.random.binomial(100,0.5)
10000 loops, best of 3: 82.6 µs per loop
%timeit for x in range(100): np.random.uniform()
100000 loops, best of 3: 14.6 µs per loop
一个二项式数要比一个统一的数大六倍!这是可以理解的,因为二项式是离散的并且需要更复杂的变换。但是,例如,如果我要求二项式试验的次数为n = 0或n = 1,则花费的时间是相似的:
%timeit for x in range(100): np.random.binomial(0,0.5)
10000 loops, best of 3: 78.8 µs per loop
%timeit for x in range(100): np.random.binomial(1,0.5)
10000 loops, best of 3: 80.1 µs per loop
这似乎不是很有效,因为这些采样的结果应该是微不足道的:对于零次试验,结果应始终为零,而对于1次试验,则应为简单的伯努利试验。因此,例如,二项式的更快实现将是:
import numpy as np
def custombinomial(n,p):
if n == 0:
return 0
if n == 1:
x = np.random.uniform()
if x<p:
return 1
else:
return 0
else:
return np.random.binomial()
现在是时间:
%timeit for x in range(100): custombinomial(0,0.5)
100000 loops, best of 3: 11.8 µs per loop
%timeit for x in range(100): custombinomial(1,0.5)
10000 loops, best of 3: 31.2 µs per loop
我确信即使更大的n值也可以改善。我有什么理由想念numpy这么慢吗?还有其他库可以提供更快的随机数(即使它包含某种C / Cython)吗?
此外,此外,我知道numpy很好,如果我想同时创建一堆随机数,即获得一个二项分布的数的数组,但是在许多情况下,分布n和p的参数会改变动态,因此调用单个随机数将不是直接的选择。是否可能会产生一个均匀分布的随机数数组,并根据需要将其转换为特定的二项式?
答案 0 :(得分:1)
Numpy的二项式随机生成器为implemented in C,如果参数足够小,该算法将使用数值反演。如果使用p = 0.5
,则可能会耗费大量精力,因为在二项式生成器中可能会使用随机位而不是随机double
。此外,基本算法似乎已经多年没有变化(另请参见mtrand.pyx
),因此,例如,它没有利用向量化或多线程技术。
此外,在Numpy成立之初,并没有“太多的理由来改变分配方法”,因此Numpy中的这种随机生成算法和其他随机生成算法都以可再现的“随机性”的名义保留下来。但是,如果尚未实现,则为expected to change:现在允许对随机生成方法进行重大更改,例如新的二项式随机算法,但将其视为仅在“ { {1}}发布,从不发布X.Y
”。如果更快的二项式随机数对您来说很重要,则您应该提交新的Numpy issue。