乱数ジェネレータをシードするために使用されたシードPythonを見つける方法はありますか?
私は自分のシードを指定できることを知っていますが、Pythonそれを管理することに非常に満足しています。しかし、どのシードが使用されたかを知りたいので、結果が気に入ったら、 m特定の実行に入ると、その実行を後で再現することができました。
答えができない場合、自分で種を生成する最良の方法は何ですか?常に実行ごとに異なるものにしたいのですが、何が使用されたかを知りたいだけです。
更新:はい、つまり、random.random()を意味します!間違い... [タイトル更新]
自動シードをジェネレーターから戻すことはできません。私は通常、次のようなシードを生成します。
seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)
この方法は時間ベースであるため、スクリプトを(手動で)実行するたびに異なりますが、複数のジェネレーターを使用している場合、ほぼ同時に作成されたという理由だけで、同じシードはありません。
乱数ジェネレーターの状態は、必ずしも単なるシードではありません。たとえば、安全なPRNGには通常、より大きなデータブロックであるエントロピーバッファーがあります。
ただし、ランダム番号ジェネレーターの状態全体を保存および復元できるため、後でその結果を再現できます。
import random
old_state = random.getstate()
print random.random()
random.setstate(old_state)
print random.random()
# You can also restore the state into your own instance of the PRNG, to avoid
# thread-safety issues from using the default, global instance.
prng = random.Random()
prng.setstate(old_state)
print prng.random()
もちろん、永続的に保存したい場合は、getstate
の結果をpickle化できます。
Random.Randomをサブクラス化し、seed()メソッドをpythonと同じように(この例ではv3.5)書き換えますが、super()を呼び出す前にシード値を変数に格納します。
import random
class Random(random.Random):
def seed(self, a=None, version=2):
from os import urandom as _urandom
from hashlib import sha512 as _sha512
if a is None:
try:
# Seed with enough bytes to span the 19937 bit
# state space for the Mersenne Twister
a = int.from_bytes(_urandom(2500), 'big')
except NotImplementedError:
import time
a = int(time.time() * 256) # use fractional seconds
if version == 2:
if isinstance(a, (str, bytes, bytearray)):
if isinstance(a, str):
a = a.encode()
a += _sha512(a).digest()
a = int.from_bytes(a, 'big')
self._current_seed = a
super().seed(a)
def get_seed(self):
return self._current_seed
テストすると、新しいシードで生成された最初のランダムな値と、同じシードを使用して生成された2番目の値(作成したget_seed()メソッドで)は等しくなります。
>>> rnd1 = Random()
>>> seed = rnd1.get_seed()
>>> v1 = rnd1.randint(1, 0x260)
>>> rnd2 = Random(seed)
>>> v2 = rnd2.randint(1, 0x260)
>>> v1 == v2
True
巨大なシード値を保存/コピーして別のセッションで使用しようとすると、生成される値はまったく同じになります。
同じことをしたかったのですが種が取れませんでした。なので、種は時間から生まれるのでと思いました。システム時間を使用してシードを作成し、それをシードとして使用したので、使用されたシードがわかりました。
SEED = int(time.time())
random.seed(SEED)
random.seed(None)
を使用してシードを「設定」すると、ランダマイザーはシステム時間として関数として自動的にシードされます。ただし、確認したように、この値にはアクセスできません。ランダム化したいのですが、シードがまだわかっている場合は、次のようにします。
_tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)
_
注:@Abdallahによって提案されたtime.time()
を使用するよりもこれを好む理由は、この方法でランドシードが人間が読める形式ですぐに理解できるため、多くの場合大きな利点があります。必要に応じて、日付コンポーネントやマイクロセグメントも追加できます。
通常、プログラミング言語で取得できる最良のランダムサンプルはオペレーティングシステムを介して生成されるとは誰も述べていないため、次のコードを提供する必要があります。
random_data = os.urandom(8)
seed = int.from_bytes(random_data, byteorder="big")
これは暗号的に安全です。
出典: https://www.quora.com/What-is-the-best-way-to-generate-random-seeds-in-python
値が8の場合、sys.maxsize
とほぼ同じ桁数になるようです。
>>> int.from_bytes(os.urandom(8), byteorder="big")
17520563261454622261
>>> sys.maxsize
9223372036854775807
>>>
シードは、次の乱数を作成するために使用されるランダムパッケージの内部変数です。新しい番号が要求されると、シードも更新されます。
毎回同じ乱数を持つようにしたい場合、またはiを構成可能にしたい場合は、シードとして0を単純に使用します。
CorelDrawには、シードで初期化されたランダムパターンジェネレーターがかつてありました。パターンはシードごとに大幅に変化するため、シードはパターンの重要な構成情報でした。これは、実行の構成オプションの一部である必要があります。
編集:ephemientによって指摘されているように、乱数ジェネレーターの内部状態は、その実装によってはシードよりも複雑な場合があります。