web-dev-qa-db-fra.com

Comment obtenir une distribution normale dans une plage de numpy?

En tâche d'apprentissage automatique. Nous devrions obtenir un groupe de distribution normale aléatoire aléatoire avec borne. Nous pouvons obtenir un numéro de distribution normal avec np.random.normal() mais il n'offre aucun paramètre lié. Je veux savoir comment faire ça?

26
maple

La paramétrisation de truncnorm est compliquée , voici donc une fonction qui traduit la paramétrisation en quelque chose de plus intuitif:

from scipy.stats import truncnorm

def get_truncated_normal(mean=0, sd=1, low=0, upp=10):
    return truncnorm(
        (low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)


Comment l'utiliser?

  1. Instanciez le générateur avec les paramètres: moyenne, écart-type et plage de troncature:

    >>> X = get_truncated_normal(mean=8, sd=2, low=1, upp=10)
    
  2. Ensuite, vous pouvez utiliser X pour générer une valeur:

    >>> X.rvs()
    6.0491227353928894
    
  3. Ou, un tableau numpy avec N valeurs générées:

    >>> X.rvs(10)
    array([ 7.70231607,  6.7005871 ,  7.15203887,  6.06768994,  7.25153472,
            5.41384242,  7.75200702,  5.5725888 ,  7.38512757,  7.47567455])
    

Un exemple visuel

Voici l'intrigue de trois distributions normales tronquées différentes:

X1 = get_truncated_normal(mean=2, sd=1, low=1, upp=10)
X2 = get_truncated_normal(mean=5.5, sd=1, low=1, upp=10)
X3 = get_truncated_normal(mean=8, sd=1, low=1, upp=10)

import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, sharex=True)
ax[0].hist(X1.rvs(10000), normed=True)
ax[1].hist(X2.rvs(10000), normed=True)
ax[2].hist(X3.rvs(10000), normed=True)
plt.show()

enter image description here

37
toto_tico

Si vous recherchez la distribution normale tronquée , SciPy a une fonction appelée truncnorm

La forme standard de cette distribution est une normale standard tronquée à l'intervalle [a, b] - notez que a et b sont définis sur le domaine de la normale standard. Pour convertir les valeurs de clip pour une moyenne et un écart-type spécifiques, utilisez:

a, b = (myclip_a - my_mean)/my_std, (myclip_b - my_mean)/my_std

truncnorm prend a et b comme paramètres de forme.

>>> from scipy.stats import truncnorm
>>> truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10)
array([-1.83136675,  0.77599978, -0.01276925,  1.87043384,  1.25024188,
        0.59336279, -0.39343176,  1.9449987 , -1.97674358, -0.31944247])

L'exemple ci-dessus est délimité par -2 et 2 et renvoie 10 variables aléatoires (en utilisant la méthode .rvs())

>>> min(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
-1.9996074381484044
>>> max(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
1.9998486576228549

Voici un tracé d'histogramme pour -6, 6:

enter image description here

12
bakkal

En plus de la suggestion @bakkal (+1), vous voudrez peut-être également jeter un œil à la recette Vincent Mazet pour y parvenir, réécrite sous la forme py-rtnorm module by Christoph Lassner .

1
armatita