Python 种子通过子函数



我有一个函数和一个子函数,在每个函数中都生成了一些随机数组。为了使结果可重复,我使用种子。但是,我看到了奇怪的案例。

当我在子函数中有一个种子时,主函数中的随机数也会从子函数中的种子中获得效果。而且,从主功能到子功能都没有这种效果。例如,请考虑以下代码。

import random
from random import randint
import numpy as np

def randgene():
    a=np.random.randint(0,5,size=5)
    print "a in function", a
    np.random.seed(seed=15)
    b=np.random.randint(0,5,size=5)
    print "b in function", b
    d=np.random.choice(50, size=5, replace = False)
    print "d in function", d
    # np.random.seed(seed=None)
def main():
    print "d-without seed", np.random.choice(50, size=5, replace = False)
    print "a-without seed", np.random.randint(0,5,size=5)
    print "b-without seed", np.random.randint(0,5,size=5)
    f = randgene()    
    print "d-without seed", np.random.choice(50, size=5, replace = False)
    print "a-without seed", np.random.randint(0,5,size=5)
    print "b-without seed", np.random.randint(0,5,size=5)
    f = randgene()
    print "d-without seed", np.random.choice(50, size=5, replace = False)
    print "a-without seed", np.random.randint(0,5,size=5)
    print "b-without seed", np.random.randint(0,5,size=5)
    np.random.seed(seed=10)
    print "d-with seed", np.random.choice(50, size=5, replace = False)
    print "a-with seed", np.random.randint(0,5,size=5)
    print "b-with seed", np.random.randint(0,5,size=5)
    f = randgene()
    print "d-with seed", np.random.choice(50, size=5, replace = False)
    print "a-with seed", np.random.randint(0,5,size=5)
    f = randgene()
    print "d-with seed", np.random.choice(50, size=5, replace = False)
    print "a-with seed", np.random.randint(0,5,size=5)
if __name__ == '__main__':
    main()

对于这段代码,我得到这个结果:

d-without seed [14 29  9 42 18]
a-without seed [3 0 0 3 4]
b-without seed [3 2 0 2 1]
a in function [2 3 1 2 3]
b in function [0 4 0 4 3]
d in function [41 16 22 24 14]
d-without seed [ 8 21 32 39 11]
a-without seed [3 0 3 3 0]
b-without seed [1 2 2 1 4]
a in function [4 4 0 2 2]
b in function [0 4 0 4 3]
d in function [41 16 22 24 14]
d-without seed [ 8 21 32 39 11]
a-without seed [3 0 3 3 0]
b-without seed [1 2 2 1 4]
d-with seed [37 23 44 42 47]
a-with seed [2 0 0 4 4]
b-with seed [0 0 2 4 2]
a in function [0 0 2 3 0]
b in function [0 4 0 4 3]
d in function [41 16 22 24 14]
d-with seed [ 8 21 32 39 11]
a-with seed [3 0 3 3 0]
a in function [1 2 2 1 4]
b in function [0 4 0 4 3]
d in function [41 16 22 24 14]
d-with seed [ 8 21 32 39 11]
a-with seed [3 0 3 3 0]

每当我调用子函数时,您都会在其中看到d-with seed [ 8 21 32 39 11], a-with seed [3 0 3 3 0] 在主函数中重复。但是,如果我在子函数中注释np.random.seed(seed=15)行,我会得到以下结果:

d-without seed [17 20 23 36 28]
a-without seed [3 1 1 2 0]
b-without seed [3 2 1 1 3]
a in function [1 2 2 0 4]
b in function [4 4 0 4 2]
d in function [ 9 46 19  7 47]
d-without seed [39 42 10 17  4]
a-without seed [2 3 0 2 4]
b-without seed [1 4 1 3 2]
a in function [1 1 3 3 2]
b in function [1 3 4 4 3]
d in function [ 0  2 45  5 19]
d-without seed [24 20 47  3 29]
a-without seed [3 0 3 3 3]
b-without seed [1 0 0 2 3]
d-with seed [37 23 44 42 47]
a-with seed [2 0 0 4 4]
b-with seed [0 0 2 4 2]
a in function [0 0 2 3 0]
b in function [4 4 0 1 1]
d in function [ 6 11 35  4  7]
d-with seed [19 47 43 38 15]
a-with seed [0 4 2 1 2]
a in function [1 2 1 3 2]
b in function [3 4 4 0 2]
d in function [38 31 17 43  2]
d-with seed [ 7 15 39  2 49]
a-with seed [3 4 1 4 0]

显然没有重复。因此,主函数中的种子在子函数中没有效果。如果我保持np.random.seed(seed=15)np.random.seed(seed=None)不加注释,我会得到类似的结果。有人可以解释我发生了什么吗?

提前致谢,阿夫申

对于局部随机状态,只需使用 numpy.random.RandomState 而不是 numpy.random.seed 设置的全局状态。

举个例子:

import numpy as np
seed1 = 1
seed2 = 42
rs1 = np.random.RandomState(seed1)
rs2 = np.random.RandomState(seed2)
rs3 = np.random.RandomState(seed1)  # same seed value used for rs1
a = rs1.randint(0, 5, size=5)
b = rs1.randint(0, 5, size=5)
c = rs2.randint(0, 5, size=5)
e = rs3.randint(0, 5, size=5)
f = rs3.randint(0, 5, size=5)

eq = np.testing.assert_array_equal
try:
    eq(a, b, err_msg='OK, a should be != b')
except AssertionError:
    pass
try:
    eq(a, c, err_msg='OK, a should be != c')
except AssertionError:
    pass
eq(a, e, err_msg='ERROR')  # a and e are equal due to same seed
eq(b, f, err_msg='ERROR')  # b and f are equal due to same seed
print('OK')
<</div> div class="one_answers">

随机数生成器种子用于设置其全局状态。该状态用于在该点之后生成的所有数字(生成的每个数字都会导致状态更改)。您可以使用全局变量将您的示例与此示例进行比较:

def print_and_increment(): # this is like generating a random number
    global x
    print("x was {}. Incrementing...".format(x))
    x += 1
    print("x is now", x)
def func():
    global x
    print("func before seed")
    print_and_increment()
    x = 10 # this is equivalent to calling seed()
    print("func after seed")
    print_and_increment()
x = 0  # seed
print("top")
print_and_increment()
func()
print("middle")
print_and_increment()
func()
print("bottom")
print_and_increment()

如果您希望函数具有它始终使用的自己的种子,但为了使它不更改外部使用的随机数生成器的状态,则可以使用 numpy.random.get_statenumpy.random.set_state

尝试这样的事情:

def randgene():
    prev_state = np.random.get_state()
    a=np.random.randint(0,5,size=5)
    print "a in function", a
    np.random.seed(seed=15)
    b=np.random.randint(0,5,size=5)
    print "b in function", b
    d=np.random.choice(50, size=5, replace = False)
    print "d in function", d
    # np.random.seed(seed=None)
    np.random.set_state(prev_state)

现在,您的函数应该不会影响外部代码对随机数生成器的使用。

最新更新