下面的代码导入NumPy并设置种子。
import numpy as np
np.random.seed(42)
然而,我对播下种子不感兴趣,更感兴趣的是阅读它。random.get_state()
似乎不包含种子。documentation没有显示出明显的答案。
假设我没有手动设置,如何检索numpy.random
使用的当前种子?
我想使用当前的种子来继续流程的下一次迭代。
下面的代码导入NumPy并设置种子。
import numpy as np
np.random.seed(42)
然而,我对播下种子不感兴趣,更感兴趣的是阅读它。random.get_state()
似乎不包含种子。documentation没有显示出明显的答案。
假设我没有手动设置,如何检索numpy.random
使用的当前种子?
我想使用当前的种子来继续流程的下一次迭代。
6条答案
按热度按时间u5rb5r591#
简短的答案是,你根本不能(至少总体上不能)。
NumPy使用的Mersenne TwisterRNG有219937-1个可能的内部状态,而单个64位整数只有264个可能的值。因此,不可能将每个RNG状态Map到唯一的整数种子。
您可以使用
np.random.get_state
和np.random.set_state
直接获取和设置RNG的内部状态。get_state
的输出是一个元组,其第二个元素是由32位整数组成的(624,)
数组。这个数组有足够多的位来表示RNG的每个可能的内部状态(2624x32>219937-1)。get_state
返回的元组可以像种子一样使用,以创建可重现的随机数序列。例如:x3naxklr2#
以下是我的调查结果:
1.使用
np.random.seed(X)
设置随机种子后,可以使用np.random.get_state()[1][0]
重新查找。1.然而,它对你没有什么用处。
以下代码部分的输出将向您说明为什么这两个语句都是正确的。
语句1-可以使用
np.random.get_state()[1][0]
找到随机种子。如果使用
np.random.seed(123)
设置随机种子,则可以使用state = np.random.get_state()
将随机状态作为元组检索。下面是state
的详细介绍(我在Spyder中使用变量EXPLORER)。我使用屏幕截图,因为使用print(state)
会淹没您的控制台,因为元组的第二个元素中的数组太大。可以很容易地看到
123
是包含在第二个元素中的数组中的第一个数字。而使用seed = np.random.get_state()[1][0]
将得到123
。完美?不完全是,因为:声明2--但是,它对您没有什么用处:
乍一看可能并非如此,因为您可以使用
np.random.seed(123)
,使用seed = np.random.get_state()[1][0]
检索相同的数字,使用np.random.seed(444)
重置种子,然后(似乎)使用np.random.seed(seed)
将其设置回123
场景。但那时你已经知道你的随机种子是什么了,所以你就不需要这样做了。下一个代码部分还将显示,您不能使用np.random.get_state()[1][0]
获取任意随机状态的第一个数字,并期望重新创建该场景。请注意,您很可能必须完全关闭并重新启动内核(或调用np.random.seed(None)
)才能看到这一点。以下代码片段使用
np.random.randint()
生成5个介于-10和10之间的随机整数,并存储有关该进程的一些信息:请注意,名为
seedState
的列与state
下的第一个数字相同。我本可以把它作为一个独立的数字打印出来,但我想把它都放在同一个地方。另请注意,到目前为止,seedSet = 123
和np.random.seed(seedSet)
已被注解掉。因为没有设置随机的种子,所以你的数字将与我的不同。但这在这里并不重要,重要的是你的结果的内在一致性:在这种情况下,
seed = np.random.get_state()[1][0]
等于1558056443
。按照董贾斯丁回答的逻辑(以及我在这次编辑之前的回答),您可以用np.random.seed(1558056443)
设置随机种子,并获得相同的随机状态。下一个片段将显示您不能:片段2
看到区别了吗?输出1和输出2的
np.random.get_state()[1][0]
相同,但输出的其余部分不同(最重要的是,随机数不相同)。因此,正如阿里已经明确表示的那样:因此,不可能将每个RNG状态Map到唯一的整数种子。
csbfibhn3#
检查
np.random.get_state()
返回的数组的第一个元素,在我看来它就是随机种子。sulc1iza4#
这一回答补充了其他人忽略的重要细节。首先,重新表述一下结论:
原始随机种子(通过
np.random.seed
设置)在生成数字后无法取回,但中间体(当前状态)可以取回。请参考@Vestland的答案;然而,它可能会误导:生成的数字不同并不是因为无法Map状态,而是因为使用了不完整的编码:
get_state()[1]
。完整的表示包括pos = get_state()[2]
。要说明以下情况:我们生成了一个数字,但
get_state()[1]
保持不变。但是:对于
state1
和rand1
也是如此。因此,@Vestland的数字不同,因为当不设置种子时,pos = 623
-而如果我们使用np.random.seed
,pos = 624
。为什么会有这样不方便的差异呢?毫无头绪。在
np.random.seed(s)
上总结如下:get_state()[1][0]
设置后立即:检索准确重新创建状态的s
get_state()[1][0]
:可能检索也可能不检索s
,但它将不重新创建当前状态(在get_state()
)get_state()[1][0]
:不会检索s
。这是因为pos
用尽了它的表示。get_state()
at any point:将准确地重新创建该点。最后,行为也可能因
get_state()[3:]
(当然还有[0]
)而不同。zwghvu4y5#
虽然最上面的答案大体上是正确的,因为这在总体上是不可能的,但实际上它是可能的。我会将你重定向到这个人的博客:https://kamila.akagi.moe/posts/mersenne-twister/
这个人开发了一种Mersenne Twister破解算法来恢复初始种子,并提供了详细的细节和算法。我不是作者,我不了解这些材料的全部内容,但任何有兴趣做这件事的人都应该检查一下。
nr9pn0ug6#
了解随机种子的一个简单解决方案是随机生成一个种子,然后对随机数生成器进行种子生成。类似于以下内容: