Conversion d’une dissortingbution uniforme en une dissortingbution normale

Comment convertir une dissortingbution uniforme (comme le font la plupart des générateurs de nombres aléatoires, par exemple entre 0.0 et 1.0) en une dissortingbution normale? Que faire si je veux un écart moyen et standard de mon choix?

L’ algorithme de Ziggurat est assez efficace pour cela, bien que la transformation de Box-Muller soit plus facile à mettre en œuvre à partir de rien (et pas trop lente).

Il y a beaucoup de méthodes:

  • Ne pas utiliser Box Muller. Surtout si vous dessinez beaucoup de chiffres gaussiens. Box Muller donne un résultat qui est bloqué entre -6 et 6 (en supposant une double précision. Les choses s’aggravent avec les flottants.). Et c’est vraiment moins efficace que les autres méthodes disponibles.
  • Ziggurat va bien, mais nécessite une recherche de table (et quelques ajustements spécifiques à la plate-forme en raison de problèmes de taille de cache)
  • Le ratio d’uniformes est mon préféré, seulement quelques ajouts / multiplications et un log 1/50 du temps (par exemple, regardez ici ).
  • Inverser le CDF est efficace (et négligé, pourquoi?), Vous avez des implémentations rapides disponibles si vous effectuez une recherche sur Google. Il est obligatoire pour les nombres quasi aléatoires.

Changer la dissortingbution d’une fonction à une autre implique d’utiliser l’inverse de la fonction souhaitée.

En d’autres termes, si vous visez une fonction de probabilité spécifique p (x), vous obtenez la dissortingbution en l’intégrant -> d (x) = intégrale (p (x)) et utilisez son inverse: Inv (d (x)) . Utilisez maintenant la fonction de probabilité aléatoire (qui a une dissortingbution uniforme) et convertissez la valeur du résultat par la fonction Inv (d (x)). Vous devriez obtenir des valeurs aléatoires avec la dissortingbution en fonction de la fonction que vous avez choisie.

C’est l’approche mathématique générique: en l’utilisant, vous pouvez maintenant choisir n’importe quelle fonction de probabilité ou de dissortingbution à condition d’avoir une approximation inverse ou bonne.

J’espère que cela a aidé et merci pour la petite remarque concernant l’utilisation de la dissortingbution et non la probabilité elle-même.

Voici une implémentation javascript utilisant la forme polaire de la transformation Box-Muller.

/* * Returns member of set with a given mean and standard deviation * mean: mean * standard deviation: std_dev */ function createMemberInNormalDissortingbution(mean,std_dev){ return mean + (gaussRandom()*std_dev); } /* * Returns random number in normal dissortingbution centering on 0. * ~95% of numbers returned should fall between -2 and 2 * ie within two standard deviations */ function gaussRandom() { var u = 2*Math.random()-1; var v = 2*Math.random()-1; var r = u*u + v*v; /*if outside interval [0,1] start over*/ if(r == 0 || r >= 1) return gaussRandom(); var c = Math.sqrt(-2*Math.log(r)/r); return u*c; /* todo: optimize this algorithm by caching (v*c) * and returning next time gaussRandom() is called. * left out for simplicity */ } 

Utilisez l’ entrée mathématique de mathworld de l’entrée du théorème de la limite centrale à votre avantage.

Générez n des nombres uniformément dissortingbués, additionnez-les, soustrayez n * 0,5 et vous obtenez la sortie d’une dissortingbution approximativement normale avec une moyenne égale à 0 et une variance égale à (1/12) * (1/sqrt(N)) (voir wikipedia sur les dissortingbutions uniformes pour ce dernier)

n = 10 vous donne quelque chose de moitié décent rapidement. Si vous voulez quelque chose de plus de la moitié décent, optez pour la solution Tylers (comme indiqué dans l’ entrée Wikipedia sur les dissortingbutions normales )

Je voudrais utiliser Box-Muller. Deux choses à ce sujet:

  1. Vous vous retrouvez avec deux valeurs par itération
    En règle générale, vous mettez une valeur en cache et renvoyez l’autre. Lors de l’appel suivant pour un exemple, vous retournez la valeur mise en cache.
  2. Box-Muller donne un Z-score
    Vous devez ensuite mettre à l’échelle le Z-score par écart-type et append la moyenne pour obtenir la valeur complète dans la dissortingbution normale.

