En la lección anterior dibujamos el histograma de los importes de pedido de MercaFresh y hablamos de su "forma": una masa central y una cola a la derecha. Las distribuciones de probabilidad son los modelos matemáticos de esas formas: describen cómo se reparten los valores que puede tomar una variable aleatoria. Entenderlas es imprescindible en Machine Learning porque muchos algoritmos asumen que los datos siguen ciertas distribuciones, y porque comparar los datos reales con una distribución esperada es la base de la detección de anomalías. En esta lección conocerás las distribuciones discretas y continuas más importantes, estudiarás la normal en profundidad y aprenderás a generarlas y visualizarlas con NumPy y scipy.

Contenido

  1. Variable aleatoria y función de probabilidad
  2. Distribuciones discretas: Bernoulli, binomial y Poisson
  3. Distribuciones continuas: uniforme, normal y exponencial
  4. La distribución normal en detalle: regla 68-95-99.7 y z-scores
  5. Por qué importan las distribuciones en Machine Learning
  6. Generación y visualización con NumPy y scipy

Variable aleatoria y función de probabilidad

Una variable aleatoria es una variable cuyo valor depende del azar: no sabemos qué valdrá en la próxima observación, pero sí podemos describir con qué probabilidad tomará cada valor posible.

Ejemplos en MercaFresh:

  • X = "¿el próximo cliente abandona el carrito?" → toma valores 0 o 1.
  • Y = "número de pedidos que llegarán en la próxima hora" → 0, 1, 2, 3...
  • Z = "importe del próximo pedido" → cualquier valor real positivo.

La forma de describir esas probabilidades depende del tipo de variable (¿recuerdas la clasificación de 02-01?):

Variable discreta Variable continua
Función Función de masa de probabilidad (PMF): P(X = k) Función de densidad de probabilidad (PDF): f(x)
Interpretación Probabilidad exacta de cada valor Densidad; la probabilidad es el área bajo la curva en un intervalo
P(X = valor exacto) Puede ser > 0 Siempre 0 (un punto no tiene área)
Suma/integral total Σ P(X=k) = 1 ∫ f(x) dx = 1

Un matiz que confunde al principio: para una variable continua, la pregunta "¿cuál es la probabilidad de que el pedido valga exactamente 50,00 €?" tiene respuesta 0. Lo que sí tiene respuesta es "¿cuál es la probabilidad de que valga entre 45 y 55 €?": el área bajo la curva de densidad en ese intervalo. Para calcular áreas acumuladas se usa la función de distribución acumulada (CDF): F(x) = P(X ≤ x), que scipy nos da hecha.

Distribuciones discretas: Bernoulli, binomial y Poisson

Bernoulli: un experimento de sí/no

Modela un único ensayo con dos resultados: éxito (1) con probabilidad p, fracaso (0) con probabilidad 1−p.

  • MercaFresh: "un cliente concreto hace churn este mes" con p = 0,08.
  • Es el ladrillo básico: la binomial y muchos modelos de clasificación (como la regresión logística del módulo 4) se construyen sobre ella.

Binomial: contar éxitos en n ensayos

Si repetimos n ensayos Bernoulli independientes con la misma p, el número total de éxitos sigue una binomial B(n, p).

  • MercaFresh: de 500 clientes con p = 0,08 de churn cada uno, ¿cuántos harán churn este mes? → B(500, 0,08), con media n·p = 40 clientes.
from scipy import stats

# ¿Probabilidad de que hagan churn exactamente 40 de 500 clientes?
print(stats.binom.pmf(k=40, n=500, p=0.08).round(4))   # 0.0657

# ¿Probabilidad de que hagan churn 50 o más? (1 - P(X <= 49))
print(1 - stats.binom.cdf(k=49, n=500, p=0.08))        # ~0.064
  • stats.binom.pmf(k, n, p) devuelve P(X = k): la probabilidad de exactamente k éxitos.
  • stats.binom.cdf(k, n, p) devuelve P(X ≤ k); restarla de 1 da la probabilidad de la cola superior. Este patrón 1 - cdf se usa constantemente.

Lectura de negocio: aunque "lo esperado" son 40 bajas, hay más de un 6 % de meses en los que habrá 50 o más solo por azar. Saber cuánta variación es normal evita alarmas injustificadas.

Poisson: contar eventos por unidad de tiempo

Modela el número de eventos en un intervalo fijo cuando ocurren de forma independiente a un ritmo medio λ (lambda).

  • MercaFresh: si llegan de media λ = 12 pedidos por hora, ¿qué probabilidad hay de recibir 20 o más en una hora (y saturar el reparto)?
