Números aleatorios¶

Métodos potenciales de prospección, FCAG, 2023.

En esta notebook buscamos generar números al azar que siguen una distribución normal. Para ello primero debemos generar números que siguen una distribución uniforme.

$X \sim \mathrm{U}(0,1)$¶

Generamos números aleatorios que siguen una distribución uniforme en $[0,1]$ por medio del siguiente algoritmo (de la familia de los linear congruential generator):

  • Dar $x_0$.
  • Elegir $a,c,m$ apropiados.
  • $x_{j+1} = (ax_j+c)\,\text{mod}\,m.$
  • $\mathbf{x}\,/m.$

Para obtener $m$ números aleatorios, debemos elegir $a,c,m$ de forma tal que:

  • $c\neq 0$;
  • $c$ y $m$ no tienen factores en común;
  • $a-1$ es un múltiplo de $p$ por cada número primo $p$ que es un factor de $m$;
  • $a-1$ es un múltiplo de 4 si $m$ es un múltiplo de 4.

Para nuestro ejemplo utilizamos $x_0,a,c,m = 0,5,3,2^{10}$ para generar un secuencia de $m=1024$ números aleatorios.

X = []
for k in range(m):
    x = (a*x+c)%m
    X.append(x)
X = np.array(X)
X = X / m

Generamos los números aleatorios y graficamos un histograma:

X = Uniform(x0=0) # 1024 números aleatorios
plt.hist(X,...)

En numpy podemos utilizar np.random.uniform() para generar $X \sim \mathrm{U}(0,1)$.

$X \sim \mathcal{N}(0,1)$¶

Ya contamos con un algoritmo para generar números aleatorios que siguen una distribución uniforme. Ahora podemos programar un método para generar números aleatorios que siguen una distribución Gaussiana (Normal) de media $\mu=0$ y desviación estándar $\sigma=1$ (canónica) de densidad de probabilidad:

$$ f(x) = \dfrac{1}{\sqrt{2\pi}}e^{-{x^2}/2}.$$
  • Podemos utilizar este algoritmo para generar números $X^\prime \sim \mathcal{N}(\mu,\sigma)$ por medio de ${X}^{\prime}{\leftarrow}{\mu}+{\sigma}{X}$

Algoritmo polar method¶

    1. Generar dos números aleatorios $U_1,U_2$ de una distribución uniforme entre 0 y 1.
    1. Hacer $V_1=2U_1-1, V_2=2U_2-1$.
    1. Calcular $S=V_1^2+V_2^2$.
    1. Sí $S\geq 1$, volver al primer paso.
    1. $X_1=V_1\sqrt{-(2/S)\ln{S}}$ y $X_2=V_2\sqrt{-(2/S)\ln{S}}$ son dos números aleatorios que siguen una distribución normal canónica.
def Normal(size=1000):
    ...
    u1,u2 = np.random.uniform(0,1,size=2)    
    ...
    return X

Si queremos generar de a dos números aleatorios con nuestro código Uniform() podemos hacer así:

u1,u2 = Uniform(x=x0)[:2]
x0    = x0 + 1 # cambiamos el x0 para la próxima iteración

Aplicamos el polar method para calcular 1000 números aleatorios que siguen $\mathcal{N}(0,1)$. Graficamos luego un histograma para verificar.

X = Normal(size=1000) # ~ N(0,1)
plt.hist(X,...)

Por último, generamos 1000 números aleatorios que siguen una distribución $\mathcal{N}(\mu=10,\sigma=5)$. Graficamos el histograma para verificar.

mu, sigma = 10, 5
X = Normal(size=1000) # ~ N(0,1)
X = mu + sigma * X  # ~ N(mu,sigma)
plt.hist(X,...)

En numpy podemos utilizar np.random.normal() para generar $X \sim \mathcal{N}(0,1)$.

Eso es todo por hoy.

Referencias¶

  • Brandt, S. (2014). Data Analysis. Springer.