Predicciones con Incertidumbre: PyMC3 para Ciencia de Datos
15 JUN., 2025
//5 min. de Lectura

En el mundo real, las predicciones perfectas son una ilusión. Nosotros enfrentamos constantemente la incertidumbre: desde fluctuaciones del mercado hasta variabilidad biológica. PyMC3 emerge como la herramienta esencial para científicos de datos que buscan no solo predecir, sino cuantificar la incertidumbre en sus predicciones. Este artículo revela cómo el modelado probabilístico bayesiano con PyMC3 transforma puntos únicos en distribuciones completas, proporcionando no solo respuestas sino intervalos de confianza, probabilidades de escenarios y medidas de riesgo. Descubrirás cómo implementar modelos que capturan la complejidad del mundo real, desde problemas básicos hasta arquitecturas avanzadas de deep learning probabilístico.
Fundamentos de PyMC3: Más Allá de los P-Valores
PyMC3 implementa inferencia probabilística mediante muestreo MCMC (Monte Carlo vía Cadenas de Markov) y VI (Inferencia Variacional). Nosotros contrastamos este enfoque con estadística frecuentista:
Enfoque | Frecuentista | Bayesiano (PyMC3) |
---|---|---|
Incertidumbre | Intervalos de confianza | Distribuciones posteriores completas |
Resultado | p-valores crípticos | Probabilidades interpretables |
Datos escasos | Problemas con poder estadístico | Incorporación de conocimiento previo |
Complejidad | Limitado a modelos lineales | Modelos jerárquicos y no lineales |
Instalación básica:
# Instalación de PyMC3 y dependencias pip install pymc3 arviz numpy pandas matplotlib # Importación estándar import pymc3 as pm import arviz as az import numpy as np
Construcción de Modelos: De Regresión a Deep Learning Probabilístico
Implementemos modelos escalando en complejidad:
1. Regresión Lineal Bayesiana:
with pm.Model() as linear_model:
# Priors
alpha = pm.Normal('intercept', mu=0, sigma=10)
beta = pm.Normal('slope', mu=0, sigma=10, shape=X.shape[1])
sigma = pm.HalfNormal('sigma', sigma=1)
# Lineal predictor
mu = alpha + pm.math.dot(X, beta)
# Likelihood
likelihood = pm.Normal('y', mu=mu, sigma=sigma, observed=y)
# Muestreo
trace = pm.sample(2000, tune=1000, cores=4)
2. Modelo Jerárquico para Datos Agrupados:
with pm.Model() as hierarchical_model:
# Hiperpriors
mu_alpha = pm.Normal('mu_alpha', mu=0, sigma=10)
sigma_alpha = pm.HalfNormal('sigma_alpha', sigma=5)
# Efectos por grupo
alpha = pm.Normal('alpha', mu=mu_alpha, sigma=sigma_alpha, shape=n_groups)
# Efectos fijos
beta = pm.Normal('beta', mu=0, sigma=5, shape=X.shape[1])
# Likelihood
mu = alpha[group_idx] + pm.math.dot(X, beta)
likelihood = pm.Normal('y', mu=mu, sigma=sigma, observed=y)
3. Bayesian Neural Network con PyMC3:
import theano.tensor as tt
# Arquitectura de red neuronal
def build_nn(inputs):
# Capa oculta con 20 neuronas
w1 = pm.Normal('w1', mu=0, sigma=1, shape=(inputs.shape[1], 20))
b1 = pm.Normal('b1', mu=0, sigma=1, shape=20)
layer1 = tt.tanh(tt.dot(inputs, w1) + b1)
# Capa de salida
w2 = pm.Normal('w2', mu=0, sigma=1, shape=(20, 1))
b2 = pm.Normal('b2', mu=0, sigma=1, shape=1)
output = tt.dot(layer1, w2) + b2
return output
with pm.Model() as nn_model:
# Construir red
prediction = build_nn(X)
# Priors para pesos ya definidos en build_nn
# Likelihood
pm.Normal('y', mu=prediction, sigma=sigma, observed=y)
# Muestreo con NUTS
trace = pm.sample(target_accept=0.95)
Inferencia y Diagnóstico: Validando Nuestras Cadenas
El muestreo MCMC requiere validación rigurosa:
- R-hat < 1.01: Indica convergencia
- ESS > 400: Tamaño muestral efectivo suficiente
- Autocorrelación baja: Muestras independientes
Diagnóstico con ArviZ:
# Resumen estadístico
az.summary(trace, round_to=2)
# Gráfico de rastreo
az.plot_trace(trace)
# Gráfico de bosque
az.plot_forest(trace, var_names=['beta'])
# Autocorrelación
az.plot_autocorr(trace)
Para problemas de convergencia:
- Aumentar
tune
(fase de adaptación) - Usar
target_accept=0.95
- Reescalar variables
- Considerar parametrizaciones no centradas
Predicciones con Intervalos de Confianza: La Incertidumbre Cuantificada
Generamos predicciones con intervalos de credibilidad:
with linear_model:
# Predicción sobre nuevos datos
pm.set_data({'x': X_new})
posterior_predictive = pm.sample_posterior_predictive(
trace, samples=2000, var_names=['y']
)
# Extraer intervalos de credibilidad
y_pred = posterior_predictive['y']
y_mean = y_pred.mean(axis=0)
y_hdi = az.hdi(y_pred) # Intervalo de densidad más alta
Visualización con incertidumbre:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.plot(X_new, y_mean, 'b-', label='Predicción media')
plt.fill_between(
X_new.flatten(),
y_hdi[:, 0],
y_hdi[:, 1],
color='blue',
alpha=0.2,
label='94% HDI'
)
plt.scatter(X_train, y_train, c='red', alpha=0.4, label='Datos observados')
plt.legend()
plt.title('Predicción con Intervalos de Credibilidad')
plt.show()
Para decisiones empresariales, calculamos probabilidades de escenarios:
# Probabilidad de que las ventas excedan 1000 unidades
sales_samples = posterior_predictive['sales']
prob_over_1000 = (sales_samples > 1000).mean()
print(f"Probabilidad de ventas > 1000: {prob_over_1000:.2%}")
# Valor en Riesgo (VaR) al 95%
var_95 = np.percentile(sales_samples, 5)
print(f"Peor escenario (95% confianza): {var_95:.0f} unidades")
Casos de Éxito: PyMC3 en Acción
Aplicaciones reales con impacto medible:
- Finanzas: Modelo de riesgo crediticio con probabilidad de default dinámica
- Salud: Predicción de progresión de enfermedades con intervalos de credibilidad
- Marketing: Atribución bayesiana de conversión multicanal
- Manufactura: Control de calidad con modelos jerárquicos por lote
Ejemplo: Modelo de crecimiento epidemiológico:
with pm.Model() as seir_model:
# Parámetros epidemiológicos con priors
beta = pm.Lognormal('beta', mu=0, sigma=0.5)
gamma = pm.Lognormal('gamma', mu=np.log(1/8), sigma=0.2)
sigma = pm.Lognormal('sigma', mu=np.log(1/5), sigma=0.2)
# Compartimentos S, E, I, R
S, E, I, R = [tt.vector() for _ in range(4)]
# Ecuaciones diferenciales
dS = -beta * S * I / N
dE = beta * S * I / N - sigma * E
dI = sigma * E - gamma * I
dR = gamma * I
# Solución ODE
solution, updates = theano.scan(
fn=lambda t, S, E, I, R: [S + dS, E + dE, I + dI, R + dR],
sequences=[time],
outputs_info=[S0, E0, I0, R0]
)
# Likelihood
pm.NegativeBinomial('obs', mu=solution[2], alpha=phi, observed=cases)
Optimización para Producción: De Jupyter a APIs en Tiempo Real
Llevamos modelos PyMC3 a producción con:
- Inferencia Variacional: Para predicción rápida
- Caché de posteriores: Reutilización de distribuciones muestreadas
- Serialización: Almacenamiento con
pickle
ojoblib
- APIs con FastAPI: Servicio de predicciones con incertidumbre
API de predicción con FastAPI:
from fastapi import FastAPI
import joblib
app = FastAPI()
model = joblib.load('bayesian_model.pkl')
@app.post("/predict")
async def predict(data: dict):
samples = model.predict(data['inputs'], samples=1000)
return {
"mean": float(samples.mean()),
"hdi_94": [float(samples.hdi[0]), float(samples.hdi[1])],
"samples": samples.tolist()
}
Para actualizaciones en tiempo real, implementamos Bayesian Online Learning con filtros de partículas.
Conclusión: La Incertidumbre como Ventaja Competitiva
Dominar PyMC3 para predicciones con incertidumbre no es solo una habilidad técnica; es un cambio de paradigma en la toma de decisiones. Nosotros hemos comprobado cómo organizaciones que cuantifican y comunican incertidumbre toman decisiones más robustas, gestionan riesgos proactivamente y generan confianza con stakeholders.
En 2024, con la integración de PyMC3 con bibliotecas como TensorFlow Probability y PyTorch, el modelado bayesiano se ha vuelto accesible para problemas de gran escala. La verdadera ventaja competitiva ya no está en predicciones puntuales, sino en comprender y gestionar el espectro completo de posibilidades. Cuando entregamos no solo un número sino una distribución, transformamos datos en sabiduría estratégica.
Comentarios
0Sin comentarios
Sé el primero en compartir tu opinión.
También te puede interesar
desmitificaremos el teorema de Bayes y lo implementaremos en Python