lam = 12
print(1 - stats.poisson.cdf(k=19, mu=lam))   # ~0.021 -> ~2% de las horas
Distribución Modela Parámetros Ejemplo MercaFresh
Bernoulli Un ensayo sí/no p ¿Este cliente hace churn?
Binomial Nº de éxitos en n ensayos n, p Bajas entre 500 clientes
Poisson Nº de eventos por intervalo λ Pedidos por hora

Regla mnemotécnica: Bernoulli = una moneda, binomial = n monedas, Poisson = "cuántas veces suena el timbre en una hora".

Distribuciones continuas: uniforme, normal y exponencial

Uniforme

Todos los valores de un intervalo [a, b] son igual de probables; su densidad es una meseta plana. Aparece poco en datos reales, pero es la base de la simulación (los generadores aleatorios producen uniformes y de ahí derivan todo lo demás) y un modelo honesto de "no sé nada dentro de este rango".

Normal (gaussiana)

La campana simétrica definida por su media μ (centro) y su desviación estándar σ (anchura). Es la reina de las distribuciones por el teorema central del límite (adelanto: sumas y medias de muchos efectos pequeños e independientes tienden a ser normales; lo demostraremos con una simulación en la lección 02-04). Por eso tantas magnitudes agregadas —errores de medición, medias de muestras— tienen forma de campana.

  • MercaFresh: el tiempo de preparación de un pedido en almacén ronda una normal con μ = 18 min y σ = 4 min.

Exponencial

Modela el tiempo entre eventos de un proceso de Poisson. Si llegan λ = 12 pedidos/hora, el tiempo entre dos pedidos consecutivos sigue una exponencial con media 1/λ = 5 minutos. Es asimétrica con cola derecha y "sin memoria": la probabilidad de esperar 5 minutos más no depende de cuánto llevas esperando.

# Si llegan 12 pedidos/hora, ¿probabilidad de estar más de 15 min sin pedidos?
scale = 60 / 12                                   # media: 5 minutos entre pedidos
print(1 - stats.expon.cdf(15, scale=scale))       # ~0.05

Fíjate en la pareja Poisson/exponencial: cuentan lo mismo desde dos ángulos (cuántos eventos por intervalo vs. cuánto tiempo entre eventos).

Distribución Forma Parámetros Ejemplo MercaFresh
Uniforme Meseta plana a, b Simulaciones; descuento aleatorio entre 5 y 15 %
Normal Campana simétrica μ, σ Tiempo de preparación en almacén
Exponencial Decae desde 0, cola derecha λ (o su inversa, la media) Minutos entre pedidos consecutivos

La distribución normal en detalle

La regla 68-95-99.7

Si X sigue una normal con media μ y desviación estándar σ:

  • El 68,3 % de los valores cae en μ ± 1σ.
  • El 95,4 % cae en μ ± 2σ.
  • El 99,7 % cae en μ ± 3σ.

Para el tiempo de preparación de MercaFresh (μ = 18, σ = 4):

  • 68 % de los pedidos se preparan entre 14 y 22 minutos.
  • 95 % entre 10 y 26 minutos.
  • 99,7 % entre 6 y 30 minutos. Un pedido que tarda 35 minutos en prepararse está a más de 4σ: algo raro ha pasado.

Z-scores: medir en "número de desviaciones estándar"

El z-score de un valor x es:

z = (x − μ) / σ

Responde a: ¿a cuántas desviaciones estándar de la media está este valor? Es una regla universal de "rareza" que no depende de las unidades:

import numpy as np

mu, sigma = 18, 4
x = 31                       # un pedido tardó 31 min en prepararse
z = (x - mu) / sigma
print(z)                                    # 3.25 -> muy atípico

# ¿Qué proporción de pedidos tarda más de 31 min?
print(1 - stats.norm.cdf(x, loc=mu, scale=sigma))   # ~0.0006
  • Un |z| < 2 es terreno normal; |z| > 3 es un candidato serio a anomalía.
  • stats.norm.cdf(x, loc=mu, scale=sigma) da P(X ≤ x) para la normal de media loc y desviación scale; su complemento dice que solo un 0,06 % de pedidos tardaría tanto por puro azar.

Aquí usamos el z-score como detector de rarezas. En el módulo 3 (lección 03-05) reaparecerá con otro papel: estandarizar variables como paso de preprocesamiento para los modelos. Misma fórmula, propósito distinto.

