Skip to content

English · Español

Lab 00 — Entropía a mano

Lee theory/02-entropy-and-kl.md antes de empezar. No consultes solutions/.

Objetivo

Calcular a mano la entropía sobre una distribución categórica pequeña; verificar que la demostración de la cota superior funciona; implementar entropy(p) en NumPy con el manejo correcto de \(p_i = 0\).

Configuración

Usa el alfabeto §A13 de tiempos verbales: {infinitive, present, past, past_participle, future} (\(V = 5\)).

Tareas

Tarea 1 — entropía sobre papel

Para cada una de las siguientes distribuciones sobre los 5 tiempos, calcula \(H(p)\) en nats a mano. Muestra tu aritmética.

Distribución \(p\)
A \((1, 0, 0, 0, 0)\)
B \((0.5, 0.5, 0, 0, 0)\)
C \((0.25, 0.25, 0.25, 0.25, 0)\)
D \((0.2, 0.2, 0.2, 0.2, 0.2)\) (uniforme)
E \((0.6, 0.1, 0.1, 0.1, 0.1)\)

Predice cuál tiene la mayor entropía antes de calcular. Luego comprueba.

Tarea 2 — implementa entropy(p) en NumPy

Restricciones:

  • NumPy puro; nada de scipy.stats.entropy, nada de PyTorch.
  • Debe manejar \(p_i = 0\) correctamente (convención: \(0 \log 0 = 0\)). Pista: hay un idioma de una línea con np.where o xlogy.
  • Debe validar que \(p\) es un vector de probabilidad válido: forma, no negativo, suma 1 dentro de tolerancia.
  • Módulo: src/phase05/probability.py (este es un módulo de borrador de la Fase 05 — NO se gradúa a src/utils/; eso es una fase posterior).

Sugerencia de firma:

def entropy(p: NDArray[np.float64]) -> float:
    """Return H(p) in nats. Raises ValueError if p is not a valid distribution."""

Tarea 3 — verifica la cota superior numéricamente

Para \(V \in \{2, 5, 10, 100, 600\}\):

  1. Muestrea 1000 distribuciones aleatorias sobre \(V\) resultados (p. ej., desde una Dirichlet(1, ..., 1)).
  2. Para cada una, calcula \(H\).
  3. Verifica \(H \le \log V\) para cada muestra.
  4. Dibuja el histograma de \(H / \log V\) — la mayoría deberían estar cerca de 1 (Dirichlet(1,...,1) se concentra cerca de la uniforme para \(V\) moderado).

Tarea 4 — reproduce la demostración de Jensen

En tus notas de lab (o en una celda de notebook), escribe la demostración:

\[H(p) = \mathbb{E}_p[\log(1/p_i)] \le \log \mathbb{E}_p[1/p_i] = \log V.\]

Justifica cada paso. Identifica exactamente dónde se usa la desigualdad de Jensen y verifica la afirmación de concavidad.

Mediciones a capturar

  • Tiempo de pared para calcular entropy(p) en \(V = 600\), 100k muestras (debería ser ≲ 10 ms — es una operación diminuta).
  • Manifest de muestra en experiments/<date>-phase-05-entropy/manifest.json según src/utils/seeding.py.
  • El histograma de la Tarea 3 guardado como experiments/<date>-phase-05-entropy/histogram.png.

Aceptación

  • Las 5 distribuciones A-E tienen entropías correctas calculadas sobre papel.
  • entropy(p) maneja \(p_i = 0\) sin NaN.
  • entropy(p) lanza ValueError ante entradas inválidas (no normalizadas, valores negativos, forma incorrecta).
  • Pasan los property tests: entropy(uniform_V) ≈ log(V), entropy(point_mass) == 0.
  • Existe el histograma; verificación visual de que todas las muestras respetan la cota.
  • Demostración de Jensen reproducida en tus notas.

Escollos esperados

  • np.log(p) sobre un vector con ceros emite silenciosamente -inf; multiplicar por 0 da NaN (la regla 0 * inf de IEEE-754). Usa np.where(p > 0, p * np.log(p), 0.0) o scipy.special.xlogy(p, p).
  • Las muestras de Dirichlet pueden no estar exactamente normalizadas (redondeo); tu validador debería permitir np.isclose(p.sum(), 1.0) con tolerancia por defecto.
  • Confundir nats y bits: \(H\) en nats usa np.log; en bits usa np.log2. La convención de este proyecto son nats (coincide con F.cross_entropy de PyTorch).

Siguiente: 01-kl-and-cross-entropy.md