Phase 01 - Lesson 06
Probabilidad y Distribuciones
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
La probabilidad es el lenguaje que la IA usa para expresar la incertidumbre.
Tipo: Learn Lenguaje: Python Requisitos previos: Fase 1, Lecciones 01-04 Tiempo: ~75 minutos
Objetivos de Aprendizaje
- Implementar PMFs y PDFs desde cero para las distribuciones de Bernoulli, categórica, Poisson, uniforme y normal
- Calcular el valor esperado, la varianza y usar el Teorema Central del Límite para explicar por que las Gaussianas dominan
- Construir las funciones softmax y log-softmax con el truco de estabilidad numérica (restar el logit máximo)
- Calcular la pérdida de entropía cruzada a partir de logits y conectarla con la log-verosimilitud negativa
El Problema
Un clasificador devuelve [0.03, 0.91, 0.06]. Un modelo de lenguaje elige la siguiente palabra entre 50.000 candidatas. Un modelo de difusión genera imágenes muestreando de distribuciones aprendidas. Todo esto es probabilidad en acción.
Cada predicción que hace un modelo es una distribución de probabilidad. Cada función de pérdida mide cuan lejos esta la distribución predicha de la verdadera. Cada paso de entrenamiento ajusta parámetros para hacer que una distribución se parezca más a otra. Sin probabilidad, no puedes leer un solo artículo de ML, depurar un solo modelo ni entender por que tu pérdida de entrenamiento es NaN.
El Concepto
Eventos, Espacios Muestrales y Probabilidad
El espacio muestral S es el conjunto de todos los resultados posibles. Un evento es un subconjunto del espacio muestral. La probabilidad asigna a los eventos números entre 0 y 1.
Lanzamiento de moneda:
S = {H, T}
P(H) = 0.5, P(T) = 0.5
Lanzamiento de un dado:
S = {1, 2, 3, 4, 5, 6}
P(par) = P({2, 4, 6}) = 3/6 = 0.5
Tres axiomas definen toda la probabilidad:
- P(A) >= 0 para cualquier evento A
- P(S) = 1 (algo siempre sucede)
- P(A o B) = P(A) + P(B) cuando A y B no pueden ocurrir juntos
Todo lo demas (teorema de Bayes, esperanzas, distribuciones) se deriva de estas tres reglas.
Probabilidad Condicional e Independencia
P(A|B) es la probabilidad de A dado que B sucedió.
P(A|B) = P(A y B) / P(B)
Ejemplo: baraja de cartas
P(Rey | Carta de figura) = P(Rey y Carta de figura) / P(Carta de figura)
= (4/52) / (12/52)
= 4/12 = 1/3
Dos eventos son independientes cuando saber uno no dice nada sobre el otro:
Independiente: P(A|B) = P(A)
Equivalente a: P(A y B) = P(A) * P(B)
Los lanzamientos de moneda son independientes. Sacar cartas sin reemplazo no lo es.
Funciones de Masa de Probabilidad vs Funciones de Densidad de Probabilidad
Las variables aleatorias discretas tienen una función de masa de probabilidad (PMF). Cada resultado tiene una probabilidad especifica que puedes leer directamente.
PMF: P(X = k)
Dado justo:
P(X = 1) = 1/6
P(X = 2) = 1/6
...
P(X = 6) = 1/6
Suma de todas las probabilidades = 1
Las variables aleatorias continuas tienen una función de densidad de probabilidad (PDF). La densidad en un solo punto no es una probabilidad. La probabilidad surge de integrar la densidad sobre un intervalo.
PDF: f(x)
P(a <= X <= b) = integral de f(x) de a a b
f(x) puede ser mayor que 1 (densidad, no probabilidad)
integral de -inf a +inf de f(x) dx = 1
Esta distinción importa en ML. Las salidas de clasificación son PMFs (elecciones discretas). Los espacios latentes de VAE usan PDFs (continuos).
Distribuciones Comunes
Bernoulli: un ensayo, dos resultados. Modela la clasificación binaria.
P(X = 1) = p
P(X = 0) = 1 - p
Media = p, Varianza = p(1-p)
Categórica: un ensayo, k resultados. Modela la clasificación multiclase (salida softmax).
P(X = i) = p_i, donde la suma de p_i = 1
Ejemplo: P(gato) = 0.7, P(perro) = 0.2, P(pajaro) = 0.1
Uniforme: todos los resultados igualmente probables. Usada para la inicialización aleatoria.
Discreta: P(X = k) = 1/n para k en {1, ..., n}
Continua: f(x) = 1/(b-a) para x en [a, b]
Normal (Gaussiana): la curva de campana. Parametrizada por la media (mu) y la varianza (sigma^2).
f(x) = (1 / sqrt(2*pi*sigma^2)) * exp(-(x - mu)^2 / (2*sigma^2))
Normal estandar: mu = 0, sigma = 1
68% de los datos dentro de 1 sigma
95% dentro de 2 sigma
99.7% dentro de 3 sigma
Poisson: conteos de eventos raros en un intervalo fijo. Modela tasas de eventos.
P(X = k) = (lambda^k * e^(-lambda)) / k!
Media = lambda, Varianza = lambda
Valor Esperado y Varianza
El valor esperado es el promedio ponderado de los resultados.
Discreta: E[X] = suma de x_i * P(X = x_i)
Continua: E[X] = integral de x * f(x) dx
La varianza mide la dispersión alrededor de la media.
Var(X) = E[(X - E[X])^2] = E[X^2] - (E[X])^2
Desviacion estandar = sqrt(Var(X))
En ML, el valor esperado aparece como la función de pérdida (pérdida promedio sobre la distribución de los datos). La varianza te informa sobre la estabilidad del modelo. Una varianza alta en los gradientes significa entrenamiento ruidoso.
Distribuciones Conjuntas y Marginales
Una distribución conjunta P(X, Y) describe dos variables aleatorias en conjunto.
Ejemplo de PMF conjunta (X = clima, Y = paraguas):
| Y=0 (sin paraguas) | Y=1 (con paraguas) | Marginal P(X) | |
|---|---|---|---|
| X=0 (sol) | 0.40 | 0.10 | P(X=0) = 0.50 |
| X=1 (lluvia) | 0.05 | 0.45 | P(X=1) = 0.50 |
| Marginal P(Y) | P(Y=0) = 0.45 | P(Y=1) = 0.55 | 1.00 |
La distribución marginal suma la otra variable:
P(X = x) = suma sobre todo y de P(X = x, Y = y)
Los totales de fila y columna en la tabla anterior son las marginales.
Por que la Distribución Normal Aparece en Todas Partes
El Teorema Central del Límite: la suma (o el promedio) de muchas variables aleatorias independientes converge a una distribución normal, sin importar la distribución original.
Lanza 1 dado: distribucion uniforme (plana)
Promedio de 2 dados: triangular (con pico)
Promedio de 30 dados: curva de campana casi perfecta
Esto funciona para CUALQUIER distribucion inicial.
Por eso:
- Los errores de medición son aproximadamente normales (muchas fuentes pequeñas e independientes)
- Las inicializaciones de pesos en redes neuronales usan distribuciones normales
- El ruido del gradiente en SGD es aproximadamente normal (suma de muchos gradientes de muestra)
- La distribución normal es la distribución de máxima entropía para una media y varianza dadas
Log-Probabilidades
Las probabilidades en bruto causan problemas numéricos. Multiplicar muchas probabilidades pequeñas juntas rápidamente sufre subdesbordamiento hasta cero.
P(oracion) = P(palabra1) * P(palabra2) * ... * P(palabra_n)
= 0.01 * 0.003 * 0.02 * ...
-> 0.0 (subdesbordamiento tras ~30 terminos)
Las log-probabilidades resuelven esto. Las multiplicaciones se convierten en sumas.
log P(oracion) = log P(palabra1) + log P(palabra2) + ... + log P(palabra_n)
= -4.6 + -5.8 + -3.9 + ...
-> numero finito (sin subdesbordamiento)
Reglas:
- log(a * b) = log(a) + log(b)
- las log-probabilidades son siempre <= 0 (ya que 0 < P <= 1)
- Más negativo = menos probable
- La pérdida de entropía cruzada es la log-probabilidad negativa de la clase correcta
Softmax como Distribución de Probabilidad
Las redes neuronales devuelven puntajes en bruto (logits). El softmax los convierte en una distribución de probabilidad válida.
softmax(z_i) = exp(z_i) / sum(exp(z_j) para todo j)
Propiedades:
- Todas las salidas estan en (0, 1)
- Todas las salidas suman 1
- Preserva el orden relativo de las entradas
- exp() amplifica las diferencias entre logits
El truco del softmax: resta el logit máximo antes de exponenciar para evitar el desbordamiento.
z = [100, 101, 102]
exp(102) = desbordamiento
z_shifted = z - max(z) = [-2, -1, 0]
exp(0) = 1 (seguro)
Mismo resultado, sin desbordamiento.
El log-softmax combina softmax y log para la estabilidad numérica. PyTorch usa esto internamente para la pérdida de entropía cruzada.
Muestreo
Muestrear significa extraer valores aleatorios de una distribución. En ML:
- El dropout muestrea aleatoriamente que neuronas poner en cero
- El aumento de datos muestrea transformaciones aleatorias
- Los modelos de lenguaje muestrean el siguiente token de la distribución predicha
- Los modelos de difusión muestrean ruido y lo eliminan progresivamente
Muestrear de distribuciones arbitrarias requiere técnicas como el muestreo por transformada inversa, el muestreo por rechazo o el truco de reparametrización (usado en VAEs).
Construye
Paso 1: Fundamentos de probabilidad
import math
import random
def factorial(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
def combinations(n, k):
return factorial(n) // (factorial(k) * factorial(n - k))
def conditional_probability(p_a_and_b, p_b):
return p_a_and_b / p_b
p_king_given_face = conditional_probability(4/52, 12/52)
print(f"P(King | Face card) = {p_king_given_face:.4f}")
Paso 2: PMF y PDF desde cero
def bernoulli_pmf(k, p):
return p if k == 1 else (1 - p)
def categorical_pmf(k, probs):
return probs[k]
def poisson_pmf(k, lam):
return (lam ** k) * math.exp(-lam) / factorial(k)
def uniform_pdf(x, a, b):
if a <= x <= b:
return 1.0 / (b - a)
return 0.0
def normal_pdf(x, mu, sigma):
coeff = 1.0 / (sigma * math.sqrt(2 * math.pi))
exponent = -0.5 * ((x - mu) / sigma) ** 2
return coeff * math.exp(exponent)
Paso 3: Valor esperado y varianza
def expected_value(values, probabilities):
return sum(v * p for v, p in zip(values, probabilities))
def variance(values, probabilities):
mu = expected_value(values, probabilities)
return sum(p * (v - mu) ** 2 for v, p in zip(values, probabilities))
die_values = [1, 2, 3, 4, 5, 6]
die_probs = [1/6] * 6
mu = expected_value(die_values, die_probs)
var = variance(die_values, die_probs)
print(f"Die: E[X] = {mu:.4f}, Var(X) = {var:.4f}, SD = {var**0.5:.4f}")
Paso 4: Muestreo de distribuciones
def sample_bernoulli(p, n=1):
return [1 if random.random() < p else 0 for _ in range(n)]
def sample_categorical(probs, n=1):
cumulative = []
total = 0
for p in probs:
total += p
cumulative.append(total)
samples = []
for _ in range(n):
r = random.random()
for i, c in enumerate(cumulative):
if r <= c:
samples.append(i)
break
return samples
def sample_normal_box_muller(mu, sigma, n=1):
samples = []
for _ in range(n):
u1 = random.random()
u2 = random.random()
z = math.sqrt(-2 * math.log(u1)) * math.cos(2 * math.pi * u2)
samples.append(mu + sigma * z)
return samples
Paso 5: Softmax y log-probabilidades
def softmax(logits):
max_logit = max(logits)
shifted = [z - max_logit for z in logits]
exps = [math.exp(z) for z in shifted]
total = sum(exps)
return [e / total for e in exps]
def log_softmax(logits):
max_logit = max(logits)
shifted = [z - max_logit for z in logits]
log_sum_exp = max_logit + math.log(sum(math.exp(z) for z in shifted))
return [z - log_sum_exp for z in logits]
def cross_entropy_loss(logits, target_index):
log_probs = log_softmax(logits)
return -log_probs[target_index]
Paso 6: Demostración del Teorema Central del Límite
def demonstrate_clt(dist_fn, n_samples, n_averages):
averages = []
for _ in range(n_averages):
samples = [dist_fn() for _ in range(n_samples)]
averages.append(sum(samples) / len(samples))
return averages
Paso 7: Visualización
import matplotlib.pyplot as plt
xs = [mu + sigma * (i - 500) / 100 for i in range(1001)]
ys = [normal_pdf(x, mu, sigma) for x, mu, sigma in ...]
plt.plot(xs, ys)
Las implementaciones completas con todas las visualizaciones están en code/probability.py.
Usa
Con NumPy y SciPy, todo lo anterior se reduce a una sola línea:
import numpy as np
from scipy import stats
normal = stats.norm(loc=0, scale=1)
samples = normal.rvs(size=10000)
print(f"Mean: {np.mean(samples):.4f}, Std: {np.std(samples):.4f}")
print(f"P(X < 1.96) = {normal.cdf(1.96):.4f}")
logits = np.array([2.0, 1.0, 0.1])
from scipy.special import softmax, log_softmax
probs = softmax(logits)
log_probs = log_softmax(logits)
print(f"Softmax: {probs}")
print(f"Log-softmax: {log_probs}")
Tu construiste todo esto desde cero. Ahora sabes que están haciendo las llamadas de la biblioteca.
Ejercicios
Implementa el muestreo por transformada inversa para la distribución exponencial. Verifica muestreando 10.000 valores y comparando el histograma con la PDF verdadera.
Construye una tabla de distribución conjunta para dos dados cargados. Calcula las distribuciones marginales y verifica si los dados son independientes.
Calcula la pérdida de entropía cruzada para un clasificador de 5 clases que devuelve los logits
[2.0, 0.5, -1.0, 3.0, 0.1]cuando la clase correcta es el índice 3. Luego verifica tu respuesta con elnn.CrossEntropyLossde PyTorch.Escribe una función que reciba una lista de log-probabilidades y devuelva la secuencia más probable, la log-probabilidad total y la probabilidad en bruto equivalente. Pruebala con una oración de 50 palabras donde cada palabra tiene probabilidad 0.01.
Términos Clave
| Término | Lo que dice la gente | Lo que realmente significa |
|---|---|---|
| Espacio muestral | "Todas las posibilidades" | El conjunto S de todo resultado posible de un experimento |
| PMF | "La función de probabilidad" | Una función que da la probabilidad exacta de cada resultado discreto, sumando 1 |
| "La curva de probabilidad" | Una función de densidad para variables continuas. Integrala sobre un intervalo para obtener la probabilidad | |
| Probabilidad condicional | "Probabilidad dado algo" | P(A|B) = P(A y B) / P(B). La base del razonamiento bayesiano y del teorema de Bayes |
| Independencia | "No se afectan mutuamente" | P(A y B) = P(A) * P(B). Saber un evento no dice nada sobre el otro |
| Valor esperado | "El promedio" | La suma ponderada por probabilidad de todos los resultados. La función de pérdida es un valor esperado |
| Varianza | "Cuan dispersa" | La desviación cuadrática esperada respecto a la media. Varianza alta = estimaciones ruidosas e inestables |
| Distribución normal | "La curva de campana" | f(x) = (1/sqrt(2pisigma^2)) * exp(-(x-mu)^2/(2*sigma^2)). Aparece en todas partes debido al TCL |
| Teorema Central del Límite | "Los promedios se vuelven normales" | El promedio de muchas muestras independientes converge a una distribución normal sin importar la fuente |
| Distribución conjunta | "Dos variables juntas" | P(X, Y) describe la probabilidad de cada combinación de resultados de X e Y |
| Distribución marginal | "Suma la otra variable" | P(X) = suma_y P(X, Y). Recupera la distribución de una variable a partir de la conjunta |
| Log-probabilidad | "Log de la probabilidad" | log P(x). Convierte productos en sumas, evitando el subdesbordamiento numérico en secuencias largas |
| Softmax | "Convierte puntajes en probabilidades" | softmax(z_i) = exp(z_i) / sum(exp(z_j)). Asigna logits de valor real a una distribución de probabilidad válida |
| Entropía cruzada | "La función de pérdida" | -sum(p_true * log(p_predicted)). Mide cuan diferentes son dos distribuciones. Menor es mejor |
| Logits | "Salidas en bruto del modelo" | Puntajes no normalizados antes del softmax. Nombrados en referencia a la función logística |
| Muestreo | "Extraer valores aleatorios" | Generar valores conforme a una distribución de probabilidad. Como los modelos generan su salida |
Lectura Adicional
- 3Blue1Brown: But what is the Central Limit Theorem? - prueba visual de por que los promedios se vuelven normales
- Stanford CS229 Probability Review - referencia concisa que cubre todo lo de aquí y más
- The Log-Sum-Exp Trick - por que importa la estabilidad numérica y como lograrla