Por qué importan las distribuciones en Machine Learning

  1. Supuestos de los modelos. Varios algoritmos funcionan mejor (o solo tienen garantías) bajo ciertas distribuciones: la regresión lineal (04-01) asume errores normales, Naive Bayes gaussiano (04-06) asume normalidad por clase, K-means (05-01) rinde mejor con grupos "redondos" de tipo gaussiano. Conocer la distribución real de tus datos te dice si esos supuestos son razonables.
  2. Detección de anomalías. El planteamiento clásico es: modela la distribución de lo normal y marca como anómalo lo que sea muy improbable bajo ella. Para MercaFresh: si los importes de pedido de un cliente siguen aproximadamente una distribución conocida, un pedido con probabilidad bajísima (z-score enorme, cola de la Poisson, etc.) merece revisión antes de aceptarse: puede ser un error o un fraude.
  3. Datos sintéticos y simulación. Generar datos con distribuciones controladas (como hicimos en 02-01) permite probar pipelines y modelos antes de tener datos reales.
  4. Colas y transformaciones. Reconocer una cola derecha (importes, tiempos) anticipa que quizá convenga transformar la variable (p. ej., con logaritmos), técnica que se desarrolla en la lección 03-03.

Generación y visualización con NumPy y scipy

División del trabajo entre librerías:

  • NumPy (np.random.default_rng()): generar muestras aleatorias.
  • scipy.stats: calcular PMF/PDF, CDF, cuantiles y ajustar distribuciones.
  • matplotlib: visualizar y comparar muestra vs. curva teórica.
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

rng = np.random.default_rng(7)

fig, axes = plt.subplots(2, 2, figsize=(11, 7))

# 1) Binomial: bajas mensuales entre 500 clientes (p=0.08)
bajas = rng.binomial(n=500, p=0.08, size=2000)
axes[0, 0].hist(bajas, bins=range(20, 65), color="steelblue", edgecolor="white")
axes[0, 0].set_title("Binomial: bajas/mes entre 500 clientes")

# 2) Poisson: pedidos por hora (lambda=12)
pedidos_hora = rng.poisson(lam=12, size=2000)
axes[0, 1].hist(pedidos_hora, bins=range(0, 30), color="darkorange", edgecolor="white")
axes[0, 1].set_title("Poisson: pedidos por hora")

# 3) Normal: tiempo de preparación, muestra vs. densidad teórica
prep = rng.normal(loc=18, scale=4, size=2000)
axes[1, 0].hist(prep, bins=40, density=True, color="seagreen",
                edgecolor="white", alpha=0.7)
x = np.linspace(4, 32, 300)
axes[1, 0].plot(x, stats.norm.pdf(x, loc=18, scale=4), "k--", label="PDF teórica")
axes[1, 0].set_title("Normal: minutos de preparación")
axes[1, 0].legend()

# 4) Exponencial: minutos entre pedidos (media = 5)
entre_pedidos = rng.exponential(scale=5, size=2000)
axes[1, 1].hist(entre_pedidos, bins=40, density=True, color="indianred",
                edgecolor="white", alpha=0.7)
x = np.linspace(0, 30, 300)
axes[1, 1].plot(x, stats.expon.pdf(x, scale=5), "k--", label="PDF teórica")
axes[1, 1].set_title("Exponencial: minutos entre pedidos")
axes[1, 1].legend()

plt.tight_layout()
plt.show()

Claves del código:

  • rng.binomial, rng.poisson, rng.normal, rng.exponential generan muestras de cada distribución; size=2000 pide 2.000 observaciones simuladas.
  • density=True en el histograma normaliza el eje Y para que el área total sea 1, y así el histograma sea comparable con la curva de densidad teórica que dibujamos encima con stats.<dist>.pdf.
  • Superponer muestra e histograma con la PDF teórica es el chequeo visual más simple de "¿mis datos se parecen a esta distribución?". En la lección 02-04 veremos contrastes formales para responder con números.
  • Observa las formas: binomial y Poisson son campanas discretas casi simétricas (con estos parámetros), la normal es la campana continua perfecta y la exponencial decae desde cero con cola derecha, como los tiempos entre pedidos reales.

Errores Comunes y Consejos

  • Interpretar la densidad como probabilidad. f(x) puede valer más de 1 (por ejemplo, en una uniforme estrecha); la probabilidad es el área bajo la curva en un intervalo, no la altura.
  • Asumir normalidad porque sí. Importes y tiempos suelen tener cola derecha (asimetría); aplicar la regla 68-95-99.7 a datos no normales da conclusiones erróneas. Dibuja el histograma primero.
  • Confundir los parámetros de scipy. scale en stats.expon es la media (1/λ), no λ. Y stats.norm recibe la desviación estándar (scale), no la varianza. Consulta siempre la parametrización en la documentación.
  • Olvidar la independencia. La binomial exige ensayos independientes con la misma p. Si el churn de un cliente arrastra al de sus vecinos (efecto boca a boca), el modelo binomial se queda corto.
  • Usar z-scores con distribuciones muy asimétricas. Un z-score de 3 en una exponencial no es tan raro como en una normal. La regla |z| > 3 presupone campana.
  • Consejo: memoriza las parejas "fenómeno → distribución" de las tablas de esta lección; reconocer el patrón correcto en un problema nuevo es el 80 % del trabajo.

