La meilleure façon d'écrire une fonction Python qui intègre une gaussienne?
En tentant d'utiliser scipy du quad méthode pour intégrer une gaussienne (disons il y a une méthode gaussienne nommé gauss), j'ai eu des problèmes en passant les paramètres nécessaires à gauss et en laissant quad pour faire de l'intégration sur la bonne variable. Quelqu'un aurait-il un bon exemple de comment utiliser quad w/multidimensionnelle de la fonction?
Mais ce qui m'a conduit à une plus grande question à propos de la meilleure façon d'intégrer une gaussienne en général. Je n'ai pas trouvé une gaussienne intégrer dans scipy (à ma grande surprise). Mon plan était d'écrire une simple fonction gaussienne et la transmettre à la quad (ou peut-être maintenant une largeur fixe de l'intégrateur). Que feriez-vous?
Edit: largeur Fixe qui signifie quelque chose comme trapz qui utilise un fixe dx pour calculer les aires sous la courbe.
De ce que j'ai à ce jour est une méthode___gauss qui retourne une fonction lambda qui peuvent aller en quad. De cette façon, je peux faire une fonction normale avec la moyenne et la variance j'ai besoin avant de les intégrer.
def make_gauss(N, sigma, mu):
return (lambda x: N/(sigma * (2*numpy.pi)**.5) *
numpy.e ** (-(x-mu)**2/(2 * sigma**2)))
quad(make_gauss(N=10, sigma=2, mu=0), -inf, inf)
Quand j'ai essayé le passage d'un général de la fonction gaussienne (qui doit être appelée avec x, N, mu et sigma) et en remplissant certaines valeurs à l'aide de quad comme
quad(gen_gauss, -inf, inf, (10,2,0))
les paramètres 10, 2, et 0 ne correspondent PAS nécessairement à N=10, sigma=2, mu=0, ce qui a suscité le plus de la définition étendue.
L'erf(z) dans scipy.spécial m'obligerait à définir exactement ce que t est d'abord, mais il est agréable de savoir qu'il est là.
- Une distribution gaussienne de chiffres ou de données. Il ressemble à bosse ou "courbe en cloche" si tracées.
- Familièrement, gaussien est utilisé comme un nom pour représenter une courbe de gauss ou de la distribution (c'est assez courant dans l'entrée de Wikipedia par exemple). Je suppose que nous devrions écrire avec la capitalisation trop, mais c'est assez parlé place, non?
- Une gaussienne est une gaussienne est une gaussienne, n'importe quel nom qu'il modifie. Fermer avec le stupide sémantique des arguments qui n'ajoutent rien.
- La fonction scipy.les stats.norme.cdf calcule votre intégrale.
Vous devez vous connecter pour publier un commentaire.
Bon, vous avez l'air d'être assez confus au sujet de plusieurs choses. Commençons par le début: vous avez parlé d'un "multidimensionnel de la fonction", mais pour discuter de l'habituelle d'une variable Gaussienne. C'est pas multidimensionnelle de la fonction: lorsque vous intégrez, vous intégrer une variable (x). La distinction est importante à faire, parce qu'il n'y est un monstre appelé une "distribution Gaussienne multivariée", qui est un véritable multidimensionnelle de la fonction et, si elle est intégrée, nécessite l'intégration de plus de deux ou plusieurs variables (qui utilise le cher technique de Monte Carlo je l'ai mentionné avant). Mais tu sembles parler d'ordinaire d'une variable Gaussienne, ce qui est beaucoup plus facile de travailler avec, de les intégrer et de tout ce qui.
Une variable Gaussienne de la distribution a deux paramètres,
sigma
etmu
, et est une fonction d'une seule variable que nous allons désignerx
. Vous semblent également avoir une normalisation paramètren
(ce qui est utile dans une couple d'applications). La normalisation des paramètres sont généralement pas inclus dans les calculs, puisque vous pouvez simplement ajouter que les ramener dans à la fin (rappelez-vous, l'intégration est un opérateur linéaire:int(n*f(x), x) = n*int(f(x), x)
). Mais on peut le transporter partout si vous le souhaitez; la mention j'aime pour une distribution normale est alorsN(x | mu, sigma, n) := (n/(sigma*sqrt(2*pi))) * exp((-(x-mu)^2)/(2*sigma^2))
(lire ainsi: "la distribution normale de
x
donnésigma
,mu
, etn
est donnée par..."), Donc bon; il correspond à la fonction que vous avez. Notez que la seule vrai variable ici estx
: les trois autres paramètres sont fixe pour une Gaussienne.Maintenant pour une mathématique: il est prouvable vrai que tous les Gaussien courbes ont la même forme, ils sont juste changé un petit peu. On peut travailler avec des
N(x|0,1,1)
, appelé la "distribution normale standard", et vient de traduire nos résultats à la générale de la courbe de Gauss. Donc, si vous avez l'intégrale deN(x|0,1,1)
, vous pouvez trivialement le calcul de l'intégrale de Gauss. Cette intégrale apparaît si souvent qu'il a un nom spécial: la de la fonction d'erreurerf
. En raison de certaines conventions anciennes, il n'est pas exactementerf
; il ya un couple additif et multiplicatif facteurs également menées autour de.Si
Phi(z) = integral(N(x|0,1,1), -inf, z)
; c'est,Phi(z)
est l'intégrale de la distribution normale standard de moins l'infini jusqu'àz
, c'est vrai, par la définition de la fonction d'erreur quePhi(z) = 0.5 + 0.5 * erf(z /sqrt(2))
.De même, si
Phi(z | mu, sigma, n) = integral( N(x|sigma, mu, n), -inf, z)
; c'est,Phi(z | mu, sigma, n)
est l'intégrale de la distribution normale des paramètres donnésmu
,sigma
, etn
de moins l'infini jusqu'àz
, c'est vrai, par la définition de la fonction d'erreur quePhi(z | mu, sigma, n) = (n/2) * (1 + erf((x - mu) /(sigma * sqrt(2))))
.Prendre un coup d'oeil à l'article de Wikipedia sur la normale de la CDF si vous voulez plus de détails ou une preuve de ce fait.
Ok, ça devrait être assez d'explication de fond. De retour à votre (édité) poste. Vous dites "L'erf(z) dans scipy.spécial m'obligerait à définir exactement ce que t est d'abord". Je n'ai aucune idée de ce que tu veux dire par là, d'où vient
t
(le temps?) entrez dans ce tout? Espérons que l'explication ci-dessus a permis de démystifier la fonction d'erreur un peu et c'est plus clair maintenant pourquoi la fonction d'erreur est le droit de la fonction pour le travail.Votre code Python est OK, mais je préfère une fermeture de plus d'un lambda:
À l'aide d'une fermeture permet de précalcul des constantes
k
ets
, de sorte que le retour de la fonction aurez besoin de faire moins de travail chaque fois qu'il est appelé (ce qui peut être important si vous êtes à l'intégrer, ce qui signifie qu'il sera appelé à de nombreuses reprises). Aussi, j'ai évité toute utilisation de l'opérateur exponentiel**
, qui est plus lent que d'écrire la quadrature, et hissé le fossé de la boucle interne et l'a remplacée par une multiplication. Je n'ai pas regardé tous à leur mise en œuvre en Python, mais de mon dernier temps de réglage intérieure de la boucle de vitesse pure à l'aide de matières x87 assemblée, il me semble me rappeler que ajoute, soustrait, ou multiplie prendre environ 4 cycles de PROCESSEUR chacun, divise sur 36, et une puissance d'environ 200. C'était il y a quelques années, afin de prendre ces chiffres avec un grain de sel; il illustre leur relative complexité. Ainsi, le calcul deexp(x)
la force brute est une mauvaise idée; il y a des trucs que vous pouvez prendre lors de la rédaction d'une bonne mise en œuvre deexp(x)
qui font qu'il est beaucoup plus rapide et plus précis qu'un générala**b
style exponentiation.Je n'ai jamais utilisé le numpy version des constantes pi et e; j'ai toujours coincé avec le vieux ordinaire de mathématiques du module de versions. Je ne sais pas pourquoi vous préférerez peut-être l'un des deux.
Je ne suis pas sûr de ce que vous allez pour les
quad()
appel.quad(gen_gauss, -inf, inf, (10,2,0))
devrait intégrer un renormalisé Gaussien de moins l'infini à plus l'infini, et devrait toujours cracher 10 (votre facteur de normalisation), depuis la Gaussienne intègre à 1, la ligne réelle. Aucune réponse loin de 10 (je ne m'attends pas exactement 10 depuisquad()
n'est qu'une approximation, après tout) signifie que quelque chose est foiré quelque part... difficile de dire ce qui est vissé vers le haut, sans en connaître la réelle valeur de retour et, éventuellement, le fonctionnement interne dequad()
.Je l'espère, qui a dissipé la confusion, et a expliqué pourquoi la fonction d'erreur est le droit de réponse à votre problème, ainsi que la façon de tout faire vous-même si vous êtes curieux. Si l'un de mon explication n'était pas claire, je suggère de jeter un rapide coup d'oeil à Wikipedia en premier; si vous avez encore des questions, n'hésitez pas à demander.
make_gauss
.print quad(make_gauss(1,1,0),-np.inf,np.inf)
scipy est livré avec la "fonction d'erreur", aka intégrale Gaussienne:
Je suppose que vous êtes la manipulation de Gaussiennes multivariées; si oui, SciPy a déjà la fonction que vous recherchez: ça s'appelle MVNDIST ("d'une DISTribution Normale Multivariée). Le SciPy documentation est, comme toujours, terrible, donc je ne peux même pas trouver où la fonction est enterré, mais il est là quelque part. La documentation est facilement la pire partie de SciPy, et a frustré de moi à pas de fin dans le passé.
Seule variable Gaussiennes suffit d'utiliser la bonne vieille fonction d'erreur, dont de nombreuses implémentations sont disponibles.
Comme pour s'attaquer au problème en général, oui, comme James Thompson mentionne, vous voulez juste écrire votre propre distribution gaussienne de la fonction et de le nourrir pour quad(). Si vous pouvez éviter la généralisation de l'intégration, mais, c'est une bonne idée de le faire -- spécialisée techniques d'intégration d'une fonction particulière (comme MVNDIST utilisations) va être beaucoup plus rapide que la norme de Monte-Carlo multidimensionnelle de l'intégration, qui peut être très lent pour une grande précision.
La distribution gaussienne est également appelé à une distribution normale. Le cdf fonction dans le scipy norme module fait ce que vous voulez.
http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.norm.html#scipy.stats.norm
Pourquoi ne pas toujours faire de votre intégration à partir de -l'infini à +l'infini, de sorte que vous savez toujours la réponse? (blague!)
Ma conjecture est que la seule raison qu'il n'y a pas déjà une conserve fonction Gaussienne dans SciPy est que c'est une simple fonction à écrire. Votre suggestion sur l'écriture de votre propre fonction et de son passage à quad à intégrer des sons excellents. Il utilise le accepté SciPy outil pour faire cela, c'est un code minimal d'effort pour vous, et c'est très lisible pour d'autres personnes, même si elles ne l'avez jamais vu SciPy.
Que voulez-vous dire exactement par une largeur fixe intégrateur? Voulez-vous dire à l'aide d'un algorithme différent de ce que QUADPACK est l'aide?
Edit: Pour être complet, voici quelque chose comme ce que j'avais essayer pour une Gaussienne avec une moyenne de 0 et un écart type de 1 de 0 à +l'infini:
C'est un peu moche parce que la fonction Gaussienne est un peu long, mais encore assez trivial à écrire.