以下导入 NumPy 并设置种子。
import numpy as np
np.random.seed(42)
但是,我对设置种子不感兴趣,而对阅读它更感兴趣。random.get_state()
似乎没有种子。该文档没有显示明显的答案。
numpy.random
假设我没有手动设置它,我如何检索 使用的当前种子?
我想使用当前的种子来延续流程的下一次迭代。
以下导入 NumPy 并设置种子。
import numpy as np
np.random.seed(42)
但是,我对设置种子不感兴趣,而对阅读它更感兴趣。random.get_state()
似乎没有种子。该文档没有显示明显的答案。
numpy.random
假设我没有手动设置它,我如何检索 使用的当前种子?
我想使用当前的种子来延续流程的下一次迭代。
简短的回答是你根本不能(至少一般来说不能)。
numpy 使用的Mersenne Twister RNG 有 2 19937 -1 个可能的内部状态,而单个 64 位整数只有 2 64 个可能值。因此,不可能将每个 RNG 状态映射到唯一的整数种子。
您可以np.random.get_state
使用和直接获取和设置 RNG 的内部状态np.random.set_state
。的输出get_state
是一个元组,其第二个元素是一个(624,)
32 位整数数组。这个数组有足够多的位来表示 RNG 的每个可能的内部状态 (2 624 * 32 > 2 19937 -1)。
get_state
可以像种子一样使用返回的元组,以创建可重现的随机数序列。例如:
import numpy as np
# randomly initialize the RNG from some platform-dependent source of entropy
np.random.seed(None)
# get the initial state of the RNG
st0 = np.random.get_state()
# draw some random numbers
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26 3 1 68 21]
# set the state back to what it was originally
np.random.set_state(st0)
# draw again
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26 3 1 68 21]
此贡献旨在澄清 ali_m 的正确答案,并作为对 Dong Justin 建议的重要更正。
这些是我的发现:
np.random.seed(X)
您可以使用 再次找到它np.random.get_state()[1][0]
。以下代码部分的输出将向您展示为什么这两个语句都是正确的。
声明 1 - 您可以使用np.random.get_state()[1][0]
.
如果使用 设置随机种子np.random.seed(123)
,则可以使用 将随机状态作为元组检索state = np.random.get_state()
。下面是仔细看看state
(我在 Spyder 中使用变量资源管理器)。我正在使用屏幕截图,因为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)
,然后(似乎)123
用 将其设置回场景np.random.seed(seed)
。但是你之前已经知道你的随机种子是什么,所以你不需要那样做。下一个代码部分还将显示您不能使用任何随机状态的第一个数字np.random.get_state()[1][0]
并期望重新创建该确切场景。请注意,您很可能必须完全关闭并重新启动内核(或调用np.random.seed(None)
)才能看到这一点。
下面的代码片段用于np.random.randint()
生成 5 个介于 -10 和 10 之间的随机整数,以及存储有关进程的一些信息:
片段 1
# 1. Imports
import pandas as pd
import numpy as np
# 2. set random seed
#seedSet = None
seedSet = 123
np.random.seed(seedSet)
# 3. describe random state
state = np.random.get_state()
state5 = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]
# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)
# 5. organize and present findings
df = pd.DataFrame.from_dict({'seedSet':seedSet, 'seedState':seedState, 'state':state, 'random':random})
print(df)
请注意,名为的列seedState
与 下的第一个数字相同state
。我本可以将其打印为独立编号,但我想将其全部保存在同一个地方。另请注意,seedSet = 123
和np.random.seed(seedSet)
到目前为止已被注释掉。而且因为没有设置随机种子,所以你的数字与我的不同。但这不是这里重要的,而是您的结果的内部一致性:
输出 1:
random seedSet seedState state
0 2 None 1558056443 1558056443
1 -1 None 1558056443 1808451632
2 4 None 1558056443 730968006
3 -4 None 1558056443 3568749506
4 -6 None 1558056443 3809593045
在这种特殊情况下seed = np.random.get_state()[1][0]
等于1558056443
。并按照董贾斯汀回答的逻辑(以及我在此编辑之前的回答),您可以设置随机种子np.random.seed(1558056443)
并获得相同的随机状态。下一个片段将显示您不能:
片段 2
# 1. Imports
import pandas as pd
import numpy as np
# 2. set random seed
#seedSet = None
seedSet = 1558056443
np.random.seed(seedSet)
# 3. describe random state
#state = np.random.get_state()
state = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]
# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)
# 5. organize and present findings
df = pd.DataFrame.from_dict({'seedSet':seedSet, 'seedState':seedState, 'state':state, 'random':random})
print(df)
输出 2:
random seedSet seedState state
0 8 1558056443 1558056443 1558056443
1 3 1558056443 1558056443 1391218083
2 7 1558056443 1558056443 2754892524
3 -8 1558056443 1558056443 1971852777
4 4 1558056443 1558056443 2881604748
看到不同?np.random.get_state()[1][0]
输出 1 和输出 2 相同,但输出的其余部分不同(最重要的是随机数不相同)。因此,正如 ali_m 已经明确指出的那样:
因此,不可能将每个 RNG 状态映射到唯一的整数种子。
这个答案补充了其他人错过的重要细节。首先,重新表述结论:
np.random.seed
生成数字后无法检索原始随机种子(通过 设置),但中间体(当前状态)可以。
请参阅@vestland 的回答;然而,它可能会产生误导:生成的数字不同不是因为无法映射状态,而是使用了不完整的编码:get_state()[1]
. 完整的表示包括pos = get_state()[2]
. 为了显示:
import numpy as np
state0 = np.random.get_state()
rand0 = np.random.randint(0, 10, 1)
state1 = np.random.get_state()
rand1 = np.random.randint(0, 10, 1)
assert all(s0 == s1 for s0, s1 in zip(state0[1], state1[1]))
我们生成了一个数字,但get_state()[1]
仍然保持不变。然而:
np.random.set_state(state0)
assert np.random.randint(0, 10, 1) == rand0
同样对于state1
& rand1
。因此,@vestland 的数字不同,因为在不设置种子时,pos = 623
- 而如果我们使用np.random.seed
, pos = 624
。为什么不方便的差异?没有线索。
总结np.random.seed(s)
:
get_state()[1][0]
设置后立即:检索s
完全重新创建状态的get_state()[1][0]
生成数字后:可能会或可能不会检索s
,但不会重新创建当前状态(at get_state()
)get_state()[1][0]
生成许多数字后:不会检索s
. 这是因为pos
用尽了它的代表性。get_state()
在任何时候:将完全重新创建该点。最后,行为也可能因get_state()[3:]
(当然[0]
)而有所不同。
检查由返回的数组的第一个元素,np.random.get_state()
对我来说似乎正是随机种子。
虽然最佳答案所说的通常是正确的,但一般来说这是不可能的,实际上是可能的。我会将您重定向到此人的博客:https ://kamila.akagi.moe/posts/mersenne-twister/
此人开发了一种梅森捻线机破解算法来恢复初始种子,并提供了完整的细节和算法。我不是作者,也不完全理解材料是什么,但是任何有兴趣这样做的人都应该检查一下。