Ejercicios

Ejercicio 1

MercaFresh envía una campaña de email a 200 clientes con una probabilidad de conversión del 5 % cada uno. (a) ¿Qué distribución sigue el número de conversiones y con qué parámetros? (b) Calcula con scipy la probabilidad de conseguir exactamente 10 conversiones y (c) la de conseguir 15 o más.

Ejercicio 2

El tiempo de preparación de pedidos sigue una normal con μ = 18 min y σ = 4 min. Usando solo la regla 68-95-99.7 (sin código): (a) ¿entre qué valores está el 95 % central de los pedidos? (b) ¿Qué porcentaje aproximado tarda más de 26 minutos? (c) Un pedido tardó 6 minutos: ¿cuál es su z-score y cómo lo interpretas?

Ejercicio 3

Al centro logístico de MercaFresh llegan de media 12 pedidos por hora. Simula con NumPy 10.000 horas de actividad y estima empíricamente la probabilidad de recibir 20 o más pedidos en una hora. Compara el resultado con el valor exacto de 1 - stats.poisson.cdf(19, mu=12).

Soluciones

Solución 1

(a) Binomial B(n=200, p=0,05): 200 ensayos Bernoulli independientes. Su media es n·p = 10 conversiones.

from scipy import stats
print(stats.binom.pmf(10, n=200, p=0.05).round(4))      # (b) ~0.1288
print((1 - stats.binom.cdf(14, n=200, p=0.05)).round(4)) # (c) ~0.0744

(b) Un 12,9 % de probabilidad de exactamente 10. (c) Un 7,4 % de conseguir 15 o más. Nota: para la cola "15 o más" se resta la CDF en 14, no en 15.

Solución 2

  • (a) μ ± 2σ = 18 ± 8 → entre 10 y 26 minutos.
  • (b) Fuera de μ ± 2σ queda el 5 % repartido en dos colas; solo la superior: ≈ 2,5 % de los pedidos tarda más de 26 min.
  • (c) z = (6 − 18) / 4 = −3. Está a tres desviaciones estándar por debajo de la media: un pedido preparado sospechosamente rápido (¿se registró mal el tiempo?, ¿pedido de un solo artículo?). Las anomalías también existen por la izquierda.

Solución 3

import numpy as np
from scipy import stats

rng = np.random.default_rng(0)
horas = rng.poisson(lam=12, size=10_000)
print((horas >= 20).mean())                    # ~0.0210 (varía con la semilla)
print(1 - stats.poisson.cdf(19, mu=12))        # 0.0213 (exacto)

(horas >= 20) crea un array de booleanos y .mean() calcula la proporción de True: la frecuencia con que ocurre el evento en la simulación. Con 10.000 repeticiones, la estimación empírica (~2,1 %) coincide casi exactamente con la teórica. Este patrón "simular y contar" es una herramienta potentísima cuando la fórmula exacta no existe o no la recuerdas.

Conclusión

Ya sabes qué es una variable aleatoria y conoces las seis distribuciones de trabajo del día a día: Bernoulli, binomial y Poisson para contar; uniforme, normal y exponencial para medir. Has profundizado en la normal —la regla 68-95-99.7 y los z-scores— y has visto por qué las distribuciones importan en ML: sustentan los supuestos de los modelos y la detección de anomalías en los pedidos de MercaFresh, además de permitir simulaciones con NumPy y cálculos exactos con scipy. Hasta ahora hemos mirado cada variable por separado; el siguiente paso es estudiar cómo se relacionan entre sí: en la próxima lección, covarianza y correlación nos dirán qué variables de MercaFresh se mueven juntas y cuáles avisan del churn.

Curso de Machine Learning

Módulo 1: Introducción al Machine Learning

Módulo 2: Fundamentos de Estadística y Probabilidad

Módulo 3: Preprocesamiento de Datos

Módulo 4: Algoritmos de Machine Learning Supervisado

Módulo 5: Algoritmos de Machine Learning No Supervisado

Módulo 6: Evaluación y Validación de Modelos

Módulo 7: Técnicas Avanzadas y Optimización

Módulo 8: Implementación y Despliegue de Modelos

Módulo 9: Proyectos Prácticos

Módulo 10: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados