numpy.random.seed(0)有什么作用?


282

np.random.seedScikit-Learn教程的以下代码在做什么?我对NumPy的随机状态生成器不太熟悉,因此我非常感谢外行对此的解释。

np.random.seed(0)
indices = np.random.permutation(len(iris_X))

Answers:


556

np.random.seed(0) 使随机数可预测

>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])
>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])

每次重置种子后,相同每次都会出现一组的数字。

如果未重置随机种子,则每次调用都会显示不同的数字:

>>> numpy.random.rand(4)
array([ 0.42,  0.65,  0.44,  0.89])
>>> numpy.random.rand(4)
array([ 0.96,  0.38,  0.79,  0.53])

(伪)随机数的工作方式是从一个数字(种子)开始,将其乘以一个大数字,加上一个偏移量,然后对该和取模。然后将所得的数字用作种子,以生成下一个“随机”数字。设置种子时(每次),每次都会执行相同的操作,并为您提供相同的编号。

如果您希望看似随机数,请不要设置种子。但是,如果您使用的代码使用要调试的随机数,则在每次运行之前设置种子可能非常有帮助,这样每次运行代码时,它们都会执行相同的操作。

要获得每次运行的最大随机数,请致电numpy.random.seed()将导致numpy将种子设置为从/dev/urandom Windows或其Windows模拟或者,如果两者均不可用,它将使用时钟。

有关使用种子生成伪随机数的更多信息,请参见Wikipedia


86
该答案应添加到numpy的文档中。谢谢。
gorjanz

8
同样,当您调用时numpy.random.seed(None),它“将尝试从/ dev / urandom(或Windows类似物)中读取数据(如果可用,否则从时钟中读取)”。
乔纳森

1
@乔纳森·优点numpy.random.seed(None)。我用该信息和文档链接更新了答案。
John1024

@ curio1729的实现可能因一个操作系统而异,但numpy试图使其命令(包括seed)兼容。
John1024 '19

1
@ L3viathan好点!为了更完整和准确,我应该提到添加了偏移量。答案已更新。对于那些想要了解更多细节的人,我还添加了一个链接到Wikipedia的伪随机数生成器讨论。
John1024

38

如果您设置np.random.seed(a_fixed_number)每次调用numpy的其他随机函数,则结果将相同:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10) 
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]

但是,如果只调用一次并使用各种随机函数,结果将仍然不同:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10)
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> print np.random.permutation(10) 
[3 5 1 2 9 8 0 6 7 4]
>>> print np.random.permutation(10) 
[2 3 8 4 5 1 0 6 9 7]
>>> print np.random.rand(4) 
[0.64817187 0.36824154 0.95715516 0.14035078]
>>> print np.random.rand(4) 
[0.87008726 0.47360805 0.80091075 0.52047748]

3
是否可以调用一次函数,以便为所有后续np.random调用设置随机种子,直到更改种子为止?每次都必须调用它似乎是不必要的冗长且容易忘记。
催眠Sl

您可以装饰@LubedUpSlug-至少在我测试过的一些简单情况下,它应该可以工作。def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrapped,然后for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))但是,从长远来看,这可能会导致非常细微的错误和奇怪的行为。(用\ 4替换\ t,并用换行符代替|)
SebastianHöffner19年

1
@SebastianHöffner感谢您的评论。我的问题有点误导,因为我对句子“但是,如果只调用一次并使用各种随机函数,结果仍然会有所不同:”感到困惑:np.random.seed()在程序启动时调用 一次总是会产生相同的结果对于同一种子,因为后续对np.random函数的调用将确定性地更改后续调用的种子。调用np.random.seed()每次调用之前np.random的功能可能会产生意想不到的结果。
催眠Sl

17

如前所述,numpy.random.seed(0)将随机种子设置为0,因此从random获得的伪随机数将从同一点开始。在某些情况下,这对于调试非常有用。但是,经过一番阅读后,如果您有线程,这似乎是错误的处理方法,因为它不是线程安全的。

