Visualización de la distribución gaussiana bivariada en Python

La distribución gaussiana (o distribución normal) es una de las distribuciones de probabilidad más fundamentales de la naturaleza. Desde su aparición en la vida diaria hasta sus aplicaciones en técnicas de aprendizaje estadístico, es uno de los descubrimientos matemáticos más profundos jamás realizados. Este artículo avanzará hacia la distribución multidimensional y obtendrá una comprensión intuitiva de la distribución normal bivariada.

El beneficio de cubrir la distribución bivariada es que podemos ver y comprender visualmente usando gráficos geométricos apropiados. Además, los mismos conceptos aprendidos a través de la distribución bivariada se pueden extender a cualquier número de dimensiones. Primero cubriremos brevemente los aspectos teóricos de la distribución y haremos un análisis exhaustivo de los diversos aspectos de la misma, como la array de covarianza y la función de densidad en Python.

Función de densidad de probabilidad (o función de densidad o PDF) de una distribución gaussiana bivariada

La función de densidad describe la probabilidad relativa de una variable aleatoria  X     en una muestra dada. Si el valor es alto alrededor de una muestra dada, eso significa que la variable aleatoria probablemente tomará ese valor cuando se muestree al azar. Responsable de su característica «forma de campana», la función de densidad de una variable aleatoria gaussiana bivariada dada  X     se define matemáticamente como:

f_X(x) = \frac{1}{{ \sqrt {2\pi|\Sigma| }}} exp\begin{pmatrix}\frac{-(x-\mu)^T \Sigma^{-1}(x-\mu)}{2} \end{pmatrix}

Donde  x        es cualquier vector de entrada  \in \mathbb{R^2}         mientras que los símbolos  \mu        y  \Sigma        tienen su significado habitual.

La función principal utilizada en este artículo es la función scipy.stats.multivariate_normal de la utilidad Scipy fora.

Sintaxis: scipy.stats.multivariate_normal(mean=Ninguno, cov=1)

Parámetros no opcionales:

  • media: una array Numpy que especifica la media de la distribución
  • cov: una array Numpy que especifica una array de covarianza definida positiva
  • semilla: una semilla aleatoria para generar resultados reproducibles

Devuelve: un objeto de variable aleatoria normal multivariante scipy.stats._multivariate.multivariate_normal_gen object. Algunos de los métodos del objeto devuelto que son útiles para este artículo son los siguientes:

  • pdf(x): Devuelve el valor de la función de densidad en el valor ‘x’
  • rvs (tamaño): extrae el número de muestras de ‘tamaño’ de la distribución gaussiana multivariante generada

Una vista «visual» de la array de covarianza

La array de covarianza es quizás uno de los componentes más ingeniosos de una distribución gaussiana bivariada. Cada elemento de la array de covarianza define la covarianza entre cada par subsiguiente de variables aleatorias. La covarianza entre dos variables aleatorias  X_1        y  X_2        se define matemáticamente como   \sigma(X_1,X_2) = \mathop{\mathbb{E}}[(X_1-\mathop{\mathbb{E}}[X_1])(X_2-\mathop{\mathbb{E}}[X_2])]        donde  \mathop{\mathbb{E}}[X]       denota el valor esperado de una variable aleatoria dada  X  . Intuitivamente hablando, al observar los elementos diagonales de la array de covarianza podemos imaginar fácilmente el contorno trazado por las dos variables aleatorias gaussianas en 2D. Así es cómo:

Los valores presentes en la diagonal derecha representan la covarianza conjunta entre dos componentes de las correspondientes variables aleatorias. Si el valor es +ve, eso significa que hay una covarianza positiva entre las dos variables aleatorias, lo que significa que si vamos en una dirección donde  x_1       aumenta,  x_2       también aumentará en esa dirección y viceversa. De manera similar, si el valor es negativo, eso significa  x_2       que disminuirá en la dirección de un aumento en  x_1      .

A continuación se muestra la implementación de la array de covarianza:

En los siguientes fragmentos de código, generaremos 3 distribuciones bivariadas gaussianas diferentes con la misma media  \mu = \begin{bmatrix}0\\[1ex]0\end{bmatrix}     pero diferentes arrays de covarianza: 

  1. Array de covarianza con -ve covarianza = \begin{bmatrix}1&-0.8 \\[1ex] -0.8&1 \end{bmatrix}
  2. Array de covarianza con 0 covarianza = \begin{bmatrix}1&0 \\[1ex] 0&1 \end{bmatrix}
  3. Array de covarianza con +ve covarianza = \begin{bmatrix}1&0.8 \\[1ex] 0.8&1 \end{bmatrix}

Python

# Importing the necessary modules
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
 
 
plt.style.use('seaborn-dark')
plt.rcParams['figure.figsize']=14,6
 
