Divergencia de Kullback–Leibler

Eval

Divergencia de Kullback–Leibler

Creado: Última actualización: Tiempo de lectura: 2 min
まとめ
  • La divergencia KL mide cuánto difiere una distribución real (P) de una referencia (Q) en términos de entropía relativa.
  • Calcula KL en ejemplos discretos, incluyendo el suavizado necesario ante probabilidades nulas.
  • Aplícala a evaluación de modelos y detección de drift, teniendo en cuenta su asimetría e inestabilidad.

1. Definición #

Para distribuciones discretas (P) y (Q):

$$ \mathrm{KL}(P \parallel Q) = \sum_i p_i \log \frac{p_i}{q_i} $$

  • ( \mathrm{KL}(P \parallel Q) = 0 ) si (P = Q).
  • Es asimétrica: ( \mathrm{KL}(P \parallel Q) \neq \mathrm{KL}(Q \parallel P) ).
  • Sensible a diferencias de soporte: si ( q_i = 0 ) y ( p_i > 0 ), diverge a infinito.

2. Cálculo en Python #

import numpy as np
from scipy.special import rel_entr  # p * log(p / q) elemento a elemento

def kl_divergence(p: np.ndarray, q: np.ndarray) -> float:
    """Divergencia KL D(P || Q)."""
    p = np.asarray(p, dtype=float)
    q = np.asarray(q, dtype=float)

    p = p / p.sum()
    q = q / q.sum()

    epsilon = 1e-12
    return float(np.sum(rel_entr(p + epsilon, q + epsilon)))

Agregar un epsilon pequeño evita divisiones por cero cuando hay probabilidades nulas. Ajusta el suavizado según el dominio.


3. Ejemplo con histogramas #

import matplotlib.pyplot as plt
import japanize_matplotlib  # opcional para etiquetas en japonés

a = np.array([0.1, 0.2, 0.3, 0.2, 0.1, 0.1])
b = np.array([0.05, 0.1, 0.2, 0.3, 0.3, 0.05])

plt.figure(figsize=(12, 4))
plt.bar(np.arange(a.size) - 0.1, a, width=0.2, label="P")
plt.bar(np.arange(b.size) + 0.1, b, width=0.2, label="Q")
plt.legend()
plt.show()

print(f"KL(P || P) = {kl_divergence(a, a):.4f}")
print(f"KL(P || Q) = {kl_divergence(a, b):.4f}")
print(f"KL(Q || P) = {kl_divergence(b, a):.4f}")

Intercambiar el orden cambia el resultado; interpreta KL con el punto de vista “referencia vs. objetivo” correcto.


4. Conexión con la divergencia Jensen–Shannon #

Para obtener una medida simétrica y acotada, promedia ambas direcciones de KL:

plt.hist(np.random.normal(1, 1, 1000), alpha=0.85, color="blue")
plt.hist(np.random.normal(4, 1, 1000), alpha=0.85, color="red")
plt.hist(np.random.normal(2.5, 1, 1000), alpha=0.85, color="green")
plt.show()

La divergencia Jensen–Shannon mitiga los valores infinitos cuando los soportes difieren y es más práctica en contextos reales.


5. Usos y precauciones #

  • Evaluación de modelos generativos: monitoriza cuánto se desvía la distribución generada de la real.
  • Monitorización/drift: sigue cómo los datos en producción se alejan de los de entrenamiento.
  • Modelos de lenguaje: compara distribuciones de n-gramas o probabilidades token.

Utiliza suavizado (p. ej., priors de Dirichlet) cuando los datos son escasos. Un KL alto no implica necesariamente fracaso; combínalo con otras métricas.


Resumen #

La divergencia KL captura la diferencia relativa entre distribuciones. Su asimetría y sensibilidad a probabilidades nulas exigen un uso cuidadoso, pero con suavizado y métricas complementarias proporciona señales valiosas sobre desviaciones o drift.