web-dev-qa-db-fra.com

Différences entre numpy.random et random.random dans Python

J'ai un gros script en Python. Je me suis inspiré du code des autres donc j'ai fini par utiliser le module numpy.random Pour certaines choses (par exemple pour créer un tableau de nombres aléatoires pris à partir d'une distribution binomiale) et à d'autres endroits j'utilise le module random.random.

Quelqu'un peut-il me dire les principales différences entre les deux? En regardant la page Web du document pour chacun des deux, il me semble que numpy.random A juste plus de méthodes, mais je ne sais pas en quoi la génération des nombres aléatoires est différente.

La raison pour laquelle je demande, c'est parce que j'ai besoin d'amorcer mon programme principal à des fins de débogage. Mais cela ne fonctionne que si j'utilise le même générateur de nombres aléatoires dans tous les modules que j'importe, est-ce correct?

De plus, j'ai lu ici, dans un autre article, une discussion sur le fait de NE PAS utiliser numpy.random.seed(), mais je n'ai pas vraiment compris pourquoi c'était une si mauvaise idée. J'apprécierais vraiment que quelqu'un m'explique pourquoi c'est le cas.

87
Laura

Vous avez déjà fait de nombreuses observations correctes!

À moins que vous ne souhaitiez amorcer les deux générateurs aléatoires, il est probablement plus simple à long terme de choisir un générateur ou l'autre.

Pour numpy.random.seed(), la principale difficulté est qu'elle n'est pas adaptée aux threads - c'est-à-dire qu'elle n'est pas sûre à utiliser si vous avez plusieurs threads d'exécution différents , car il n'est pas garanti de fonctionner si deux threads différents 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 n'ayez pas besoin de réécrire votre programme de cette façon à l'avenir, numpy.random.seed() devrait convenir. S'il y a une raison de soupçonner que vous pourriez avoir besoin de threads à l'avenir, il est beaucoup plus sûr à long terme de faire comme suggéré, et de créer une instance locale de la classe numpy.random.Random . Pour autant que je sache, random.random.seed() est thread-safe (ou du moins, je n'ai trouvé aucune preuve du contraire).

La bibliothèque numpy.random Contient quelques distributions de probabilité supplémentaires couramment utilisées dans la recherche scientifique, ainsi que quelques fonctions pratiques pour générer des tableaux de données aléatoires. La bibliothèque random.random Est un peu plus légère et devrait convenir si vous ne faites pas de recherche scientifique ou d'autres types de travaux en statistique.

Sinon, ils utilisent tous les deux la séquence de torsion de Mersenne pour générer leurs nombres aléatoires, et ils sont tous deux complètement déterministes - c'est-à-dire que si vous connaissez quelques informations clés, il est possible de prédire avec une certitude absolue quel numéro viendra ensuite . Pour cette raison, ni numpy.random ni random.random ne convient à aucune tilisations cryptographiques sérieuses . Mais parce que la séquence est très très longue, les deux sont parfaits pour générer des nombres aléatoires dans les cas où vous ne vous inquiétez pas des personnes qui essaient de rétro-concevoir vos données. C'est aussi la raison de la nécessité de semer la valeur aléatoire - si vous commencez au même endroit à chaque fois, vous obtiendrez toujours la même séquence de nombres aléatoires!

En remarque, si vous avez besoin d'aléatoire de niveau cryptographique, vous devez utiliser le module secrets , ou quelque chose comme - Crypto.Random si vous utilisez une version Python antérieure à Python 3.6.

104
Hannele

De Python for Data Analysis , le module numpy.random complète le Python random avec des fonctions pour générer efficacement des tableaux entiers de valeurs d'échantillons à partir de nombreux types de distributions de probabilités.

En revanche, le module random intégré de Python n'échantillonne qu'une valeur à la fois, tandis que numpy.random peut générer un échantillon très volumineux plus rapidement. Utilisation de la fonction magique IPython %timeit on peut voir quel module fonctionne plus rapidement:

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop
11
lmiguelvargasf

La source de la graine et le profil de distribution utilisé vont affecter les sorties - si vous recherchez un caractère aléatoire cryptographique, l'amorçage à partir de os.urandom () obtiendra des octets aléatoires presque réels à partir du bavardage de l'appareil (c'est-à-dire Ethernet ou disque) (ie/dev/random sur BSD)

cela vous évitera de donner une graine et donc de générer des nombres aléatoires déterministes. Cependant, les appels aléatoires vous permettent ensuite d'ajuster les nombres à une distribution (ce que j'appelle un aléa scientifique - finalement, tout ce que vous voulez est une distribution en courbe en cloche de nombres aléatoires, numpy est le meilleur pour atténuer cela.

Alors oui, restez avec un seul générateur, mais décidez quel aléatoire vous voulez - aléatoire, mais à coup sûr à partir d'une courbe de distrubtuion, ou aussi aléatoire que possible sans appareil quantique.

3