random.seed(): 它是用来做什么的?

225

我有点困惑 random.seed() 在 Python 中是做什么的。例如,下面的测试为什么会产生这样的结果(且结果一致)?

>>> import random
>>> random.seed(9001)
>>> random.randint(1, 10)
1
>>> random.randint(1, 10)
3
>>> random.randint(1, 10)
6
>>> random.randint(1, 10)
6
>>> random.randint(1, 10)
7

我找不到好的文档。


48
随机数生成并非真正的“随机”。它是可预测的,并且所生成的序列由传入random.seed的种子值决定。通常你只需调用random.seed(),它会使用当前时间作为种子值,这意味着每次运行脚本时都会得到不同的数值序列。 - Asad Saeeduddin
5
如果将相同的种子传递给随机函数,并再次调用该函数,就会得到相同的数字集合。这是预期的行为,如果您希望每次结果不同,就需要在每次启动应用程序时使用不同的种子(例如从/dev/random或时间戳获取)。 - Tymoteusz Paul
7
种子是喂给随机数生成器以产生第一个随机数的。之后,随机数生成器自我喂养。由于这个原因,你不会看到相同的答案。如果再次运行这个脚本,将会得到相同的“随机”数序列。设置种子有助于重现结果,因为生成的所有“随机”数都将始终相同。 - Blink
值得一提的是:本帖中展示的序列是基于Python 2的。Python 3会给出不同的序列。 - ggorlen
2
@Blink对“随机数”的使用是误导性的。RNG具有自我反馈的内部状态。从这个内部状态中,派生出randint(1,10)和其他调用的输出。如果RNG从randint(1,10)的输出中获取数据,则序列将崩溃为最多10个序列之一,并且在最多10个数字后重复序列。 - Joachim Wagner
12个回答

263

伪随机数生成器通过对一个值执行某些操作来工作。通常,这个值是生成器产生的上一个数字。但是,在第一次使用生成器时,没有先前的值。

为伪随机数生成器提供种子值,可以给它赋予第一个“先前”的值。每个种子值将对应于给定随机数生成器生成的值序列。也就是说,如果您两次提供相同的种子,您会得到相同的数字序列两次。

通常,您希望用某个在每次程序执行时都会改变的值来为随机数生成器提供种子。例如,当前时间是经常使用的种子。之所以不自动发生这种情况,是因为如果您想要,可以提供特定的种子来获得已知的数字序列。


64
值得一提的是,有时我们希望提供种子以确保程序每次运行时生成相同的随机序列。有时,软件程序中避免使用随机性可以使程序行为确定,并有可能再现问题/错误。 - ViFI
4
遵循 @ViFI 的建议,保持程序的确定性(使用固定种子或固定的种子序列)也可以让您更好地评估对程序的某些更改是否有益。 - shaneb
4
这是一个真实的场景:https://dev59.com/IW025IYBdhLWcg3wtofX。随机种子也常用于产生可重现的研究结果。例如,如果你是一名数据科学家,想要发布使用随机性(如随机森林)的某种模型的结果,你需要在代码中包含一个种子,以便人们可以确保你的计算结果是可重现的。 - Galen Long
1
@Jitin 不完全正确。伪随机数生成器实际上会产生一系列(非常长的)重复数字。也就是说,理论上,如果你不断请求随机数足够长的时间,最终你会开始得到与起始时相同顺序的相同数字。提供的种子只是指定你从这个序列的哪个位置开始。 - Eric Finn
1
请注意,如果底层算法发生变化或者生成所请求的数字(在一个范围内)发生变化,random函数可能不会产生相同的随机数。因此,只有在完全相同的运行时环境下(例如单元测试期间),才能依赖这种特性。更多信息请参阅官方规范中的可重现性主题。 - undefined
显示剩余2条评论

108

所有其他答案似乎都没有解释random.seed()的用法。以下是一个简单的示例(来源):

import random
random.seed( 3 )
print "Random number with seed 3 : ", random.random() #will generate a random number 
#if you want to use the same random number once again in your program
random.seed( 3 )
random.random()   # same random number as before

47
>>> random.seed(9001)   
>>> random.randint(1, 10)  
1     
>>> random.seed(9001)     
>>> random.randint(1, 10)    
1           
>>> random.seed(9001)          
>>> random.randint(1, 10)                 
1                  
>>> random.seed(9001)         
>>> random.randint(1, 10)          
1     
>>> random.seed(9002)                
>>> random.randint(1, 10)             
3

你可以尝试这个。

假设 'random.seed' 为随机值生成器 ('random.randint()') 分配一个值,该生成器基于此种子生成这些值。 随机数的必备属性之一是它们应该是可重现的。 当您使用相同的种子时,您会得到相同的随机数模式。 这样,您就可以从一开始就生成它们。 您提供不同的种子-它将以不同的初始值(高于3)开始。