Le module de bibliothèque Python standard aléatoire a ce que vous voulez:

Variable normale (mu, sigma)
Dissortingbution normale. mu est la moyenne et sigma est l’écart type.

Pour l’algorithme lui-même, regardez la fonction dans random.py dans la bibliothèque Python.

La saisie manuelle est ici

Où R1, R2 sont des nombres uniformes aléatoires:

DISTRIBUTION NORMALE, avec SD de 1: sqrt (-2 * log (R1)) * cos (2 * pi * R2)

C’est exact … pas besoin de faire toutes ces boucles lentes!

Il semble incroyable que je puisse append quelque chose après huit ans, mais dans le cas de Java, j’aimerais orienter les lecteurs vers la méthode Random.nextGaussian () , qui génère une dissortingbution gaussienne avec une moyenne de 0,0 et une déviation standard de 1.0.

Un simple ajout et / ou une multiplication changera la moyenne et l’écart type à vos besoins.

Je pense que vous devriez essayer ceci dans EXCEL: =norminv(rand();0;1) . Cela produira les nombres aléatoires qui devraient normalement être dissortingbués avec la moyenne nulle et la variance unitaire. “0” peut être fourni avec n’importe quelle valeur, de sorte que les nombres seront de la moyenne désirée, et en changeant “1”, vous obtiendrez la variance égale au carré de votre entrée.

Par exemple: =norminv(rand();50;3) cèdera aux nombres normalement dissortingbués avec MEAN = 50 VARIANCE = 9.

Q Comment convertir une dissortingbution uniforme (comme le font la plupart des générateurs de nombres aléatoires, par exemple entre 0.0 et 1.0) en une dissortingbution normale?

  1. Pour l’implémentation du logiciel, je connais quelques noms de générateurs aléatoires qui vous donnent une séquence aléatoire pseudo-uniforme dans [0,1] (Mersenne Twister, Générateur linéaire de Congruate). Appelons ça U (x)

  2. Il existe un domaine mathématique appelé théorie des probabilités. Première chose: Si vous voulez modéliser la RV avec la dissortingbution intégrale F, vous pouvez simplement essayer d’évaluer F ^ -1 (U (x)). En théorie, il a été prouvé que ce type de véhicule aura une dissortingbution intégrale F.

  3. L’étape 2 peut être applicable pour générer rv ~ F sans utiliser de méthodes de comptage lorsque F ^ -1 peut être dérivé analytiquement sans problème. (par exemple exp.dissortingbution)

  4. Pour modéliser la dissortingbution normale, vous pouvez coaguler y1 * cos (y2), où y1 ~ est uniforme dans [0,2pi]. et y2 est la dissortingbution relei.

Q: Que faire si je veux un écart moyen et standard de mon choix?

Vous pouvez calculer sigma * N (0,1) + m.

On peut montrer que ces décalages et ces échelles mènent à N (m, sigma)

Ceci est une implémentation de Matlab utilisant la forme polaire de la transformation Box-Muller :

Fonction randn_box_muller.m :

 function [values] = randn_box_muller(n, mean, std_dev) if nargin == 1 mean = 0; std_dev = 1; end r = gaussRandomN(n); values = r.*std_dev - mean; end function [values] = gaussRandomN(n) [u, v, r] = gaussRandomNValid(n); c = sqrt(-2*log(r)./r); values = u.*c; end function [u, v, r] = gaussRandomNValid(n) r = zeros(n, 1); u = zeros(n, 1); v = zeros(n, 1); filter = r==0 | r>=1; % if outside interval [0,1] start over while n ~= 0 u(filter) = 2*rand(n, 1)-1; v(filter) = 2*rand(n, 1)-1; r(filter) = u(filter).*u(filter) + v(filter).*v(filter); filter = r==0 | r>=1; n = size(r(filter),1); end end 

Et invoquer histfit(randn_box_muller(10000000),100); c’est le résultat: Boîte-Muller Matlab Histfit

De toute évidence, il est vraiment inefficace par rapport au randn intégré Matlab.

 function distRandom(){ do{ x=random(DISTRIBUTION_DOMAIN); }while(random(DISTRIBUTION_RANGE)>=dissortingbutionFunction(x)); return x; } 

Approximation:

 function rnd_snd() { return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1); } 

Voir http://www.protonfish.com/random.shtml