Saltar al contenido

# introduccion-a-la-estadistica-bayesiana-con-pymc

Introducción a la estadística bayesiana con PyMC

Volver a la portada del curso
Lectura (Markdown)

Configuración de Entorno

Sección 3 · PyMC: Introducción y Uso Básico

Un entorno que no se rompe a mitad del curso

La mayoría de los problemas con PyMC no aparecen en el modelo, sino antes: una versión de NumPy incompatible, un compilador ausente o un kernel de Jupyter que apunta a otro Python. Esta lección arma un entorno aislado, fija versiones y verifica que el muestreo funcione de punta a punta antes de escribir el primer modelo serio.

Las tres piezas y cómo encajan

Trabajar con PyMC implica tres bibliotecas con responsabilidades distintas:

  • PyMC: el lenguaje para declarar el modelo (priors, verosimilitud) y los algoritmos de muestreo.
  • PyTensor: construye el grafo computacional del modelo, calcula gradientes de forma automática y lo compila a código rápido (C, Numba o JAX).
  • ArviZ: guarda los resultados en un objeto InferenceData y ofrece diagnósticos y gráficas (az.summary, az.plot_trace).

Lo que PyMC calcula al final es la log-densidad posterior, salvo una constante, y su gradiente respecto a los parámetros:

$$\log p(\theta \mid y) = \log p(y \mid \theta) + \log p(\theta) - \log p(y)$$

El término $\log p(y)$ no depende de $\theta$, así que el muestreador lo ignora. PyTensor se encarga de derivar $\nabla_\theta \log p(\theta \mid y)$, que es justo lo que necesita NUTS. Por eso la calidad de la instalación de PyTensor afecta directamente la velocidad del curso.

Crear el entorno aislado

La documentación oficial recomienda conda con el canal conda-forge, porque resuelve de una vez las dependencias binarias (BLAS, compiladores). Si prefieres pip, usa siempre un venv dedicado. En este curso se fijan PyMC 5.x y ArviZ 0.x: las ramas nuevas (PyMC 6, ArviZ 1.x) cambian APIs y nombres de columnas que los notebooks usan.

# Opción recomendada (conda-forge):
# conda create -c conda-forge -n bayes "pymc<6" "arviz<1" nutpie jupyterlab
# conda activate bayes
#
# Alternativa con venv + pip:
# python -m venv .venv
# .venv\Scripts\activate          (Windows)  |  source .venv/bin/activate
# pip install "pymc<6" "arviz<1" nutpie jupyterlab ipykernel
# python -m ipykernel install --user --name bayes
import pymc as pm
import pytensor
import arviz as az

print(pm.__version__, pytensor.__version__, az.__version__)

El último paso de la alternativa pip registra el entorno como kernel de Jupyter. Sin él, es fácil abrir un notebook que corre con otro intérprete y obtener un ModuleNotFoundError aunque el paquete esté instalado.

El compilador C y la alternativa nutpie

Con el backend C por defecto, PyTensor necesita un compilador (g++). En Windows sin compilador aparece una advertencia y PyTensor cae a un modo en Python puro: el modelo funciona, pero el muestreo puede tardar decenas de veces más. Hay dos salidas: instalar el compilador desde conda-forge, o usar nutpie, un muestreador NUTS escrito en Rust que compila el modelo con Numba y no requiere g++. Se activa con un solo argumento: pm.sample(nuts_sampler="nutpie"). Es la opción probada en los notebooks del curso.

Prueba de humo: el modelo mínimo

Todo modelo PyMC vive dentro de un bloque with pm.Model(). Las variables declaradas ahí se registran en ese modelo, y pm.sample sabe qué muestrear sin que se lo pases. Este ejemplo sirve como verificación completa de la instalación:

import numpy as np
import pymc as pm
import arviz as az

rng = np.random.default_rng(42)
y = rng.normal(loc=3.0, scale=1.0, size=50)

with pm.Model() as modelo:
    mu = pm.Normal("mu", mu=0, sigma=10)
    sigma = pm.HalfNormal("sigma", sigma=5)
    pm.Normal("y_obs", mu=mu, sigma=sigma, observed=y)
    idata = pm.sample(draws=1000, tune=1000, chains=4, cores=4,
                      random_seed=42, nuts_sampler="nutpie")

print(az.summary(idata, var_names=["mu", "sigma"]))

Si la tabla muestra mu cerca de 3, columnas hdi_3% y hdi_97%, y r_hat en 1.00, el entorno está listo.

Cadenas, núcleos y semillas

chains define cuántas cadenas independientes se corren y cores cuántas en paralelo. Por defecto, cores usa el número de CPU (máximo 4) y chains el mayor entre cores y 2. Conviene fijar al menos 4 cadenas: los diagnósticos como R-hat comparan cadenas entre sí. El argumento random_seed hace el resultado reproducible; sin él, cada ejecución produce muestras distintas y las cifras del notebook no coinciden con las del texto.

Trampas comunes

  • Mezclar conda y pip sin orden: instalar PyMC con pip encima de un entorno conda suele duplicar NumPy o BLAS. Elige un gestor por entorno.
  • No fijar versiones: un pip install pymc sin pin puede traer PyMC 6 y ArviZ 1.x, con columnas y funciones distintas a las del curso.
  • Kernel equivocado en Jupyter: verifica con import sys; print(sys.executable) que el notebook corre en el entorno correcto.
  • Ignorar la advertencia del compilador: si el muestreo tarda minutos en un modelo de dos parámetros, PyTensor está en modo Python; cambia a nutpie.
  • Multiproceso en scripts de Windows: con cores mayor a 1 fuera de Jupyter, protege el código con if __name__ == "__main__":.

Cierre

Un entorno aislado, versiones fijadas y una prueba de humo que muestrea sin errores eliminan la mayor fuente de fricción del curso. Guarda el comando de creación del entorno junto a tus notebooks: reconstruirlo en otra máquina debe tomar un minuto, no una tarde.

Recursos