Saltar al contenido

Cómo especificar límites superior e inferior al usar numpy.random.normal

Comprende el código de forma correcta antes de usarlo a tu proyecto y si tdeseas aportar algo puedes dejarlo en los comentarios.

Parece que quieres una distribución normal truncada. Usando scipy, podrías usar scipy.stats.truncnorm para generar variaciones aleatorias a partir de tal 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()

ingrese la descripción de la imagen aquí

La figura superior muestra la distribución normal truncada, la figura inferior muestra la distribución normal con la misma media mu y desviación estándar sigma.

Encontré esta publicación mientras buscaba una forma de devolver una serie de valores muestreados 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 integrada “.rvs”.

Entonces, si desea 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. Usar el integrado será sustancialmente más rápido que hacer un bucle para recopilar muestras, especialmente para valores grandes de N.

En caso de que alguien quiera una solución usando solo numpy, aquí hay una implementación simple usando 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 use esto! asi es como no se debe hacer!! 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)

será definitivamente no dibujar una normal truncadacomo se puede ver en el siguiente histograma:

ingrese la descripción de la imagen aquí

Lo siento por eso, ¡espero que nadie haya resultado herido! Supongo que la lección es, no trates de emular a MacGyver en la codificación… Saludos,
Andrés

Tienes la opción de sostener nuestra labor dejando un comentario y puntuándolo te estamos eternamente agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *