numpy二项式随机数效率低吗?

时间:2019-05-03 15:47:16

标签: python numpy random

我一直在采样来自不同分布的随机数,只是意识到与其他分布相比,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的参数会改变动态,因此调用单个随机数将不是直接的选择。是否可能会产生一个均匀分布的随机数数组,并根据需要将其转换为特定的二项式?

1 个答案:

答案 0 :(得分:1)

Numpy的二项式随机生成器为implemented in C,如果参数足够小,该算法将使用数值反演。如果使用p = 0.5,则可能会耗费大量精力,因为在二项式生成器中可能会使用随机位而不是随机double。此外,基本算法似乎已经多年没有变化(另请参见mtrand.pyx),因此,例如,它没有利用向量化或多线程技术。

此外,在Numpy成立之初,并没有“太多的理由来改变分配方法”,因此Numpy中的这种随机生成算法和其他随机生成算法都以可再现的“随机性”的名义保留下来。但是,如果尚未实现,则为expected to change:现在允许对随机生成方法进行重大更改,例如新的二项式随机算法,但将其视为仅在“ { {1}}发布,从不发布X.Y”。如果更快的二项式随机数对您来说很重要,则您应该提交新的Numpy issue