1つの値からN個の独立した乱数ジェネレータをシードする最良の方法


10

私のプログラムでは、大規模なデータセットのサンプリングに使用される独自のRNGを使用して、それぞれN個の個別のスレッドを実行する必要があります。結果を再現できるように、このプロセス全体に単一の値をシードできるようにする必要があります。

各インデックスのシードを単純に順次増やすだけで十分ですか?

現在、私は使用numpyRandomStateメルセンヌツイスターの擬似乱数生成器を使用しています。

以下のコードの抜粋:

# If a random number generator seed exists
if self.random_generator_seed:
    # Create a new random number generator for this instance based on its
    # own index
    self.random_generator_seed += instance_index
    self.random_number_generator = RandomState(self.random_generator_seed)

基本的に、ユーザーが入力したシード(存在する場合)から始め、インスタンス/スレッドごとに、実行中のインスタンスのインデックス(0からN-1)を順番に追加します。これが良い習慣なのか、これを行うより良い方法があるのか​​はわかりません。


1
各スレッドが使用する疑似ランダム値の数を事前に知っていますか?少なくとも、適切な上限推定値を取得できますか?
whuber

私にはできません。しきい値になるまで合計される領域をサンプリングします。領域のサイズは大幅に異なる場合があります。
EricR

回答:


9

確かに、それは素晴らしい習慣ではありません。たとえば、12345と12346のルートシードで2つの実行を実行するとどうなるかを考えますN-1。各実行には共通のストリームがあります。

Mersenne Twister実装(numpy.randomおよびを含むrandom)は通常、異なるPRNGを使用して、MTが使用する大きな状態ベクトル(624 32ビット整数)に整数シードを拡張します。これはの配列ですRandomState.get_state()。あなたが望むことをする良い方法は、そのPRNGを実行し、入力整数を一度シードしてN*624、そこから32ビット整数を取得することです。そのストリームをN状態ベクトルに分割し、RandomState.set_state()RandomStateインスタンスを明示的に初期化するために使用します。そのPRNGを取得するには、標準ライブラリのCソースnumpy.randomまたは_random標準ライブラリからの参照が必要になる場合があります(これらは同じです)。誰かがそのPRNG for Pythonのスタンドアロンバージョンを実装したかどうかはわかりません。


これが今まで聞いた中で一番の解決策かもしれないと思います。ストリームを正しく分割する方法はそれほど重要ではないと思いますか?最初のPRNGとシードからどのように選択されても、インスタンス間で624 32ビット整数のシーケンスが重複する可能性ははるかに低いようです。
EricR

1
実は、少し歩きます。イニシャライザPRNGがそこから任意に多くの値を引き出すように設計されているかどうかは、私にはわかりません。状態ストリームを生成するために、別の品質のPRNG(MTに関連しないことが望ましい)の使用を検討してください。標準ライブラリのみを比較的簡単に使用して、HMAC-DRBG(HMACを暗号プリミティブとして使用するPRNG)を実装できます。暗号化のセキュリティは問題ではありません。実装の容易さとビットストリームの品質だけです。非常にまれなオフチャンスで、すべて0のベクターが作成されないようにする必要があります。
Robert Kern

またはRandomState、設定可能なストリームを持つアルゴリズムを使用する開発中の新しい実装の1つを使用するだけです。つまり、各RandomStateインスタンスを同じシードと異なるストリームIDで初期化し(単にインクリメントするだけで十分です)、独立したストリームが保証されます。pypi.python.org/pypi/randomstate
Robert Kern

4

使用される溶液の並列処理は、あなたの乱数発生器を使用することである、することによって、あなたの種子であり -batches。Φ(u)uN

  1. 生成Φ(u),ΦN(u),Φ2N(u),...
  2. 生成Φ2(u),Φ1+N(u),Φ1+2N(u),...
  3. ...
  4. 生成ΦN1(u),ΦN1+N(u),ΦN1+2N(u),...

ここで、です。この方法では、単一のシードを使用し、シーケンスはすべて均一で独立しています。Φn(u)=Φ(Φn1(u))


2

これを実現するメソッドを持つRandomGenというPythonパッケージができました。

それはサポートして単一の種、ならびにMT19937などの古い乱数発生器のための跳躍プロトコルから作成された独立したストリームを。


0

一部の人々は、シーケンシャルシードによって生成された乱数に相関があると主張しています。/programming/10900852/near-seeds-in-random-number-generation-may-give-similar-random-numbersそれがどれほど本当かわからない。

それが心配な場合は、単一の乱数ジェネレータを使用して、他のすべてのジェネレータのシードを選択してみませんか?


単に、2つ以上のジェネレーターに対して同じシードをランダムに生成する可能性がないようにするためです。もちろん、これを防ぐためにプログラミング作業を行うこともできますが、そもそもシーズを順番に選択するよりも、それがどのように良いのかわかりません。
EricR

1
どうやら、シーケンシャルシードで相関が可能です...しかし、John D Cookのブログの回答にリンクされている記事が示すように、1つのRNGを使用して他のジェネレーターのシードを生成することは、誕生日の問題にぶつかるため、はるかに悪いです!ランダムに1000個の16ビット符号なしシードを生成すると、99.95%のオーバーラップの可能性があると言われています。
Praveen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.