Python中numpy.random和random.random的区别
Posted
技术标签:
【中文标题】Python中numpy.random和random.random的区别【英文标题】:Differences between numpy.random and random.random in Python 【发布时间】:2011-10-25 04:36:12 【问题描述】:我有一个很大的 Python 脚本。我在其他人的代码中启发了自己,所以我最终在某些事情上使用了 numpy.random
模块(例如,用于创建从二项分布中获取的随机数数组),而在其他地方我使用了模块 random.random
。
谁能告诉我两者之间的主要区别?
查看两者的文档网页,在我看来numpy.random
只是有更多方法,但我不清楚随机数的生成有何不同。
我问的原因是因为我需要为我的主程序播种以进行调试。但是除非我在我正在导入的所有模块中使用相同的随机数生成器,否则它不起作用,这是正确的吗?
另外,我在另一篇文章中读到了关于不使用numpy.random.seed()
的讨论,但我真的不明白为什么这是个坏主意。如果有人向我解释为什么会这样,我将不胜感激。
【问题讨论】:
【参考方案1】:你已经做了很多正确的观察!
除非您想为两个随机生成器播种,否则从长远来看,选择一个或另一个生成器可能更简单。但是,如果您确实需要同时使用两者,那么是的,您还需要为它们提供种子,因为它们会相互独立地生成随机数。
对于numpy.random.seed()
,主要困难在于它不是线程安全的——也就是说,如果你有many different threads of execution,使用它是不安全的,因为如果两个不同的线程在同时。如果您不使用线程,并且您可以合理地预期将来不需要以这种方式重写程序,numpy.random.seed()
应该没问题。如果有任何理由怀疑您将来可能需要线程,从长远来看,按照建议和make a local instance of the numpy.random.Random
class 做会更安全。据我所知,random.random.seed()
是线程安全的(或者至少,我没有发现任何相反的证据)。
numpy.random
库包含一些在科学研究中常用的额外概率分布,以及一些用于生成随机数据数组的便利函数。 random.random
库更轻量级,如果您不从事科学研究或其他类型的统计工作,应该没问题。
否则,它们都使用Mersenne twister sequence 来生成随机数,而且它们都是完全确定的——也就是说,如果您知道一些关键信息,就可以绝对确定地预测what number will come next。出于这个原因,numpy.random 和 random.random 都不适合任何serious cryptographic uses。但是因为这个序列非常长,所以在你不担心人们试图对你的数据进行逆向工程的情况下,两者都可以生成随机数。这也是为什么需要播种随机值的原因——如果你每次都从同一个地方开始,你总是会得到相同的随机数序列!
附带说明,如果您确实需要加密级别的随机性,则应使用secrets 模块,如果您使用的是早于 Python 3.6 的 Python 版本,则应使用 Crypto.Random 之类的模块.
【讨论】:
作为一个遥远相关的注释,有时需要使用 nother,因为 Mersenne twister 不会产生足以用于加密(以及一些不寻常的科学)目的的随机熵序列。在这些罕见的情况下,您通常需要Crypto.Random,它能够使用操作系统特定的熵源来生成质量比单独的random.random
更高质量的非确定性随机序列。不过,您通常不需要这个。
谢谢汉妮尔。你的见解真的很有用!事实证明,我不能只使用一个随机数生成器(它需要是 numpy,因为 random 不会产生二项式分布),因为我的程序的一部分调用了另一个使用随机数的程序。我将不得不播种两个生成器。
“如果你知道你现在有哪个号码,就可以绝对确定地预测接下来会出现什么号码。”我认为这个声明可能需要一些澄清。这意味着如果您知道生成器的内部状态,您就可以重现该序列——这就是您在为生成器播种时所做的事情。给定生成器的单个数字输出,您无法预测下一个数字。周期是如此之大,您可能需要一长串数字才能计算出您在伪随机序列上的位置,从而预测下一个。【参考方案2】:
来自Python for Data Analysis,模块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
【讨论】:
其他方法不是这样。将np.random.randint(2)
与random.randrange(2)
进行比较,NumPy 较慢一个。 NumPy:1.25 us,随机:891 ns。 np.random.rand()
和 random.random()
的关系也相同。【参考方案3】:
种子的来源和使用的分布配置文件将影响输出 - 如果您正在寻找加密随机性,从 os.urandom() 播种将从设备抖动(即以太网或磁盘)中获得几乎真实的随机字节(即 BSD 上的 /dev/random)
这将避免您提供种子并因此生成确定性随机数。然而,随机调用然后允许您将数字拟合到分布(我称之为科学随机性 - 最终您想要的只是随机数的钟形曲线分布,numpy 最擅长于此。
所以是的,坚持使用一个生成器,但要决定你想要什么随机 - 随机,但明确地来自分布曲线,或者在没有量子设备的情况下尽可能随机。
【讨论】:
非常感谢保罗,您的回答真的很有用!我不是在寻找密码随机性,我在做数学建模,伪随机数对我来说就足够了。事实证明,我不能按照自己的意愿坚持使用一个生成器,因为我需要 numpy 来进行二项式分布,并且我的程序调用了另一个使用随机的程序:(【参考方案4】:令我惊讶的是randint(a, b)
方法在numpy.random
和random
中都存在,但它们的上限行为不同。
random.randint(a, b)
返回一个随机整数 N,使得a <= N <= b
。 randrange(a, b+1)
的别名。它包含b
。 random documentation
但是,如果您调用numpy.random.randint(a, b)
,它将返回低(包括)到高(不包括)。 Numpy documentation
【讨论】:
以上是关于Python中numpy.random和random.random的区别的主要内容,如果未能解决你的问题,请参考以下文章