Python随机种子在遗传编程示例代码中不起作用
我正在尝试使用Toby Segaran的《编程集体智能》第11章中的遗传编程代码来获得可重复的结果。不过,单纯设置“random.seed(55)”似乎没有效果,把原来的代码“from random import ....”改成“import random”也没用,甚至改变Random()也没有帮助。这些方法看起来都差不多,树的构建开始是一样的,但之后就开始分歧了。
我查阅了很多关于随机数行为的资料,但在他的遗传编程代码中,我找不到任何理由解释这种分歧。代码中似乎只有调用随机数的部分,没有其他会导致这种行为的变化。我理解调用random.seed()应该能正确设置所有的随机调用,而且代码根本没有使用多线程,所以我不明白为什么会出现这种分歧。
有没有人修改过这个代码,使其能够产生可重复的结果?有没有什么更好的方法来调用random.seed()?
抱歉没有提供示例代码,但这段代码显然不是我自己的(我只是添加了对seed的调用,并改变了代码中随机数的调用方式),而且这似乎不是一个简单的随机数问题(我已经阅读了这里关于Python随机数的所有条目,以及网上的许多相关内容)。
谢谢。
Mark L.
3 个回答
这可能会对你有帮助,下面是创建一个不会被其他地方干扰的随机对象的方法:
from random import Random
random = Random(55)
# random can be used like the plain module
如果其他库出于某种原因调用了 random.seed
,也不会影响你为程序创建的随机对象。
我在gp.py文件中添加了以下函数,其他地方没有做任何改动:
def set_seed(n):
import random
random.seed(n)
我使用的模块是基于这本书第267页的例子。我可以确认,在以下实验中,我得到了不同的结果:
>>> import gp
>>> gp.set_seed(55)
>>> rf = gp.getrankfunction(gp.buildhiddenset())
>>> gp.evolve(2, 500, rf, mutationrate=0.2, breedingrate=0.1, pexp=0.7, pnew=0.1)
结果在打印的第4个值时就开始出现差异。我在每次实验之间都重启解释器,所以问题不是由之前的状态引起的。
编辑:
我发现了随机因素。问题出在树的内存地址上。rank函数会对结果列表进行排序,每个项目都是一个包含分数和树的元组。在不同的运行之间,地址会发生变化,因此相同分数的树的相对排序顺序就不是固定的。幸运的是,Python有稳定的排序方法,所以解决方案很简单。只需使用一个排序关键字,仅根据分数进行排序:
def getrankfunction(dataset):
def rankfunction(population):
scores=[(scorefunction(t, dataset), t) for t in population]
scores.sort(key=lambda x: x[0])
return scores
return rankfunction
我刚才遇到了同样的问题,虽然和我写的代码完全没有关系。我觉得我的解决办法和eryksun的答案有点像,不过我没有用树。我用的是一些集合,然后我用 random.choice(list(set))
从中随机选择值。有时候,即使每次用的种子都一样,我得到的结果(选中的项目)还是不一样,这让我快要抓狂了。在看到eryksun的回答后,我试着用 random.choice(sorted(set))
,结果问题好像就解决了。我对Python的内部工作原理了解得不够,所以不能解释为什么会这样。