Python中numpy.random和random.random之间的区别

问题:Python中numpy.random和random.random之间的区别

我在Python中有一个大脚本。我从其他人的代码中获得启发,因此最终我将该numpy.random模块用于某些方面(例如,创建从二项式分布中获取的随机数数组),而在其他地方则使用该模块random.random

有人可以告诉我两者之间的主要区别吗?在这两个文档的文档网页上,我似乎numpy.random都拥有更多的方法,但是我不清楚随机数的生成方式有何不同。

我问的原因是因为我需要为调试目的播种我的主程序。但是,除非我在要导入的所有模块中使用相同的随机数生成器,否则它将无法正常工作?

另外,我在另一篇文章中阅读了有关不使用的讨论numpy.random.seed(),但是我并不真正理解为什么这是一个糟糕的主意。如果有人向我解释为什么会这样,我将不胜感激。

I have a big script in Python. I inspired myself in other people’s code so I ended up using the numpy.random module for some things (for example for creating an array of random numbers taken from a binomial distribution) and in other places I use the module random.random.

Can someone please tell me the major differences between the two? Looking at the doc webpage for each of the two it seems to me that numpy.random just has more methods, but I am unclear about how the generation of the random numbers is different.

The reason why I am asking is because I need to seed my main program for debugging purposes. But it doesn’t work unless I use the same random number generator in all the modules that I am importing, is this correct?

Also, I read here, in another post, a discussion about NOT using numpy.random.seed(), but I didn’t really understand why this was such a bad idea. I would really appreciate if someone explain me why this is the case.


回答 0

您已经做出了许多正确的观察!

除非您希望为两个随机生成器都作为种子,否则从长远来看选择一个或另一个生成器可能更简单。但是,如果您确实需要同时使用两者,那么是的,您还需要同时对两者进行播种,因为它们彼此独立地生成随机数。

对于numpy.random.seed(),主要的困难是它不是线程安全的-也就是说,如果您有许多不同的执行线程,则使用它是不安全的,因为如果两个不同的线程同时执行该函数,则不能保证它能正常工作。如果您不使用线程,并且可以合理地期望将来不需要以这种方式重写程序,那numpy.random.seed()应该很好。如果有任何理由怀疑您将来可能需要线程,那么从长远来看,按照建议进行操作并创建numpy.random.Random该类的本地实例会更加安全。据我所知,它random.random.seed()是线程安全的(或者至少没有找到相反的证据)。

numpy.random库包含一些科学研究中常用的额外概率分布,以及用于生成随机数据数组的几个便捷函数。该random.random库要轻巧一些,如果您不从事科学研究或其他统计工作,那应该很好。

否则,它们都使用Mersenne扭曲序列生成它们的随机数,并且它们都是完全确定性的-也就是说,如果您知道一些关键信息,则可以绝对确定地预测下一个数字。因此,numpy.random和random.random都不适合任何严重的加密用途。但是因为序列非常长,所以在您不必担心有人试图对数据进行反向工程的情况下,两者都适合生成随机数。这也是必须播种随机值的原因-如果每次都从同一位置开始,那么您将始终获得相同的随机数序列!

附带说明一下,如果您确实需要加密级别的随机性,则应该使用secrets模块,或者如果使用的是Python 3.6之前的Python版本,则应使用Crypto.Random之类的东西。

You have made many correct observations already!

Unless you’d like to seed both of the random generators, it’s probably simpler in the long run to choose one generator or the other. But if you do need to use both, then yes, you’ll also need to seed them both, because they generate random numbers independently of each other.

For numpy.random.seed(), the main difficulty is that it is not thread-safe – that is, it’s not safe to use if you have many different threads of execution, because it’s not guaranteed to work if two different threads are executing the function at the same time. If you’re not using threads, and if you can reasonably expect that you won’t need to rewrite your program this way in the future, numpy.random.seed() should be fine. If there’s any reason to suspect that you may need threads in the future, it’s much safer in the long run to do as suggested, and to make a local instance of the numpy.random.Random class. As far as I can tell, random.random.seed() is thread-safe (or at least, I haven’t found any evidence to the contrary).

The numpy.random library contains a few extra probability distributions commonly used in scientific research, as well as a couple of convenience functions for generating arrays of random data. The random.random library is a little more lightweight, and should be fine if you’re not doing scientific research or other kinds of work in statistics.

Otherwise, they both use the Mersenne twister sequence to generate their random numbers, and they’re both completely deterministic – that is, if you know a few key bits of information, it’s possible to predict with absolute certainty what number will come next. For this reason, neither numpy.random nor random.random is suitable for any serious cryptographic uses. But because the sequence is so very very long, both are fine for generating random numbers in cases where you aren’t worried about people trying to reverse-engineer your data. This is also the reason for the necessity to seed the random value – if you start in the same place each time, you’ll always get the same sequence of random numbers!

As a side note, if you do need cryptographic level randomness, you should use the secrets module, or something like Crypto.Random if you’re using a Python version earlier than Python 3.6.


回答 1

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

From Python for Data Analysis, the module numpy.random supplements the Python random with functions for efficiently generating whole arrays of sample values from many kinds of probability distributions.

By contrast, Python’s built-in random module only samples one value at a time, while numpy.random can generate very large sample faster. Using IPython magic function %timeit one can see which module performs faster:

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

回答 2

种子的来源和使用的分发配置文件将影响输出-如果您正在寻找加密随机性,则os.urandom()的种子将从设备颤动(即以太网或磁盘)中获得几乎真实的随机字节(即/ BSD上的dev / random)

这样可以避免您提供种子,从而避免生成确定的随机数。但是,随机调用然后允许您将数字拟合为一个分布(我称之为科学随机性-最终,您想要的只是一个随机数的钟形曲线分布,numpy最擅长于解决这个问题。

所以,是的,坚持使用一个生成器,但要确定您想要的随机数-随机,但是会偏离分布曲线,或者在没有量子设备的情况下尽可能地随机。

The source of the seed and the distribution profile used are going to affect the outputs – if you are looking for cryptgraphic randomness, seeding from os.urandom() will get nearly real random bytes from device chatter (ie ethernet or disk) (ie /dev/random on BSD)

this will avoid you giving a seed and so generating determinisitic random numbers. However the random calls then allow you to fit the numbers to a distribution (what I call scientific random ness – eventually all you want is a bell curve distribution of random numbers, numpy is best at delviering this.

SO yes, stick with one generator, but decide what random you want – random, but defitniely from a distrubtuion curve, or as random as you can get without a quantum device.