# Initializing the random seed
random_seed=1000
 
# List containing the variance
# covariance values
cov_val = [-0.8, 0, 0.8]
 
# Setting mean of the distributino to
# be at (0,0)
mean = np.array([0,0])
 
# Iterating over different covariance
# values
for idx, val in enumerate(cov_val):
    plt.subplot(1,3,idx+1)
     
    # Initializing the covariance matrix
    cov = np.array([[1, val], [val, 1]])
     
    # Generating a Gaussian bivariate distribution
    # with given mean and covariance matrix
    distr = multivariate_normal(cov = cov, mean = mean,
                                seed = random_seed)
     
    # Generating 5000 samples out of the
    # distribution
    data = distr.rvs(size = 5000)
     
    # Plotting the generated samples
    plt.plot(data[:,0],data[:,1], 'o', c='lime',
             markeredgewidth = 0.5,
             markeredgecolor = 'black')
    plt.title(f'Covariance between x1 and x2 = {val}')
    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.axis('equal')
     
plt.show()

Producción:

Muestras generadas para diferentes arrays de covarianza

¡Podemos ver que la salida del código ha cumplido con éxito nuestras pruebas teóricas! Tenga en cuenta que el valor 0,8 se tomó solo por conveniencia. El lector puede jugar con diferentes magnitudes de covarianza y esperar resultados consistentes.

Vista 3D de la función de densidad de probabilidad:

Ahora podemos pasar a uno de los aspectos más interesantes y característicos de la distribución gaussiana bivariada, ¡la función de densidad! La función de densidad es responsable de la forma de campana característica de la distribución.

Python

# Importing the necessary modules
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
 
 
plt.style.use('seaborn-dark')
plt.rcParams['figure.figsize']=14,6
fig = plt.figure()
 
# Initializing the random seed
random_seed=1000
 
# List containing the variance
# covariance values
cov_val = [-0.8, 0, 0.8]
 
# Setting mean of the distributino
# to be at (0,0)
mean = np.array([0,0])
 
# Storing density function values for
# further analysis
pdf_list = []
 
# Iterating over different covariance values
for idx, val in enumerate(cov_val):
     
    # Initializing the covariance matrix
    cov = np.array([[1, val], [val, 1]])
     
    # Generating a Gaussian bivariate distribution
    # with given mean and covariance matrix
    distr = multivariate_normal(cov = cov, mean = mean,
                                seed = random_seed)
     
    # Generating a meshgrid complacent with
    # the 3-sigma boundary
    mean_1, mean_2 = mean[0], mean[1]
    sigma_1, sigma_2 = cov[0,0], cov[1,1]
     
    x = np.linspace(-3*sigma_1, 3*sigma_1, num=100)
    y = np.linspace(-3*sigma_2, 3*sigma_2, num=100)
    X, Y = np.meshgrid(x,y)
     
    # Generating the density function
    # for each point in the meshgrid
    pdf = np.zeros(X.shape)
    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            pdf[i,j] = distr.pdf([X[i,j], Y[i,j]])
     
    # Plotting the density function values
    key = 131+idx
    ax = fig.add_subplot(key, projection = '3d')
    ax.plot_surface(X, Y, pdf, cmap = 'viridis')
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.title(f'Covariance between x1 and x2 = {val}')
    pdf_list.append(pdf)
    ax.axes.zaxis.set_ticks([])
 
plt.tight_layout()
plt.show()
 
# Plotting contour plots
for idx, val in enumerate(pdf_list):
    plt.subplot(1,3,idx+1)
    plt.contourf(X, Y, val, cmap='viridis')
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.title(f'Covariance between x1 and x2 = {cov_val[idx]}')
plt.tight_layout()
plt.show()

Producción:

1) Gráfico de la función de densidad

Funciones de densidad correspondientes a diferentes arrays de covarianza

2) Gráfico de contornos

Contornos de las funciones de densidad

Como podemos ver, los contornos de la función de densidad coinciden exactamente con las muestras dibujadas por nosotros en la sección anterior. Tenga en cuenta que el límite de 3 sigma (concluido a partir de la regla 68-95-99.7) garantiza la máxima cobertura de muestra para la distribución definida. Como se mencionó anteriormente, el lector puede jugar con diferentes límites y esperar resultados consistentes.

Conclusión

Entendimos las diversas complejidades detrás de la distribución bivariada gaussiana a través de una serie de gráficos y verificamos los resultados teóricos con los hallazgos prácticos usando Python. ¡Se anima al lector a jugar con los fragmentos de código para obtener una intuición mucho más profunda sobre esta distribución mágica!

Publicación traducida automáticamente

Artículo escrito por adityasaini70 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

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