来自python中的numpy随机和随机随机数之间的差异

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

如何执行此操作的示例:

from numpy.random import RandomState
prng = RandomState()
print prng.permutation(10)
prng = RandomState()
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)

可以给:

[3 0 4 6 8 2 1 9 7 5]

[1 6 9 0 2 7 8 3 5 4]

[8 1 5 0 7 2 9 4 3 6]

[8 1 5 0 7 2 9 4 3 6]

最后,请注意,由于xor的工作方式,可能在某些情况下初始化为0(与并非所有位均为0的种子相反)可能会导致一些首次迭代的分布不均匀,但这取决于算法,这超出了我目前的担忧和这个问题的范围。


12

我在神经网络中经常使用它。众所周知,当我们开始训练神经网络时,我们会随机初始化权重。在特定数据集上对这些权重训练模型。经过数个时期后,您将获得一组训练有素的权重。

现在,假设您要从头开始再次训练,或者要将模型传递给其他人来重现您的结果,权重将再次初始化为一个随机数,该数字与以前的数字大不相同。在与之前相同的时期(保持相同的数据和其他参数)之后,获得的训练权重将有所不同。问题在于您的模型不再具有可复制性,因为每次您从头训练模型时,模型都会提供不同的权重集。这是因为每次都会用不同的随机数初始化模型。

如果每次您从头开始训练时都将模型初始化为同一组随机初始化权重,该怎么办?在这种情况下,您的模型可以重现。这是通过numpy.random.seed(0)实现的。通过将seed()提到一个特定的数字,您将始终挂在同一组随机数上。


3

想象一下,您正在向某人展示如何使用一堆“随机”数字进行编码。通过使用numpy种子,他们可以使用相同的种子编号并获得相同的“随机”编号集。

因此,它不是完全随机的,因为算法会散出数字,但看起来像是随机生成的一堆。


0

随机种子指定计算机生成随机数序列时的起点。

例如,假设您要在Excel中生成一个随机数(注意:Excel为种子设置的限制为9999)。如果您在此过程中向“随机种子”框中输入数字,则可以再次使用同一组随机数。如果在框中键入“ 77”,并在下次运行随机数生成器时键入“ 77”,则Excel将显示同一组随机数。如果输入“ 99”,则会得到一组完全不同的数字。但是,如果您恢复为77的种子,那么您将获得与开始时相同的一组随机数。

例如,“取一个数字x,加900 + x,然后减去52。” 为了启动该过程,您必须指定一个起始编号x(种子)。让我们以77开始:

加900 + 77 = 977减52 = 925按照相同的算法,第二个“随机”数将是:

900 + 925 = 1825减52 = 1773这个简单的例子遵循一个模式,但是计算机数字生成背后的算法要复杂得多。


0

在所有平台/系统上,设置特定种子值后生成的所有随机数均相同。



0
numpy.random.seed(0)
numpy.random.randint(10, size=5)

这将产生以下输出: array([5, 0, 3, 3, 7]) 同样,如果我们运行相同的代码,我们将得到相同的结果。

现在,如果我们将种子值0更改为1或其他值:

numpy.random.seed(1)
numpy.random.randint(10, size=5)

这将产生以下输出:array([5 8 9 5 0])但是现在输出与上面的不一样。


0

以上所有答案均显示了 np.random.seed() in代码。我将尽力简要地解释为什么它真正发生。计算机是基于预定义算法设计的计算机。计算机的任何输出都是在输入上实现的算法的结果。因此,当我们要求计算机生成随机数时,请确保它们是随机的,但计算机并不仅仅是随机地提供它们!

因此,当我们编写np.random.seed(any_number_here)该算法时,将输出一组特定于参数的数字any_number_here。如果我们传递正确的参数,几乎就像可以获得一组特定的随机数。但是,这将要求我们了解算法的工作方式,这非常繁琐。

因此,例如,如果我写np.random.seed(10)了一组获得的特定数字,即使我在10年后执行同一行,也将保持不变,除非算法发生变化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.