En écrivant un script, j'ai découvert la fonction numpy.random.choice. Je l'ai mis en œuvre parce que c'était beaucoup plus propre que l'équivalent si la déclaration. Cependant, après avoir exécuté le script, j'ai réalisé qu'il est Ce qui suit est un MWE. La première méthode prend 0,0 s, tandis que la seconde prend 7,2 s. Si vous échouez à la boucle i em>, vous verrez à quel point Random.choice ralentit. P> Quelqu'un peut-il commenter pourquoi aléatoire.choice est tellement plus lent? P>
4 Réponses :
Vous l'utilisez mal. Vectorisez sur l'opération ou NUMPY n'offrira aucun avantage:
>>> timeit.timeit('''numpy.random.choice([-1, 0, 1],
... size=1000,
... p=[0.25, 0.5, 0.25])''',
... 'import numpy', number=10000)
2.380380242513752
>>> timeit.timeit('''
... var = []
... for i in xrange(1000):
... tmp = rand.rand()
... if tmp < 0.25:
... var.append(1)
... elif tmp < 0.5:
... var.append(-1)
... else:
... var.append(0)''',
... setup='import numpy.random as rand', number=10000)
5.673041396894519
Comme écrit, comparez-vous des pommes aux pommes? Le premier calcule 10 ^ 3 * 10 ^ 4 = 10 ^ 7 nombres aléatoires, mais le second calcule 10 ^ 2 * 10 ^ 3 * 10 ^ 4 = 10 ^ 9 nombres aléatoires, non?
Je soupçonne la généralité de Une vectorisation brute de la version code> si code> est: p> exécuté dans donc pour le np.random.choice code> le ralentit, plus pour de petits échantillons que les grands. ipython code> i get: p > 1000 code> taille, le choix code> est de 3-4x plus lent, mais avec des vecteurs plus grands, la différence commence à disparaître. p> p>
Il m'a fallu très longtemps pour comprendre que mon générateur de données est très lent en raison de l'échantillonnage de clé aléatoire via Si la distribution non uniforme est remplacer p> avec p> qui donne une vitesse de x60. p> p> np.random.choice code>.
Hmm; intéressant. Une idée de la raison pour laquelle cela rend une telle différence à la vitesse? De source , votre expansion La version ne regarde pas si i> différente de quel engourdissement fait déjà.
Ah, après quelques tests, je soupçonne la principale cause de la différence de chronométrage que vous constatez est que vous utilisez une liste de la liste python code> en entrée et np.random.choice Code> Convertit implicitement qu'en premier, lorsque votre deuxième version de get_random_key code> évite cette conversion. C'est la conversion liste-to-tableau qui devient le goulot d'étranglement pour les grandes listes. Lorsque je teste les deux variantes sur un tableau 1D Numpy Array i> de 10 ** 6 éléments (plutôt qu'une liste), les horaires sont beaucoup plus proches pour moi: la deuxième version est d'environ 50% plus rapide.
Cette solution avec un score cumulatif est d'environ 25 fois plus vite: exécuté i get: p>
Petit refactoring: python def rapide_choice (options, probs): x = aléatoire.random () # np.random.rand () cum = 0 pour i, p en énumérable (probs): cum + = p if x < Cum: options de retour [i] Options de retour [-1] code>
Ce n'est pas vraiment une comparaison juste. Chaque fois, NUMPY doit prendre la somme cumulative de la liste P, la mettre dans un nouveau vecteur, puis itérer sur elle. Vous faites efficacement le prétraitement en sachant qu'il n'y a que trois variables et que la somme des premier et troisième est .5. Au-delà de cela, comme indiqué ci-dessous, NUMPY est optimisé pour des opérations vectorisées, et non pour effectuer une seule opération simple des milliers de fois.
En outre, utilisez
TimeIt code>, pasheure code> seul.Voir non répétitif-numéros aléatoire-numppy Pour certains truts pour choisir 40000 sur 10000 ^ 2 en numpopique 1.8.1.