Python会重置我的随机种子

时间:2013-12-10 00:13:33

标签: python random numpy regression-testing

我的问题与this one完全相反。

这是我的测试文件的摘录

f1 = open('seed1234','r')
f2 = open('seed7883','r')
s1 = eval(f1.read())
s2 = eval(f2.read())
f1.close()
f2.close()
####
test_sampler1.random_inst.setstate(s1)
out1 = test_sampler1.run()
self.assertEqual(out1,self.out1_regress) # this is fine and passes

test_sampler2.random_inst.setstate(s2)
out2 = test_sampler2.run()
self.assertEqual(out2,self.out2_regress) # this FAILS

一些信息 -

test_sampler1test_sampler2是来自执行某些随机抽样的类的2个对象。该类具有属性random_inst,该属性是random.Random()类型的对象。文件seed1234包含TestSampler的{​​{1}}状态,当random_instrandom.getstate()种子时,1234可以猜出seed7883 {1}}是。我做的是我在终端中创建了一个TestSampler,给它一个1234的随机种子,用rand_inst.getstate()获取状态并将其保存到文件中。然后我重新创建回归测试,我总是得到相同的输出。

无论其

上述相同的程序对test_sampler2不起作用 - 无论我没有得到相同的随机数字序列。我正在使用python的random模块,我没有在其他地方导入它,但我在某些地方使用numpy(但不是numpy.random)。

test_sampler1test_sampler2之间的唯一区别是它们是从2个不同的文件创建的。我知道这是一个大问题,它完全依赖于我编写的代码,但我也不能简单地在这里粘贴〜800行代码,我只是在寻找一些关于我可能会弄乱的一般概念......

什么可能扰乱test_sampler2的随机数生成器的状态?

解决方案

我的代码有两个不同的问题:

1

我的脚本是一个命令行脚本,在我重构它以使用python的optparse库后,我发现我使用像seed = sys.argv[1]之类的东西为我的采样器设置种子,这意味着我正在设置种子为str,而不是int - seed可以使用任何可清洗对象,我发现它很难。这解释了为什么如果我使用相同的种子,我会得到2个不同的序列 - 如果我从命令行运行我的脚本,如python sample 1234 #seed is 1234和我的unit_tests.py文件,那么我将创建一个对象实例比如test_sampler1 = TestSampler(seed=1234)

2

我有一个离散分布采样函数,我从here借用(看看接受的答案)。那里的代码缺少一些基本的东西:它仍然是非确定性的,如果你赋予它相同的值和概率数组,但是通过置换(比如值['a','b']和probs [0.1,0.9]和值['b','a']和概率[0.9,0.1])并设置了种子,PRNG将获得相同的随机样本,例如0.3,但由于概率的间隔不同,因此一个案例,您将获得一个b,并在一个a。为了解决它,我只是将值和概率压缩在一起,按概率和tadaa排序 - 我现在总是得到相同的概率间隔。

在解决了两个问题之后,代码按预期工作,即out2开始确定性地运行。

1 个答案:

答案 0 :(得分:1)

可以改变random.Random实例状态的唯一(除了内部Python错误)是调用该实例上的方法。所以问题在于你没有向我们展示的东西。这是一个小测试程序:

from random import Random

r1 = Random()
r2 = Random()

for _ in range(100):
    r1.random()
for _ in range(200):
    r2.random()

r1state = r1.getstate()
r2state = r2.getstate()

with open("r1state", "w") as f:
    print >> f, r1state
with open("r2state", "w") as f:
    print >> f, r2state


for _ in range(100):
    with open("r1state") as f:
        r1.setstate(eval(f.read()))
    with open("r2state") as f:
        r2.setstate(eval(f.read()))
    assert r1state == r1.getstate()
    assert r2state == r2.getstate()

我没有整天都跑,但我打赌我可以并且永远不会看到失败的断言; - )

顺便说一下,使用pickle这种事情肯定更常见,但它不会解决你的真正问题。问题不在于获取或设置状态。问题是你还没有找到的东西是在你的random.Random个实例上调用方法。

虽然这样做是一个很大的痛苦,但你可以尝试将打印语句添加到random.py以找出正在做的事情。有更聪明的方法可以做到这一点,但最好还是保持简单,这样你就不会最终调试调试代码了。