python - ¿Cómo obtener una distribución normal dentro de un rango en numpy?
random machine-learning (4)
Además de la sugerencia @bakkal (+1), es posible que desee echar un vistazo a la receta de Vincent Mazet para lograr esto, reescrita como módulo py-rtnorm por Christoph Lassner .
En la tarea de aprendizaje automático.
Deberíamos obtener un grupo de distribución normal aleatoria de wrt con límite.
Podemos obtener un número de distribución normal con
np.random.normal()
pero no ofrece ningún parámetro enlazado.
Quiero saber como hacer eso?
La
parametrización de
truncnorm
es complicada
, así que aquí hay una función que traduce la parametrización a algo más intuitivo:
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)
¿Cómo usarlo?
-
Instale el generador con los parámetros: media , desviación estándar y rango de truncamiento :
>>> X = get_truncated_normal(mean=8, sd=2, low=1, upp=10)
-
Luego, puede usar X para generar un valor:
>>> X.rvs() 6.0491227353928894
-
O, una matriz numpy con N valores generados:
>>> 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 ejemplo visual
Aquí está la gráfica de tres distribuciones normales truncadas diferentes:
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()
Si está buscando la
distribución normal truncada
, SciPy tiene una función llamada
truncnorm
La forma estándar de esta distribución es una normal estándar truncada al rango [a, b]. Observe que a y b se definen sobre el dominio de la normal estándar. Para convertir valores de clip para una media específica y desviación estándar, use:
a, b = (myclip_a - my_mean) / my_std, (myclip_b - my_mean) / my_std
truncnorm toma ayb como parámetros de forma.
>>> 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])
El ejemplo anterior está limitado por -2 y 2 y devuelve 10 variables aleatorias (utilizando el método
.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
Aquí hay un diagrama de histograma para -6, 6:
Si solo quieres trabajar con
numpy
, también puedes hacer algo como esto:
int(np.clip(int(np.random.normal(mean,std)),min_size,max_size)
Esto solo recortará valores cada vez más pequeños a su
min
y
max
especificados