Как отменить случайную последовательность, ранее посеянную в numpy? - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь сгенерировать случайные числа в функции множественных пересечений. Моя проблема в том, что мне нужно посеять первую часть случайного поколения, а не вторую. Я бы хотел, чтобы начальное число для первой части было одинаковым для всех процессов.

Я попытался отменить генерацию, выбрав случайное число Int (np.random.seed(np.random.randint(100000000))), но поскольку я сначала посеял генератор, я выберите тот же самый Int для остальной части поколения.

Я не могу использовать np.random.seed(None) или np.random.seed(random.seed(time.time())), потому что Мой класс использует @jitclass, что делает их не подходящими.

Так я получаю та же последовательность для каждого процесса.

0 [0.5488135  0.71518937 0.60276338 0.54488318 0.4236548 ]
0 [0.91989807 0.99511873 0.6750629  0.60976887 0.65852849]
1 [0.5488135  0.71518937 0.60276338 0.54488318 0.4236548 ]
1 [0.91989807 0.99511873 0.6750629  0.60976887 0.65852849]
2 [0.5488135  0.71518937 0.60276338 0.54488318 0.4236548 ]
2 [0.91989807 0.99511873 0.6750629  0.60976887 0.65852849]

Здесь MWE

import numpy as np
import multiprocessing
import random


class mp_worker_class():

    def __init__(self,):
        pass

    @classmethod
    def start(self, nb=None, seed=None, nbcore=None):
        lfp_p=np.empty((nbcore,nb))
        pipe_list = []
        for h in range(nbcore):
            recv_end, send_end = multiprocessing.Pipe( )
            p = multiprocessing.Process(target=self.mp_worker , args=(h, nb, seed, send_end ))
            p.start()
            pipe_list.append(recv_end)

        for idx, recv_end in enumerate(pipe_list):
            lfp_p[idx,:]=recv_end.recv()


        return lfp_p

    @classmethod
    def mp_worker(self,h, nb=None, seed=None, send_end=None):
        np.random.seed(seed)
        np.random.seed(0)
        print(h,np.random.rand(5))
        #trying to undo the seed
        np.random.seed(np.random.randint(100000000))
        print(h, np.random.rand(5))
        send_end.send(np.random.rand(5))
        return

if __name__ == '__main__':
    print(mp_worker_class().start(nb=10, seed=1, nbcore=3 ))

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Вы можете сохранить состояние генератора случайных чисел и восстановить его позже:

original_state = np.random.get_state()
np.random.seed(seed)

# ... stuff using your seeded random

np.random.set_state(original_state)
1 голос
/ 28 февраля 2020

Вы должны просто дать каждому процессу другое второе семя:

...
    @classmethod
    def start(self, nb=None, seed=None, seeds=None, nbcore=None):
        if seeds if not None:
            seeds = iter(seeds)          # get an iterator
        lfp_p=np.empty((nbcore,nb))
        pipe_list = []
        for h in range(nbcore):
            recv_end, send_end = multiprocessing.Pipe( )
            seed2 = None if seeds = None else next(seeds)
            p = multiprocessing.Process(target=self.mp_worker ,
                                        args=(h, nb, seed, seed2, send_end ))
            p.start()
            pipe_list.append(recv_end)

        for idx, recv_end in enumerate(pipe_list):
            lfp_p[idx,:]=recv_end.recv()


        return lfp_p

    @classmethod
    def mp_worker(self,h, nb=None, seed=None, seed2=None, send_end=None):
        np.random.seed(seed)
        print(h,np.random.rand(5))
        np.random.seed(seed2)
        print(h, np.random.rand(5))
        send_end.send(np.random.rand(5))
        return

if __name__ == '__main__':
    print(mp_worker_class().start(nb=10, seed=1, seeds=[2, 3, 4], nbcore=3 ))

Таким образом, вы дадите любую итерацию за seeds до start, и каждый работник получит свое собственное семя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...