如何检索NumPy随机数生成器的当前种子?

Mas*_*ast 48 python random numpy mersenne-twister random-seed

以下导入NumPy并设置种子.

import numpy as np
np.random.seed(42)
Run Code Online (Sandbox Code Playgroud)

但是,我对设置种子不感兴趣,而是更多地阅读它.random.get_state()似乎没有包含种子.该文件并没有表现出明显的答案.

我如何检索当前使用的种子numpy.random,假设我没有手动设置它?

我想使用当前种子来继承下一个进程的迭代.

ali*_*i_m 63

简短的回答是你根本不能(至少不是一般).

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]
Run Code Online (Sandbox Code Playgroud)

  • 为什么你说你不能"简短的回答是你根本不能(至少在一般情况下不是这样)."在我看来,你可以从我读到你的答案.我糊涂了. (9认同)
  • 看,我对辩论"种子"的定义并不特别感兴趣.只要您乐意将`get_state`的输出称为"种子",那么我的答案中显示的代码将适合您.我将OP的问题解释为*"`np.random.seed`的反函数是什么函数?***,由于我上面讨论的原因,这是不可能的. (9认同)
  • 我没有辩论,我在辩论中并不感兴趣.我真的试图确保我理解你的答案,并且以后没有一个奇怪的意外警告.据我所知,它的确有效,你的回答对我来说更有意义,这一切都很好(因此我的upvote;)).谢谢 :) (4认同)
  • 我不知道是否有任何地方有严格的定义,种子在任何情况下都需要.如果元组或任何其他结构使您返回到您想要的相同随机状态,那么不是种子吗?我不知道种子**有**是一个整数.但你的答案似乎有效,或者除了你提到的整数表示之外还有一个警告吗? (2认同)
  • @bukzor 这是一个有争议的问题,因为“RandomState”的“seed”参数是 [required](https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/mtrand.pyx#L680)是介于 0 和 2**32-1 之间的整数,或此类整数的数组。原则上,您可以通过在本机 Python 整数中解包位来生成 uint32 数组,但这不是 `RandomState` 本身支持的内容。 (2认同)

ves*_*and 12

在我找到有关手头问题的更多细节之后,我已经大量编辑了这个答案.就目前情况而言,我希望它能够很好地澄清来自ali_m的答案,并作为对Dong Justin答案的重要修正.

这些是我的发现:

  1. 使用随机种子设置后,np.random.seed(X)可以再次使用np.random.get_state()[1][0].
  2. 但是,它对你没用.

以下代码部分的输出将显示两个语句为何正确的原因.


声明1 - 您可以使用随机种子找到np.random.get_state()[1][0].

如果使用随机种子设置np.random.seed(123),则可以使用随机状态检索随机状态state = np.random.get_state().下面仔细看看state(我在Spyder中使用Variable 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),然后(貌似)将其设置回123场景123.但是之后你已经知道你的随机种子什么了,所以你不需要这样做.下一个代码部分还将显示您无法使用任何随机状态的第一个数字np.random.seed(seed)并期望重新创建该确切方案.请注意,您很可能必须关闭并重新启动你的内核完全(或致电np.random.get_state()[1][0]为了能够看到这一点).

以下代码段用于np.random.seed(None)生成-10到10之间的5个随机整数,以及存储有关该过程的一些信息:

片段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)
Run Code Online (Sandbox Code Playgroud)

请注意,名称列np.random.randint()与下面的第一个数字相同seedState.我可以把它打印成一个独立的号码,但我想把它们全部保存在同一个地方.还要注意的是,stateseedSet = 123至今都被注释掉.因为没有设置随机种子,你的数字将与我的不同.但这不是重要的,而是结果的内在一致性:

输出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
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下np.random.seed(seedSet)等于seed = np.random.get_state()[1][0].按照Dong Justins的回答(在编辑之前作为我自己的答案),您可以设置随机种子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)
Run Code Online (Sandbox Code Playgroud)

输出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
Run Code Online (Sandbox Code Playgroud)

看到不同?np.random.seed(1558056443)对于输出1和输出2是相同的,但输出的其余部分不相同(最重要的是随机数不相同).所以,由于ali_m已经明确说明:

因此,不可能将每个RNG状态映射到唯一的整数种子.

  • TL;DR 中间随机状态无法恢复(例如生成 5 个数字之后的状态)。写得不错。 (2认同)

Jér*_*Roy 5

了解随机种子的一个简单解决方案是随机生成一个随机种子,然后为随机数生成器提供种子。像下面这样:

import numpy as np
seed = int(np.random.rand() * (2**32 - 1))
np.random.seed(seed)
Run Code Online (Sandbox Code Playgroud)