Python中numpy.random和random.random的区别
我有一个比较大的Python脚本。在写这个脚本的时候,我参考了其他人的代码,所以我在某些地方用了numpy.random
模块(比如用它来创建一个从二项分布中随机生成的数字数组),而在其他地方则用了random.random
模块。
有人能告诉我这两个模块之间的主要区别吗?我看了它们各自的文档网页,感觉numpy.random
的功能更多,但我不太明白它们生成随机数的方式有什么不同。
我之所以问这个问题,是因为我需要为我的主程序设置种子,以便进行调试。但是,除非我在所有导入的模块中使用相同的随机数生成器,否则它就无法正常工作,这样理解对吗?
另外,我在其他帖子里看到有人讨论不要使用numpy.random.seed()
,但我不太明白为什么这样做不好。如果有人能解释一下原因,我会非常感激。
4 个回答
来自《Python数据分析》,模块numpy.random
是对Python内置的random
模块的补充,它提供了一些功能,可以高效地从多种概率分布中生成一整组样本值。
相比之下,Python自带的random
模块一次只能生成一个值,而numpy.random
可以更快地生成非常大的样本。通过使用IPython的魔法命令%timeit
,我们可以看到哪个模块的速度更快:
In [1]: from random import normalvariate
In [2]: N = 1000000
In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop
In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop
你已经观察到很多正确的地方了!
除非你想同时使用两个随机数生成器,否则长远来看选择一个生成器会更简单。不过如果你确实需要用到两个,那你就得给它们都设置种子,因为它们是独立生成随机数的。
对于 numpy.random.seed()
,主要的问题是它不支持多线程安全使用。也就是说,如果你有很多不同的执行线程,同时在运行这个函数,就不一定能保证它正常工作。如果你不使用线程,并且可以合理地预期将来不会以这种方式重写你的程序,那么 numpy.random.seed()
是可以的。如果你有任何理由怀疑将来可能需要使用线程,长远来看,按照建议做,创建一个 numpy.random.Random
类的本地实例会更安全。根据我所了解,random.seed()
是线程安全的(或者至少我没有找到相反的证据)。
numpy.random
库包含了一些在科学研究中常用的额外概率分布,以及一些生成随机数据数组的便利函数。如果你不做科学研究或其他统计工作,random.random
库会更轻量,使用起来也没问题。
除此之外,它们都使用 梅森旋转算法 来生成随机数,并且它们都是完全确定性的,也就是说,如果你知道一些关键的信息,就可以绝对确定地预测 下一个会出现什么数字。因此,numpy.random
和 random.random
都不适合用于任何 严肃的加密用途。不过,由于这个序列非常非常长,它们在你不担心别人试图破解你的数据的情况下生成随机数是没问题的。这也是为什么需要设置随机值种子的原因——如果每次都从同一个地方开始,你就总会得到相同的随机数序列!
顺便提一下,如果你确实需要加密级别的随机性,应该使用 secrets 模块,或者如果你使用的是 Python 3.6 之前的版本,可以使用 Crypto.Random。