Numpy Fonctions Pures pour la performance, la mise en cache
Je suis en train d'écrire quelques modérément critique pour les performances du code de numpy.
Ce code sera à l'intérieur de la plupart de boucle, d'un calcul que la course du temps est mesurée en heures.
Un rapide calcul suggèrent que ce code sera exécuté jusqu'à quelque chose comme 10^12 fois, dans certaines variantes du calcul.
Donc la fonction est de calculer sigmoïde(X) et une autre pour calculer sa dérivée (gradient).
Sigmoïde a la propriété que pour
y=sigmoïde(x), dy/dx= y(1-y)
En python pour numpy cela ressemble à:
sigmoid = vectorize(lambda(x): 1.0/(1.0+exp(-x)))
grad_sigmoid = vectorize(lambda (x): sigmoid(x)*(1-sigmoid(x)))
Comme on peut le voir, les deux fonctions sont de pures (sans effets secondaires),
donc, ils sont des candidats idéaux pour memoization,
au moins pour le court terme, j'ai quelques inquiétudes sur la mise en cache chaque appel à sigmoïde jamais fait: Stockage de 10^12 flotteurs qui prendrait plusieurs téra-octets de RAM.
Est-il un bon moyen d'optimiser ce?
Va python ramasser que ce sont des pures fonctions et les mettre en cache pour moi, comme il convient?
Suis-je à vous soucier de rien?
1/(1+np.exp(-x))
accepte d'ores et déjà numpy des tableaux d'entrée et il est vraiment rapide (j'imagine memoization ne va pas aider du tout). En utilisant vectorize
, vous êtes le rendant beaucoup plus lent, mais, depuis qu'il est mis en œuvre à l'aide de slow pour les boucles.Quelle est la taille de x?
varie, mais j'ai pris pour ma règle de tumb calculs, x est le plus souvent un vecteur de longueur 100.
OriginalL'auteur Lyndon White | 2014-01-14
Vous devez vous connecter pour publier un commentaire.
Ces fonctions existent déjà dans scipy. La fonction sigmoïde est disponible en
scipy.spécial.expit
.Comparer
expit
à la vectorisé fonction sigmoïde:expit
est également plus rapide que la mise en œuvre de la formule de vous-même:Le CDF de la logistique de distribution est la fonction sigmoïde. Il est disponible en tant que
cdf
méthode descipy.stats.logistic
, maiscdf
appelle éventuellementexpit
, donc il n'y a pas de point à l'aide de cette méthode. Vous pouvez utiliser lepdf
méthode pour calculer la dérivée de la fonction sigmoïde, ou le_pdf
méthode qui a moins de frais généraux, mais "rolling" est plus rapide:Timing (x est de longueur 1001):
Être prudent avec votre application si vous allez utiliser les valeurs qui sont loin dans la queue. La fonction exponentielle peut débordement assez facilement.
logistic._cdf
est un peu plus robuste que mon rapidité de mise en œuvre desigmoid_grad
:Une mise en œuvre à l'aide de
sech**2
(1/cosh**2
) est un peu plus lent que le ci-dessussigmoid_grad
:Mais elle gère les queues de mieux:
Oui,
._pdf()
a moins d'erreurs et de vérification des arguments. Il également ne pas utiliser leloc
(emplacement) etscale
paramètres de la distribution, de celles qui sont traitées dans le.pdf()
méthode..pdf()
appelle éventuellement._pdf()
pour faire le calcul.OriginalL'auteur Warren Weckesser
Juste élargissement sur mon commentaire, voici un comparatif entre votre sigmoïde par
vectorize
et l'utilisation de numpy directement:Comme vous pouvez le voir, pas seulement
vectorize
rendre beaucoup plus lent, le fait est que vous pouvez calculer 10000 sigmoids dans 250 microsecondes (qui est, de 25 nanosecondes pour chaque). Un seul dictionnaire de recherche en Python est plus lente que celle, sans parler de tous les autres code pour obtenir la memoization en place.La seule façon d'optimiser, ce qui je pense est de l'écriture d'une sigmoïde ufunc pour numpy, qui, fondamentalement, permettra de mettre en œuvre l'opération dans C. de Cette façon, vous n'aurez pas à faire de chaque opération dans le sigmoïde à l'ensemble de la matrice, même si numpy est-ce réellement rapide.
OriginalL'auteur Gustav Larsson
Si vous êtes à la recherche d'memoize ce processus, j'avais envelopper ce code dans une fonction, et décorer avec des
functools.lru_cache(maxsize=n)
. Expérience avec lemaxsize
valeur pour trouver la taille appropriée pour votre application. Pour de meilleurs résultats, utilisez unmaxsize
argument qui est une puissance de deux.Si vous êtes sur 2.7 (que j'attends de vous, puisque vous êtes à l'aide de numpy), vous pouvez prendre un coup d'oeil à https://pypi.python.org/pypi/repoze.lru/ pour un memoization de la bibliothèque avec la même syntaxe.
Vous pouvez l'installer via pip:
pip install repoze.lru
Bon appel -- j'ai ajouté dans un 2.7 alternative à ma réponse.
OriginalL'auteur Madison May
Surtout je suis d'accord avec Warren Weckesser et sa réponse ci-dessus.
Mais pour les dérivés du sigmoïde au suivant peut être utilisé:
Horaires:
Le seul problème est la précision:
OriginalL'auteur Sklavit