python - initialize - Cómo especificar los límites superior e inferior al usar numpy.random.normal
numpy random uniform (4)
IOK, por lo que quiero poder elegir valores de una distribución normal que solo caiga entre 0 y 1. En algunos casos, quiero básicamente devolver solo una distribución completamente aleatoria, y en otros casos quiero devolver valores que Caer en la forma de un gaussiano.
En este momento estoy usando la siguiente función:
def blockedgauss(mu,sigma):
while True:
numb = random.gauss(mu,sigma)
if (numb > 0 and numb < 1):
break
return numb
Escoge un valor de una distribución normal, luego lo descarta si cae fuera del rango 0 a 1, pero creo que debe haber una mejor manera de hacerlo.
En el caso de que alguien quiera una solución que use solo numpy, aquí hay una implementación simple que usa una función normal y un clip (el enfoque de MacGyver):
import numpy as np
def truncated_normal(mean, stddev, minval, maxval):
return np.clip(np.random.normal(mean, stddev), minval, maxval)
EDITAR: ¡NO uses esto! ¡Así es como no deberías hacerlo! por ejemplo,
a = truncated_normal(np.zeros(10000), 1, -10, 10)
puede parecer que funciona, pero
b = truncated_normal(np.zeros(10000), 100, -1, 1)
definitivamente no dibujará una normal truncada , como se puede ver en el siguiente histograma:
Lo siento, espero que nadie salga lastimado! Supongo que la lección es, no intentes emular a MacGyver en la codificación ... Saludos,
Andres
Encontré esta publicación mientras buscaba una manera de devolver una serie de valores muestreados a partir de una distribución normal truncada entre cero y 1 (es decir, probabilidades). Para ayudar a cualquier otra persona que tenga el mismo problema, solo quería señalar que scipy.stats.truncnorm tiene la capacidad incorporada ".rvs".
Entonces, si quisiera 100,000 muestras con una media de 0.5 y una desviación estándar de 0.1:
import scipy.stats
lower = 0
upper = 1
mu = 0.5
sigma = 0.1
N = 100000
samples = scipy.stats.truncnorm.rvs(
(lower-mu)/sigma,(upper-mu)/sigma,loc=mu,scale=sigma,size=N)
Esto da un comportamiento muy similar a numpy.random.normal, pero dentro de los límites deseados. El uso de la función incorporada será sustancialmente más rápido que el bucle para recopilar muestras, especialmente para valores grandes de N.
He hecho un script de ejemplo de la siguiente manera. Muestra cómo usar las API para implementar las funciones que queríamos, como generar muestras con parámetros conocidos, cómo calcular CDF, PDF, etc. También adjunto una imagen para mostrar esto.
#load libraries
import scipy.stats as stats
#lower, upper, mu, and sigma are four parameters
lower, upper = 0.5, 1
mu, sigma = 0.6, 0.1
#instantiate an object X using the above four parameters,
X = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
#generate 1000 sample data
samples = X.rvs(1000)
#compute the PDF of the sample data
pdf_probs = stats.truncnorm.pdf(samples, (lower-mu)/sigma, (upper-mu)/sigma, mu, sigma)
#compute the CDF of the sample data
cdf_probs = stas.truncnorm.cdf(samples, (lower-mu)/sigma, (upper-mu)/sigma, mu, sigma)
#make a histogram for the samples
plt.hist(samples, bins= 50,normed=True,alpha=0.3,label=''histogram'');
#plot the PDF curves
plt.plot(samples[samples.argsort()],pdf_probs[samples.argsort()],linewidth=2.3,label=''PDF curve'')
#plot CDF curve
plt.plot(samples[samples.argsort()],cdf_probs[samples.argsort()],linewidth=2.3,label=''CDF curve'')
#legend
plt.legend(loc=''best'')
Parece que quieres una distribución normal truncada . Usando scipy, podría usar scipy.stats.truncnorm
para generar variables aleatorias a partir de dicha distribución:
import matplotlib.pyplot as plt
import scipy.stats as stats
lower, upper = 3.5, 6
mu, sigma = 5, 0.7
X = stats.truncnorm(
(lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
N = stats.norm(loc=mu, scale=sigma)
fig, ax = plt.subplots(2, sharex=True)
ax[0].hist(X.rvs(10000), normed=True)
ax[1].hist(N.rvs(10000), normed=True)
plt.show()
La figura superior muestra la distribución normal truncada, la figura inferior muestra la distribución normal con la misma mu
media y la desviación estándar sigma
.