Existe-t-il un moyen de savoir quelle graine Python utilisé pour amorcer son générateur de nombres aléatoires?
Je sais que je peux spécifier ma propre graine, mais je suis assez satisfait de la gestion de Python. Mais, je veux savoir quelle graine elle a utilisée, de sorte que si j'aime les résultats, je ' m dans une série particulière, je pourrais reproduire cette série plus tard. Si j'avais la graine utilisée, je le pourrais.
Si la réponse est que je ne peux pas, alors quelle est la meilleure façon de générer moi-même une graine? Je veux qu'ils soient toujours différents d'une course à l'autre --- Je veux juste savoir ce qui a été utilisé.
MISE À JOUR: oui, je veux dire random.random ()! erreur ... [titre mis à jour]
Il n'est pas possible de retirer la semence automatique du générateur. Je génère normalement des graines comme ceci:
seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)
De cette façon, il est basé sur le temps, donc chaque fois que vous exécutez le script (manuellement), il sera différent, mais si vous utilisez plusieurs générateurs, ils n'auront pas la même graine simplement parce qu'ils ont été créés presque simultanément.
L'état du générateur de nombres aléatoires n'est pas toujours simplement une graine. Par exemple, un PRNG sécurisé possède généralement un tampon d'entropie, qui est un bloc de données plus important.
Cependant, vous pouvez enregistrer et restaurer l'intégralité de l'état du générateur de nombres randon, afin de pouvoir reproduire ses résultats ultérieurement:
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()
Les résultats de getstate
peuvent, bien sûr, être décapés si vous souhaitez les enregistrer de manière persistante.
Vous pouvez sous-classer random.Random, réécrire la méthode seed () de la même manière python fait (v3.5 dans cet exemple) mais en stockant la valeur de départ dans une variable avant d'appeler 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
Si vous le testez, une première valeur aléatoire générée avec une nouvelle graine et une deuxième valeur générée en utilisant la même graine (avec la méthode get_seed () que nous avons créée) seront égales:
>>> rnd1 = Random()
>>> seed = rnd1.get_seed()
>>> v1 = rnd1.randint(1, 0x260)
>>> rnd2 = Random(seed)
>>> v2 = rnd2.randint(1, 0x260)
>>> v1 == v2
True
Si vous stockez/copiez l'énorme valeur de départ et essayez de l'utiliser dans une autre session, la valeur générée sera exactement la même.
Je voulais faire la même chose mais je n'ai pas pu obtenir la graine. Donc, je pensais que la graine est générée à partir du temps. J'ai créé ma graine en utilisant l'heure système et l'ai utilisée comme graine alors maintenant je sais quelle graine a été utilisée.
SEED = int(time.time())
random.seed(SEED)
Si vous "définissez" la valeur de départ à l'aide de random.seed(None)
, le randomiseur est automatiquement défini en fonction de l'heure système. Cependant, vous ne pouvez pas accéder à cette valeur, comme vous l'avez observé. Ce que je fais quand je veux randomiser mais que je sais toujours la graine est la suivante:
tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)
note: la raison pour laquelle je préfère cela à l'utilisation de time.time()
comme proposé par @Abdallah est parce que de cette façon le randseed est lisible par l'homme et immédiatement compréhensible, ce qui a souvent de gros avantages. Des composants de date et même des microsegments pourraient également être ajoutés au besoin.
Étant donné que personne n'a mentionné que généralement le meilleur échantillon aléatoire que vous pourriez obtenir dans n'importe quel langage de programmation est généré via le système d'exploitation, je dois fournir le code suivant:
random_data = os.urandom(8)
seed = int.from_bytes(random_data, byteorder="big")
c'est cryptographiquement sécurisé.
Source: https://www.quora.com/What-is-the-best-way-to-generate-random-seeds-in-python
avec une valeur 8, il semble produire environ le même nombre de chiffres que sys.maxsize
pour moi.
>>> int.from_bytes(os.urandom(8), byteorder="big")
17520563261454622261
>>> sys.maxsize
9223372036854775807
>>>
La graine est une variable interne dans le package aléatoire qui est utilisée pour créer le prochain nombre aléatoire. Lorsqu'un nouveau numéro est demandé, la valeur de départ est également mise à jour.
Je voudrais simplement utiliser 0 comme graine si vous voulez être sûr d'avoir les mêmes nombres aléatoires à chaque fois, ou rendre i configurable.
CorelDraw avait une fois un générateur de motifs aléatoires, qui a été initialisé avec une graine. Les modèles variaient considérablement pour différentes graines, donc la graine était une information de configuration importante du modèle. Cela devrait faire partie des options de configuration pour vos courses.
EDIT: Comme noté par l'éphémient, l'état interne d'un générateur de nombres aléatoires peut être plus complexe que la graine, selon sa mise en œuvre.