问题 来自scipy.stats的随机抽取之间的差异... rvs和numpy.random


似乎它是相同的分布,从中抽取随机样本 numpy.random 比这更快 scipy.stats.-.rvs。我想知道导致两者之间速度差异的原因是什么?


3679
2017-10-22 23:07


起源



答案:


scipy.stats.uniform实际上使用了numpy,这里是stats中的相应函数(mtrand是numpy.random的别名)

class uniform_gen(rv_continuous):
    def _rvs(self):
        return mtrand.uniform(0.0,1.0,self._size)

scipy.stats有一些错误检查的开销,使界面更灵活。只要你不为每次抽奖调用uniform.rvs,速度差应该是最小的。你可以一次性获得所有随机抽取,例如(1000万)

>>> rvs = stats.uniform.rvs(size=(10000, 1000))
>>> rvs.shape
(10000, 1000)

这是我刚才写的很长的答案:

scipy / numpy中的基本随机数由 Mersenne-Twister PRNG在numpy.random中。随机数 numpy.random中的发行版都在cython / pyrex中并且非常快。

scipy.stats没有随机数生成器,随机数是 以三种方式之一获得:

  • 直接来自numpy.random,例如normal,t,...非常快

  • 通过转换其他随机数的随机数 在numpy.random中可用,也很快,因为它可以运行 整个数字数组

  • generic:唯一的通用代随机数生成是 使用ppf(逆cdf)转换均匀随机数。 如果存在明确的表达式,则相对较快 ppf,但可以 非常 如果必须计算ppf,则会变慢 间接的影响。例如,如果只定义了pdf,那么cdf就是 通过数值积分得到的ppf是通过数值积分获得的 方程求解器。所以一些发行版很慢。


11
2017-10-23 04:18



谢谢。我正在运行MCMC例程,所以我必须迭代地绘制,所以我将使用numpy.random。 - joon


答案:


scipy.stats.uniform实际上使用了numpy,这里是stats中的相应函数(mtrand是numpy.random的别名)

class uniform_gen(rv_continuous):
    def _rvs(self):
        return mtrand.uniform(0.0,1.0,self._size)

scipy.stats有一些错误检查的开销,使界面更灵活。只要你不为每次抽奖调用uniform.rvs,速度差应该是最小的。你可以一次性获得所有随机抽取,例如(1000万)

>>> rvs = stats.uniform.rvs(size=(10000, 1000))
>>> rvs.shape
(10000, 1000)

这是我刚才写的很长的答案:

scipy / numpy中的基本随机数由 Mersenne-Twister PRNG在numpy.random中。随机数 numpy.random中的发行版都在cython / pyrex中并且非常快。

scipy.stats没有随机数生成器,随机数是 以三种方式之一获得:

  • 直接来自numpy.random,例如normal,t,...非常快

  • 通过转换其他随机数的随机数 在numpy.random中可用,也很快,因为它可以运行 整个数字数组

  • generic:唯一的通用代随机数生成是 使用ppf(逆cdf)转换均匀随机数。 如果存在明确的表达式,则相对较快 ppf,但可以 非常 如果必须计算ppf,则会变慢 间接的影响。例如,如果只定义了pdf,那么cdf就是 通过数值积分得到的ppf是通过数值积分获得的 方程求解器。所以一些发行版很慢。


11
2017-10-23 04:18



谢谢。我正在运行MCMC例程,所以我必须迭代地绘制,所以我将使用numpy.random。 - joon


我今天碰到了这个,只想在这个问题上添加一些时间细节。我看到了joon提到的内容,特别是正常分布中的随机数更快地生成了 numpy 而不是 rvs 在 scipy.stats。正如用户333700所提到的,有一些开销 rvs 但是如果你要生成一个随机值数组,那么与之相比,这个差距就会关闭 numpy。这是一个jupyter计时示例:

from scipy.stats import norm
import numpy as np

n = norm(0, 1)
%timeit -n 1000 n.rvs(1)[0]
%timeit -n 1000 np.random.normal(0,1)

%timeit -n 1000 a = n.rvs(1000)
%timeit -n 1000 a = [np.random.normal(0,1) for i in range(0, 1000)]
%timeit -n 1000 a = np.random.randn(1000)

这,在我的运行中 numpy 版本1.11.1和 scipy 0.17.0,输出:

1000 loops, best of 3: 46.8 µs per loop
1000 loops, best of 3: 492 ns per loop
1000 loops, best of 3: 115 µs per loop
1000 loops, best of 3: 343 µs per loop
1000 loops, best of 3: 61.9 µs per loop

所以只需生成一个随机样本 rvs 几乎比使用慢100倍 numpy 直。但是,如果要生成的值数组比间隙关闭(115到61.9微秒)。

如果你可以避免它,可能不要打电话 rvs 在一个循环中获得一个随机值很多次。


5
2017-10-20 16:34