Théorie de l'Information
“Entropie, entropie croisée, divergence KL — les maths derrière le fonctionnement des fonctions de coût”
Entropie, perte d'entropie croisée, divergence KL, information mutuelle — pourquoi la cross-entropy fonctionne comme fonction de perte.
Prérequis
Concepts Couverts
∑Formules Clés
Entropie
Surprise moyenne en bits — maximale quand tous les résultats sont équiprobables, nulle si déterministe
Perte d'Entropie Croisée
Bits attendus pour encoder des échantillons de p avec un code conçu pour q — la perte de classification
Divergence KL
Bits supplémentaires pour encoder p avec un code optimisé pour q. Toujours ≥ 0, nul ssi p=q
Information Mutuelle
Combien la connaissance de Y réduit l'incertitude sur X — sélection de variables et apprentissage de représentation
▶Simulation Interactive
Pourquoi la Théorie de l'Information Sous-tend les Fonctions de Perte ML
Quand vous entraînez un classifieur avec la perte d'entropie croisée, vous minimisez le nombre de 'bits' nécessaires pour communiquer les étiquettes réelles avec la distribution prédite du modèle. Quand un VAE minimise l'ELBO, le terme de régularisation est une divergence KL. Quand vous mesurez une division d'arbre de décision avec le gain d'information, vous calculez la réduction d'entropie. La connexion à la théorie de l'information n'est pas un accident.
Entropie croisée H(p,q) = Entropie H(p) + KL(p‖q). Puisque H(p) est fixe, minimiser l'entropie croisée revient à minimiser la divergence KL de q vers p.
Entropie : Mesurer la Surprise
Pensez à l'entropie comme la surprise moyenne dans une distribution de probabilité. Une pièce équilibrée (50/50) a une entropie H = 1 bit — vous gagnez exactement 1 bit d'information à chaque lancer. Une pièce biaisée (99/1) a une entropie quasi nulle — vous êtes rarement surpris. Application ML : les prédictions d'un modèle bien calibré sur les frontières de classe ont une entropie élevée (incertain), et ses prédictions sur des exemples clairs ont une entropie quasi nulle (confiant).
Principe d'entropie maximale : étant donné des contraintes, choisissez la distribution qui maximise l'entropie. Cela donne la distribution Normale pour les contraintes moyenne+variance.
Entropie, Entropie Croisée & Divergence KL en Pratique
import numpy as np from scipy.special import xlogy class="tok-comment"># gère class="tok-num">0 * log(class="tok-num">0) = class="tok-num">0 proprement from scipy.stats import entropy as scipy_entropy import matplotlib.pyplot as plt def entropie(p: np.ndarray, base: float = class="tok-num">2) -> float: class="tok-str">"""Entropie de Shannon H(p) en bits (base=class="tok-num">2) ou nats (base=e)""" p = np.asarray(p, dtype=float) p = p[p > class="tok-num">0] class="tok-comment"># class="tok-num">0 * log(class="tok-num">0) = class="tok-num">0 par convention return -np.sum(p * np.log(p) / np.log(base)) def entropie_croisee(p: np.ndarray, q: np.ndarray, eps: float = class="tok-num">1e-12) -> float: class="tok-str">"""H(p, q) = -sum p * log(q)""" p, q = np.asarray(p, dtype=float), np.asarray(q, dtype=float) return -np.sum(p * np.log(q + eps)) def divergence_kl(p: np.ndarray, q: np.ndarray, eps: float = class="tok-num">1e-12) -> float: class="tok-str">"""KL(p||q) — NON symétrique""" p, q = np.asarray(p, dtype=float), np.asarray(q, dtype=float) masque = p > class="tok-num">0 return np.sum(p[masque] * np.log((p[masque] + eps) / (q[masque] + eps))) class="tok-comment"># ── class="tok-num">1. Entropie de diverses distributions ───────────────────────────────────── print(class="tok-str">"Exemples d'entropie (bits) :") print(fclass="tok-str">" Pièce équitable [class="tok-num">0.5, class="tok-num">0.5]: {entropie([class="tok-num">0.5, class="tok-num">0.5]):.4f}") class="tok-comment"># class="tok-num">1.0 bit print(fclass="tok-str">" Pièce biaisée [class="tok-num">0.99, class="tok-num">0.01]: {entropie([class="tok-num">0.99, class="tok-num">0.01]):.4f}") class="tok-comment"># ≈ class="tok-num">0.08 bits print(fclass="tok-str">" Uniforme class="tok-num">8 classes : {entropie([class="tok-num">1/class="tok-num">8]*class="tok-num">8):.4f}") class="tok-comment"># class="tok-num">3.0 bits print(fclass="tok-str">" Certain [class="tok-num">1.0, class="tok-num">0.0] : {entropie([class="tok-num">1.0, class="tok-num">0.0]):.4f}") class="tok-comment"># class="tok-num">0.0 bits class="tok-comment"># ── class="tok-num">2. Perte dclass="tok-str">'entropie croisée (classification) ───────────────────────────── class="tok-comment"># Vérité terrain (one-hot) : chat p_vrai = np.array([class="tok-num">1., class="tok-num">0., class="tok-num">0.]) class="tok-comment"># chat q_bon = np.array([class="tok-num">0.8, class="tok-num">0.1, class="tok-num">0.1]) class="tok-comment"># confiant et correct q_mauvais = np.array([class="tok-num">0.1, class="tok-num">0.8, class="tok-num">0.1]) class="tok-comment"># confiant et incorrect q_incertain = np.array([class="tok-num">0.4, class="tok-num">0.3, class="tok-num">0.3]) class="tok-comment"># incertain mais penche vers le bon print("\nPertes d'entropie croisée :class="tok-str">") print(f" Bonne prédiction : {entropie_croisee(p_vrai, q_bon):.4f}class="tok-str">") print(f" Mauvaise prédiction : {entropie_croisee(p_vrai, q_mauvais):.4f}class="tok-str">") print(f" Incertain mais ok : {entropie_croisee(p_vrai, q_incertain):.4f}class="tok-str">") class="tok-comment"># H(p,q) = H(p) + KL(p||q). Comme H(p)=class="tok-num">0 pour one-hot : EC = KL(p||q) print(f" KL(p_vrai||q_bon) = {divergence_kl(p_vrai, q_bon):.4f}class="tok-str">") class="tok-comment"># ── class="tok-num">3. Divergence KL : asymétrie ───────────────────────────────────────────── p = np.array([class="tok-num">0.6, class="tok-num">0.3, class="tok-num">0.1]) q = np.array([class="tok-num">0.3, class="tok-num">0.5, class="tok-num">0.2]) print(f"\nKL(p||q) = {divergence_kl(p,q):.4f}class="tok-str">") print(f"KL(q||p) = {divergence_kl(q,p):.4f}class="tok-str">") class="tok-comment"># différent — pas une distance class="tok-comment"># ── class="tok-num">4. Gain d'information dans les arbres de décision ──────────────────────── def gain_information(parent, gauche, droite): n = len(parent) n_g, n_d = len(gauche), len(droite) h_p = scipy_entropy(np.bincount(parent) / n, base=class="tok-num">2) h_g = scipy_entropy(np.bincount(gauche) / n_g, base=class="tok-num">2) if n_g > class="tok-num">0 else class="tok-num">0 h_d = scipy_entropy(np.bincount(droite) / n_d, base=class="tok-num">2) if n_d > class="tok-num">0 else class="tok-num">0 return h_p - (n_g/n * h_g + n_d/n * h_d) class="tok-comment"># class="tok-num">10 échantillons : class="tok-num">6 classe-class="tok-num">0, class="tok-num">4 classe-class="tok-num">1 parent = np.array([class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">1,class="tok-num">1,class="tok-num">1,class="tok-num">1]) gauche = np.array([class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">0,class="tok-num">1]) droite = np.array([class="tok-num">0,class="tok-num">0,class="tok-num">1,class="tok-num">1,class="tok-num">1]) print(f"\nGain d'information : {gain_information(parent, gauche, droite):.4f} bits")
Divergence KL dans le ML Moderne
La divergence KL apparaît partout dans le ML moderne : (1) Perte VAE = perte de reconstruction + KL(q(z|x) ‖ p(z)). (2) RL politique — TRPO/PPO contraignent le KL entre ancienne et nouvelle politique. (3) Distillation de connaissances — minimiser le KL entre les sorties de l'étudiant et du professeur. (4) RLHF — pénalité KL pour éviter que le modèle s'éloigne trop du modèle de base.
KL directe (mode-covering) vs KL inverse (mode-seeking) est un choix de conception fondamental dans les modèles génératifs — les VAEs utilisent la directe, les GANs utilisent implicitement l'inverse.
?Vérification des Connaissances
La progression est sauvegardée dans votre navigateur — aucun compte requis.
Besoin d'un ingénieur IA ou data scientist ?
Je conçois des modèles ML sur mesure, des agents IA, de la vision par ordinateur et de l'automatisation — de l'idée à la production.