Que fait np.random.seed dans le code ci-dessous d'un didacticiel Scikit-Learn? Je ne connais pas très bien le générateur d’états aléatoires de NumPy, alors j’apprécierais vraiment l’explication d’un profane.
np.random.seed(0)
indices = np.random.permutation(len(iris_X))
np.random.seed(0)
rend les nombres aléatoires prévisibles
>>> numpy.random.seed(0) ; numpy.random.Rand(4)
array([ 0.55, 0.72, 0.6 , 0.54])
>>> numpy.random.seed(0) ; numpy.random.Rand(4)
array([ 0.55, 0.72, 0.6 , 0.54])
Avec la réinitialisation de la graine (à chaque fois), la série de chiffres même apparaîtra à chaque fois.
Si la graine aléatoire n'est pas réinitialisée, des nombres différents apparaissent à chaque appel:
>>> numpy.random.Rand(4)
array([ 0.42, 0.65, 0.44, 0.89])
>>> numpy.random.Rand(4)
array([ 0.96, 0.38, 0.79, 0.53])
Les nombres (pseudo-) aléatoires fonctionnent en commençant par un nombre (la graine), en le multipliant par un grand nombre, puis en prenant modulo de ce produit. Le nombre résultant est ensuite utilisé comme graine pour générer le prochain nombre "aléatoire". Lorsque vous définissez la graine (à chaque fois), il fait la même chose à chaque fois, en vous donnant les mêmes chiffres.
Si vous voulez des nombres apparemment aléatoires, ne définissez pas la graine. Si vous avez un code qui utilise des nombres aléatoires que vous souhaitez déboguer, il peut s'avérer très utile de définir la valeur de départ avant chaque exécution afin que le code répète les mêmes opérations à chaque fois que vous l'exécutez.
Pour obtenir le plus grand nombre de nombres aléatoires pour chaque exécution, appelez numpy.random.seed()
. Ceci fera en sorte que numpy attribue à la valeur de départ un nombre aléatoire obtenu à partir de /dev/urandom
ou de son analogue Windows ou, si aucun de ceux-ci n'est disponible, il utilisera l'horloge.
Si vous définissez np.random.seed(a_fixed_number)
chaque fois que vous appelez l'autre fonction aléatoire de numpy, le résultat sera le même:
>>> import numpy as np
>>> np.random.seed(0)
>>> perm = np.random.permutation(10)
>>> print perm
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0)
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0)
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0)
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0)
>>> print np.random.Rand(4)
[0.5488135 0.71518937 0.60276338 0.54488318]
>>> np.random.seed(0)
>>> print np.random.Rand(4)
[0.5488135 0.71518937 0.60276338 0.54488318]
Cependant, si vous l'appelez une seule fois et utilisez différentes fonctions aléatoires, les résultats seront toujours différents:
>>> import numpy as np
>>> np.random.seed(0)
>>> perm = np.random.permutation(10)
>>> print perm
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0)
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> print np.random.permutation(10)
[3 5 1 2 9 8 0 6 7 4]
>>> print np.random.permutation(10)
[2 3 8 4 5 1 0 6 9 7]
>>> print np.random.Rand(4)
[0.64817187 0.36824154 0.95715516 0.14035078]
>>> print np.random.Rand(4)
[0.87008726 0.47360805 0.80091075 0.52047748]
Comme indiqué ci-dessus, numpy.random.seed (0) définit la valeur de départ aléatoire sur 0. Les nombres pseudo-aléatoires que vous obtenez de manière aléatoire commenceront donc au même point. Cela peut être utile pour le débogage dans certains cas. Cependant, après quelques lectures, cela semble être la mauvaise façon de procéder, si vous avez des threads car ce n'est pas thread-safe.
from différences-entre-numpy-aléatoire-et-aléatoire-en-python :
Pour numpy.random.seed (), la principale difficulté est que ce n’est pas le cas thread-safe - c’est-à-dire qu’il est dangereux de l’utiliser si vous avez de nombreux fichiers threads d'exécution, car il n'est pas garanti que cela fonctionne si deux différents threads exécutent la fonction en même temps. Si vous n'utilisez pas de threads, et si vous pouvez raisonnablement vous attendre à ce que vous vous n’aurez pas besoin de réécrire votre programme de cette façon à l’avenir, numpy.random.seed () devrait convenir à des fins de test. S'il y a aucune raison de penser que vous pourriez avoir besoin de threads dans l’avenir, c’est beaucoup plus sûr à long terme de faire ce que suggéré, et de faire un local instance de la classe numpy.random.Random. Autant que je sache, random.random.seed () est thread-safe (ou du moins, je n'ai trouvé aucune preuve du contraire).
exemple de comment s'y prendre:
from numpy.random import RandomState
prng = RandomState()
print prng.permutation(10)
prng = RandomState()
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
peut donner:
[3 0 4 6 8 2 1 9 7 5]
[1 6 9 0 2 7 8 3 5 4]
[8 1 5 0 7 2 9 4 3 6]
[8 1 5 0 7 2 9 4 3 6]
Enfin, notez qu'il peut y avoir des cas où l'initialisation à 0 (par opposition à une valeur initiale ne contenant pas tous les bits 0) peut entraîner des distributions non uniformes pour quelques premières itérations en raison du fonctionnement de xor, mais cela dépend de l'algorithme , et est au-delà de mes préoccupations actuelles et de la portée de cette question.
Je l'ai utilisé très souvent dans les réseaux de neurones. Il est bien connu que lorsque nous commençons à former un réseau de neurones, nous initialisons les poids de manière aléatoire. Le modèle est formé à ces poids sur un jeu de données particulier. Après le nombre d'époques, vous obtenez un ensemble de poids formés.
Supposons maintenant que vous souhaitiez vous entraîner à nouveau à partir de zéro ou que vous souhaitiez transmettre le modèle à d'autres personnes afin de reproduire vos résultats. Les poids seront à nouveau initialisés à un nombre aléatoire qui sera pour la plupart différent des précédents. Les poids formés obtenus après le même nombre d’époques (en conservant les mêmes données et d’autres paramètres) seront identiques. Le problème est que votre modèle n’est plus reproductible, c’est-à-dire que chaque fois que vous formez votre modèle à partir de zéro, il vous fournit différents ensembles de poids. En effet, le modèle est initialisé par différents nombres aléatoires à chaque fois.
Que se passe-t-il si chaque fois que vous commencez à vous entraîner à partir de zéro, le modèle est initialisé avec le même ensemble de poids d’initialisation aléatoires? Dans ce cas, votre modèle pourrait devenir reproductible. Ceci est réalisé par numpy.random.seed (0). En mentionnant seed () à un numéro particulier, vous vous accrocherez toujours au même ensemble de nombres aléatoires.
Tous les nombres aléatoires générés après avoir défini une valeur de départ particulière sont les mêmes sur toutes les plates-formes/systèmes.
Une graine aléatoire spécifie le point de départ lorsqu'un ordinateur génère une séquence de nombres aléatoires.
Par exemple, supposons que vous souhaitiez générer un nombre aléatoire dans Excel (Remarque: Excel définit une limite de 9999 pour la valeur de départ). Si vous entrez un nombre dans la zone Random Seed au cours du processus, vous pourrez utiliser à nouveau le même ensemble de nombres aléatoires. Si vous avez saisi «77» dans la zone et «77» la prochaine fois que vous exécuterez le générateur de nombres aléatoires, Excel affichera le même ensemble de nombres aléatoires. Si vous tapez «99», vous obtiendrez un ensemble de chiffres entièrement différent. Mais si vous revenez à une valeur de départ de 77, vous obtiendrez le même ensemble de nombres aléatoires que vous avez commencé.
Par exemple, «prenez un nombre x, ajoutez 900 + x, puis soustrayez 52.» Pour que le processus puisse démarrer, vous devez spécifier un nombre de départ, x (le germe). Prenons le numéro de départ 77:
Ajoutez 900 + 77 = 977 Soustrayez 52 = 925 En suivant le même algorithme, le deuxième nombre «aléatoire» serait:
900 + 925 = 1825 Soustrayez 52 = 1773 Cet exemple simple suit un modèle, mais les algorithmes derrière la génération du numéro de l'ordinateur sont beaucoup plus compliqués.