Мой вопрос - полная противоположность this one.Python что-то сбрасывает мое случайное семя
Это отрывок из моего тестового файла
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
'random_inst
', которое было возвращено random.getstate()
, когда было дано семя 1234
, и вы можете догадаться, что такое seed7883
. То, что я сделал, я создал TestSampler
в терминале, дал ему случайное семя 1234
, приобрел состояние с rand_inst.getstate()
и сохранил его в файл. Затем я воссоздаю регрессионный тест, и я всегда получаю тот же результат.
ОДНАКО
Та же процедура, что и выше не работает test_sampler2
- все, что я не получаю ту же случайную последовательность чисел. Я использую модуль random
python, и я не импортирую его нигде, но в некоторых местах я использую numpy
(но не numpy.random
).
Единственная разница между test_sampler1
и test_sampler2
заключается в том, что они созданы из 2 разных файлов. Я знаю, что это большое дело, и это полностью зависит от кода, который я написал, но я также не могу просто вставить здесь ~ 800 строк кода, я просто ищу какое-то общее представление о том, что я могу испортить ...
Что может быть скремблировать состояние генератора случайных чисел test_sampler2
?
Решение
Были 2 отдельные проблемы с моим кодом:
Мой сценарий командной строки сценария и после того, как я реструктурировать его использовать optparse
библиотеку питона я узнал, что Я устанавливал семя для моего пробоотборника, используя что-то вроде seed = sys.argv[1]
, что означало, что я устанавливал семя как str
, а не int
- seed
может принимать любые хэши e, и я нашел это трудным путем. Это объясняет, почему я получал бы две разные последовательности, если бы использовал одно и то же семя - один, если я запустил свой сценарий из командной строки с помощью sth, например 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]
) и семя установлено, и вы получите тот же случайный образец, скажем 0.3
, по PRNG, но так как интервалы для ваших вероятностей разные, в одном случае вы получите b
и в одном a
. Чтобы исправить это, я просто связал значения и вероятности вместе, отсортированные по вероятности и тадаа - теперь я всегда получаю одинаковые интервалы вероятности.
После исправления обеих проблем код работал, как ожидалось, i.e. out2 начал детерминистически деваться.
Я принимал бы обратную связь и в нисходящем направлении ... Что не так с этим вопросом? – baibo
Почему бы не использовать 'pickle.dump (random_inst, f1)' и 'random_inst = pickle.load (f1)' вместо 'eval'? –
Итак, вы говорите, что загрузка одного и того же файла семени снова и снова дает другую последовательность? Какую версию Python вы используете? –