numpy.random.seed(0) 做啥?
Posted
技术标签:
【中文标题】numpy.random.seed(0) 做啥?【英文标题】:What does numpy.random.seed(0) do?numpy.random.seed(0) 做什么? 【发布时间】:2014-02-24 23:58:22 【问题描述】:np.random.seed
在以下来自 Scikit-Learn 教程的代码中做了什么?我对 NumPy 的随机状态生成器的东西不是很熟悉,所以我非常感谢外行的术语解释。
np.random.seed(0)
indices = np.random.permutation(len(iris_X))
【问题讨论】:
我发现这篇文章对理解np.random.seed()
和伪随机数很有帮助:sharpsightlabs.com/blog/numpy-random-seed
这仍然是推荐的答案吗? towardsdatascience.com/…
【参考方案1】:
我希望给出一个非常简短的答案:
seed
使(下一个系列)随机数可预测。你可以想,每次调用seed
后,它会预先定义序列号,numpy random 会保留它的迭代器,然后每次你得到一个随机数它就会调用get next。
例如:
np.random.seed(2)
np.random.randn(2) # array([-0.41675785, -0.05626683])
np.random.randn(1) # array([-1.24528809])
np.random.seed(2)
np.random.randn(1) # array([-0.41675785])
np.random.randn(2) # array([-0.05626683, -1.24528809])
您可以注意到,当我设置相同的种子时,无论您每次向 numpy 请求多少个随机数,它总是给出相同的数字序列,在本例中为 array([-0.41675785, -0.05626683, -1.24528809])
。
【讨论】:
【参考方案2】:以上所有答案都显示了np.random.seed()
在代码中的实现。我会尽力简要解释它为什么会发生。计算机是基于预定义算法设计的机器。计算机的任何输出都是在输入上实施的算法的结果。因此,当我们要求计算机生成随机数时,请确保它们是随机的,但计算机并不是随机产生的!
因此,当我们编写 np.random.seed(any_number_here)
时,算法将输出一组特定的数字,这些数字对参数 any_number_here
是唯一的。如果我们传递正确的参数,这几乎就像可以获得一组特定的随机数。但这需要我们知道算法是如何工作的,这非常乏味。
因此,例如,如果我写 np.random.seed(10)
,即使我在 10 年后执行同一行,我获得的特定数字集也将保持不变,除非算法发生变化。
【讨论】:
【参考方案3】: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])
,但现在的输出与上面不同。
【讨论】:
【参考方案4】:Numpy 文档中有一个很好的解释: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.RandomState.html 它指的是Mersenne Twister 伪随机数生成器。关于算法的更多细节在这里:https://en.wikipedia.org/wiki/Mersenne_Twister
【讨论】:
【参考方案5】: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()
。 This 将导致 numpy 将种子设置为从 /dev/urandom
或其 Windows 模拟获得的随机数,或者,如果两者都不可用,它将使用时钟。
有关使用种子生成伪随机数的更多信息,请参阅wikipedia。
【讨论】:
这个答案应该添加到numpy的文档中。谢谢。 另外,当您调用numpy.random.seed(None)
时,它“将尝试从 /dev/urandom(或 Windows 模拟)中读取数据(如果可用)或从时钟中读取数据”。
@Jonathan 关于numpy.random.seed(None)
的精彩之处。我用该信息和文档链接更新了答案。
@L3viathan 好点!为了更完整和准确,我应该提到添加了一个偏移量。答案已更新。对于那些想了解更多细节的人,我还添加了一个链接到***关于伪随机数生成器的讨论。【参考方案6】:
假设您正在向某人展示如何用一堆“随机”数字编写代码。通过使用 numpy 种子,他们可以使用相同的种子数并获得相同的“随机”数集。
所以它不是完全随机的,因为算法会吐出数字,但它看起来像是随机生成的一堆。
【讨论】:
【参考方案7】:我在神经网络中经常使用它。众所周知,当我们开始训练神经网络时,我们会随机初始化权重。该模型在特定数据集上的这些权重上进行训练。在经过数个时期后,您将获得训练有素的权重集。
现在假设您想再次从头开始训练,或者您想将模型传递给其他人以重现您的结果,权重将再次初始化为一个随机数,该随机数大部分与之前的不同。在与之前的相同数量的时期(保持相同的数据和其他参数)之后获得的训练权重会有所不同。问题是您的模型不再具有可重复性,即每次您从头开始训练模型时,它都会为您提供不同的权重集。这是因为模型每次都被不同的随机数初始化。
如果每次您从头开始训练时,模型都被初始化为相同的随机初始化权重集怎么办?在这种情况下,您的模型可能会变得可重现。这是通过 numpy.random.seed(0) 实现的。通过将 seed() 提到一个特定的数字,你总是挂在同一组随机数上。
【讨论】:
【参考方案8】:设置特定种子值后生成的所有随机数在所有平台/系统中都是相同的。
【讨论】:
【参考方案9】:如果每次调用numpy的其他随机函数时都设置np.random.seed(a_fixed_number)
,结果都是一样的:
>>> 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]
【讨论】:
是否有一个函数可以调用一次,以便为所有后续np.random
调用设置随机种子,直到种子被更改?每次都必须调用它似乎不必要地冗长且容易忘记。
@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)))
但是,从长远来看,这可能会导致非常微妙的错误和奇怪的行为。 (将 \t 替换为四个空格,将 | 替换为换行符...)
@SebastianHöffner 感谢您的评论。我的问题有点误导,因为我被这句话弄糊涂了“但是,如果你只调用一次并使用各种随机函数,结果仍然会有所不同:”在程序开始时调用一次np.random.seed()
总是会产生相同种子的结果相同,因为随后对 np.random
函数的调用将确定性地更改后续调用的种子。在每次调用 np.random
函数之前调用 np.random.seed()
可能会产生不希望的结果。
这仍然是推荐的答案吗? towardsdatascience.com/…【参考方案10】:
随机种子指定计算机生成随机数序列时的起点。
例如,假设您想在 Excel 中生成一个随机数(注意:Excel 为种子设置了 9999 的限制)。如果您在此过程中在随机种子框中输入一个数字,您将能够再次使用同一组随机数。如果您在框中键入“77”,并在下次运行随机数生成器时键入“77”,Excel 将显示同一组随机数。如果你输入“99”,你会得到一组完全不同的数字。但是,如果您恢复到种子 77,那么您将获得与开始时相同的一组随机数。
例如,“取一个数字 x,加上 900 +x,然后减去 52。”为了启动该过程,您必须指定一个起始编号 x(种子)。让我们以起始数字 77 为例:
加 900 + 77 = 977 减去 52 = 925 按照相同的算法,第二个“随机”数将是:
900 + 925 = 1825 减去 52 = 1773 这个简单的例子遵循一个模式,但计算机数字生成背后的算法要复杂得多
【讨论】:
【参考方案11】:如前所述,numpy.random.seed(0) 将随机种子设置为 0,因此您从 random 获得的伪随机数将从同一点开始。在某些情况下,这可能有利于调试。但是,经过一番阅读,如果您有线程,这似乎是错误的方法,因为它不是线程安全的。
来自differences-between-numpy-random-and-random-random-in-python:
对于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 的种子相反)可能会导致一些第一次迭代的分布不均匀,但这取决于关于算法,超出了我目前的担忧和这个问题的范围。
【讨论】:
这仍然是推荐的答案吗? towardsdatascience.com/…以上是关于numpy.random.seed(0) 做啥?的主要内容,如果未能解决你的问题,请参考以下文章