给定一个种子,它将依次生成1到10之间的随机数。 因此,您可以为一个种子值假定一个数字集。


21

通过对先前值进行某些操作生成随机数

如果没有先前的值,则自动将当前时间作为先前值。我们可以使用random.seed(x)提供先前值,其中x可以是任何数字或字符串等。

因此,random.random()实际上并非完全随机的数字,可以通过random.seed(x)预测。

import random 
random.seed(45)            #seed=45  
random.random()            #1st rand value=0.2718754143840908
0.2718754143840908  
random.random()            #2nd rand value=0.48802820785090784
0.48802820785090784  
random.seed(45)            # again reasign seed=45  
random.random()
0.2718754143840908         #matching with 1st rand value  
random.random()
0.48802820785090784        #matching with 2nd rand value
因此,生成随机数字并不是真正的随机,因为它依赖于算法。算法总是根据相同的输入输出相同的结果。这意味着它取决于种子的值。因此,为了使其更加随机,时间会自动分配给 seed()

14
Seed() can be used for later use ---

Example:
>>> import numpy as np
>>> np.random.seed(12)
>>> np.random.rand(4)
array([0.15416284, 0.7400497 , 0.26331502, 0.53373939])
>>>
>>>
>>> np.random.seed(10)
>>> np.random.rand(4)
array([0.77132064, 0.02075195, 0.63364823, 0.74880388])
>>>
>>>
>>> np.random.seed(12) # When you use same seed as before you will get same random output as before
>>> np.random.rand(4)
array([0.15416284, 0.7400497 , 0.26331502, 0.53373939])
>>>
>>>
>>> np.random.seed(10)
>>> np.random.rand(4)
array([0.77132064, 0.02075195, 0.63364823, 0.74880388])
>>>

13
# Simple Python program to understand random.seed() importance

import random

random.seed(10)

for i in range(5):    
    print(random.randint(1, 100))

多次执行上面的程序...

第一次尝试:打印在1-100范围内的5个随机整数

第二次尝试:打印与上次相同的5个随机数字。

第三次尝试:同上

...以此类推

说明:每次运行以上程序时,我们都会设置种子为10,然后随机生成器将其作为一个参考变量。然后通过一些预定义的公式生成一个随机数。

因此,在下一次执行中再次将种子设置为10便会重新设置参考数字为10,然后相同的行为重新开始...

一旦我们重置种子值,它就会给出相同的结果。

注意:更改种子值并运行该程序,您将看到不同于上一次的随机序列。


9

在这种情况下,随机数实际上是伪随机数。给定一个种子,它将生成具有相等分布的数字。但是使用相同的种子,它每次都会生成相同的数字序列。如果您想要更改数字序列,您需要更改种子。很多人喜欢基于当前时间或其他东西生成种子。


为什么要根据当前时间生成种子?Python会尽可能地使用操作系统的随机数生成器(在桌面/服务器系统上始终如此),然后将当前时间作为备用。因此,如果您想要“真正”的随机数,根本不需要提供种子。 - undefined

6

在生成一组随机数之前,设置seed(x),并使用相同的种子生成相同的随机数集合。这在重现问题时非常有用。

>>> from random import *
>>> seed(20)
>>> randint(1,100)
93
>>> randint(1,100)
88
>>> randint(1,100)
99
>>> seed(20)
>>> randint(1,100)
93
>>> randint(1,100)
88
>>> randint(1,100)
99
>>> 

6

在我看来,当你再次使用random.seed(samedigit)时,它被用于生成相同的随机结果。

In [47]: random.randint(7,10)

Out[47]: 9


In [48]: random.randint(7,10)

Out[48]: 9


In [49]: random.randint(7,10)

Out[49]: 7


In [50]: random.randint(7,10)

Out[50]: 10


In [51]: random.seed(5)


In [52]: random.randint(7,10)

Out[52]: 9


In [53]: random.seed(5)


In [54]: random.randint(7,10)

Out[54]: 9

2

以下是我的理解。 每次我们设置一个种子值,都会生成一个“标签”或“引用”。下一次调用random.function时,它将附加到这个“标签”,因此下一次调用相同的种子值和random.function时,它将给出相同的结果。

np.random.seed( 3 )
print(np.random.randn()) # output: 1.7886284734303186

np.random.seed( 3 )
print(np.random.rand()) # different function. output: 0.5507979025745755

np.random.seed( 5 )
print(np.random.rand()) # different seed value. output: 0.22199317108973948

在伪随机数生成器(PRNG)中,并不存在所谓的“标签”,只有一个“状态”。你只是无缘无故地“引入”了一个术语。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接