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"s random_instкак возвращено random.getstate() когда ему дали семя 1234 и вы можете догадаться, что seed7883 является. Что я сделал, я создал TestSampler в терминале, дал ему случайное семя 1234, приобрел государство с rand_inst.getstate() и сохранить его в файл. Затем я воссоздаю регрессионный тест и всегда получаю один и тот же результат.

ТЕМ НЕ МЕНИЕ

Та же процедура, что и выше, не работает для test_sampler2 - что бы я не получал одинаковую случайную последовательность чисел. Я использую питона random модуль, и я не импортирую его куда-либо еще, но я использую numpy в некоторых местах (но не numpy.random).

Единственная разница между test_sampler1 а также test_sampler2 является то, что они созданы из 2 разных файлов. Я знаю, что это большое дело, и оно полностью зависит от кода, который я написал, но я также не могу просто вставить здесь ~800 строк кода, я просто ищу общее представление о том, что я могу испортить...

Что может карабкаться test_sampler2генератор случайных чисел?

Решение

С моим кодом было две отдельные проблемы:

1

Мой сценарий является сценарием командной строки, и после того, как я реорганизовал его для использования Python optparse Библиотека я обнаружил, что я устанавливал семя для моего сэмплера, используя что-то вроде seed = sys.argv[1] Это означало, что я собирался стать strне int - seed может взять любой хешируемый объект и я нашел его трудным путем. Это объясняет, почему я получил бы 2 разные последовательности, если бы использовал одно и то же семя - одну, если я запускаю свой скрипт из командной строки с помощью команды sth python sample 1234 #seed is 1234 и из моего unit_tests.py файл, когда я хотел бы создать экземпляр объекта, как test_sampler1 = TestSampler(seed=1234),

2

У меня есть функция для дискретной выборки распределения, которую я позаимствовал отсюда (посмотрите на принятый ответ). В коде отсутствовало что-то фундаментальное: оно все еще было недетерминированным в том смысле, что если вы дадите ему тот же массив значений и вероятностей, но трансформируется перестановкой (скажем, значениями) ['a','b'] и пробы [0.1,0.9] и ценности ['b','a'] и вероятности [0.9,0.1]) и семя будет установлено, и вы получите тот же случайный образец, скажем, 0.3PRNG, но так как интервалы для ваших вероятностей разные, в одном случае вы получите b и в одном a, Чтобы исправить это, я просто сжал значения и вероятности вместе, отсортированные по вероятности и тадаа - теперь я всегда получаю одинаковые интервалы вероятности.

После исправления обеих проблем код работал как ожидалось, т.е. out2 начал вести себя детерминистически.

1 ответ

Единственная вещь (кроме внутренней ошибки Python), которая может изменить состояние random.Random Экземпляр вызывает методы в этом экземпляре. Таким образом, проблема заключается в том, что вы не показали нам. Вот небольшая тестовая программа:

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 чтобы выяснить, что делает это. Существуют более умные способы сделать это, но лучше сохранить их простыми, чтобы в итоге вы не отладили код отладки.

Другие вопросы по тегам