我的问题与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_sampler1
和test_sampler2
是来自执行某些随机抽样的类的2个对象。该类具有属性random_inst
,该属性是random.Random()
类型的对象。文件seed1234
包含TestSampler
的{{1}}状态,当random_inst
为random.getstate()
种子时,1234
可以猜出seed7883
{1}}是。我做的是我在终端中创建了一个TestSampler
,给它一个1234
的随机种子,用rand_inst.getstate()
获取状态并将其保存到文件中。然后我重新创建回归测试,我总是得到相同的输出。
无论其
上述相同的程序对test_sampler2
不起作用 - 无论我没有得到相同的随机数字序列。我正在使用python的random
模块,我没有在其他地方导入它,但我在某些地方使用numpy
(但不是numpy.random
)。
test_sampler1
和test_sampler2
之间的唯一区别是它们是从2个不同的文件创建的。我知道这是一个大问题,它完全依赖于我编写的代码,但我也不能简单地在这里粘贴〜800行代码,我只是在寻找一些关于我可能会弄乱的一般概念......
什么可能扰乱test_sampler2
的随机数生成器的状态?
解决方案
我的代码有两个不同的问题:
我的脚本是一个命令行脚本,在我重构它以使用python的optparse
库后,我发现我使用像seed = sys.argv[1]
之类的东西为我的采样器设置种子,这意味着我正在设置种子为str
,而不是int
- seed
可以使用任何可清洗对象,我发现它很难。这解释了为什么如果我使用相同的种子,我会得到2个不同的序列 - 如果我从命令行运行我的脚本,如python sample 1234 #seed is 1234
和我的unit_tests.py
文件,那么我将创建一个对象实例比如test_sampler1 = TestSampler(seed=1234)
。
我有一个离散分布采样函数,我从here借用(看看接受的答案)。那里的代码缺少一些基本的东西:它仍然是非确定性的,如果你赋予它相同的值和概率数组,但是通过置换(比如值['a','b']
和probs [0.1,0.9]
和值['b','a']
和概率[0.9,0.1]
)并设置了种子,PRNG将获得相同的随机样本,例如0.3
,但由于概率的间隔不同,因此一个案例,您将获得一个b
,并在一个a
。为了解决它,我只是将值和概率压缩在一起,按概率和tadaa排序 - 我现在总是得到相同的概率间隔。
在解决了两个问题之后,代码按预期工作,即out2开始确定性地运行。
答案 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
以找出正在做的事情。有更聪明的方法可以做到这一点,但最好还是保持简单,这样你就不会最终调试调试代码了。