Introduzione: Misurare l'Informazione
La teoria dell'informazione, fondata da Claude Shannon nel 1948, ci da gli strumenti per quantificare l'incertezza, misurare la quantità di informazione contenuta in un messaggio e valutare quanto bene un modello approssima la realta. In machine learning, questi concetti appaiono ovunque: la cross-entropy e la loss function di default per la classificazione, la KL divergence e al cuore dei VAE e del knowledge distillation.
Cosa Imparerai
- Information content: la sorpresa come -log(p)
- Entropia: misura dell'incertezza di una distribuzione
- Cross-entropy: la loss più usata per la classificazione
- KL divergence: distanza asimmetrica tra distribuzioni
- Mutual information: dipendenza tra variabili
- Perplexity e le sue connessioni con i modelli di linguaggio
Information Content: La Sorpresa
L'information content (o self-information) di un evento con probabilità p misura quanto e "sorprendente" quell'evento:
Intuizione: un evento molto probabile (P \\approx 1) porta poca informazione (bassa sorpresa). Un evento raro (P \\approx 0) porta molta informazione (alta sorpresa). L'unita in base 2 e il bit: un bit e la quantità di informazione di un lancio equo di una moneta.
Entropia: L'Incertezza Media
L'entropia e il valore atteso dell'information content, ovvero la sorpresa media di una distribuzione:
Per una distribuzione continua:
Proprietà fondamentali:
- H(X) \\geq 0 sempre (l'incertezza non e mai negativa)
- H(X) = 0 solo se X e deterministica (un solo evento ha probabilità 1)
- H(X) e massima per la distribuzione uniforme (massima incertezza)
Esempio: per una moneta equa (P(T) = P(C) = 0.5), l'entropia e H = -0.5\\log_2(0.5) - 0.5\\log_2(0.5) = 1 bit. Per una moneta truccata con P(T) = 0.99, l'entropia e circa 0.08 bit: quasi nessuna incertezza, sappiamo quasi sempre il risultato.
import numpy as np
def entropy(probs):
"""Calcola entropia in bit (log base 2)."""
probs = np.array(probs)
probs = probs[probs > 0] # Evita log(0)
return -np.sum(probs * np.log2(probs))
# Moneta equa
print(f"Moneta equa: H = {entropy([0.5, 0.5]):.4f} bit")
# Moneta truccata
print(f"Moneta truccata (0.99): H = {entropy([0.99, 0.01]):.4f} bit")
# Dado a 6 facce (uniforme)
print(f"Dado equo: H = {entropy([1/6]*6):.4f} bit")
# Dado truccato (3 esce il 50%)
probs_loaded = [0.1, 0.1, 0.5, 0.1, 0.1, 0.1]
print(f"Dado truccato: H = {entropy(probs_loaded):.4f} bit")
Cross-Entropy: La Loss della Classificazione
La cross-entropy tra la distribuzione vera p e la distribuzione predetta dal modello q misura quanti bit servono in media per codificare dati da p usando il codice ottimale per q:
Nella classificazione, p e la distribuzione target (one-hot) e q e l'output del softmax. Per un singolo campione con label y (one-hot) e predizione \\hat{y}:
Per classificazione binaria, si semplifica nella binary cross-entropy:
Connessione fondamentale: minimizzare la cross-entropy equivale a massimizzare la log-likelihood del modello. Questo spiega perchè la cross-entropy e la loss naturale per la classificazione: stiamo cercando il modello che assegna la massima probabilità ai dati osservati.
import numpy as np
def cross_entropy(p, q):
"""Cross-entropy H(p, q) usando logaritmo naturale."""
q = np.clip(q, 1e-15, 1 - 1e-15) # Evita log(0)
return -np.sum(p * np.log(q))
def binary_cross_entropy(y_true, y_pred):
"""Binary cross-entropy per un singolo campione."""
y_pred = np.clip(y_pred, 1e-15, 1 - 1e-15)
return -(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
# Classificazione a 3 classi
y_true = np.array([0, 0, 1]) # Classe 3
# Predizione buona
y_pred_good = np.array([0.05, 0.05, 0.90])
print(f"Buona predizione: CE = {cross_entropy(y_true, y_pred_good):.4f}")
# Predizione mediocre
y_pred_mid = np.array([0.2, 0.3, 0.5])
print(f"Predizione media: CE = {cross_entropy(y_true, y_pred_mid):.4f}")
# Predizione sbagliata
y_pred_bad = np.array([0.7, 0.2, 0.1])
print(f"Predizione errata: CE = {cross_entropy(y_true, y_pred_bad):.4f}")
# Binary cross-entropy
print(f"\nBCE(y=1, pred=0.9) = {binary_cross_entropy(1, 0.9):.4f}")
print(f"BCE(y=1, pred=0.5) = {binary_cross_entropy(1, 0.5):.4f}")
print(f"BCE(y=1, pred=0.1) = {binary_cross_entropy(1, 0.1):.4f}")
KL Divergence: Distanza tra Distribuzioni
La KL divergence (Kullback-Leibler) misura quanto una distribuzione q differisce da una distribuzione di riferimento p:
Proprietà importanti:
- D_{\\text{KL}}(p \\| q) \\geq 0 sempre (disuguaglianza di Gibbs)
- D_{\\text{KL}}(p \\| q) = 0 se e solo se p = q
- Non e simmetrica: D_{\\text{KL}}(p \\| q) \\neq D_{\\text{KL}}(q \\| p)
La relazione H(p, q) = H(p) + D_{\\text{KL}}(p \\| q) ci dice che la cross-entropy e l'entropia di p più la KL divergence. Poichè H(p) e costante (non dipende dal modello), minimizzare la cross-entropy equivale a minimizzare la KL divergence.
KL Divergence nei VAE
Nei Variational Autoencoders, la loss include un termine di KL divergence che forza la distribuzione latente ad essere vicina a una Gaussiana standard:
import numpy as np
def kl_divergence(p, q):
"""KL divergence D_KL(p || q)."""
p = np.array(p, dtype=float)
q = np.array(q, dtype=float)
mask = p > 0
return np.sum(p[mask] * np.log(p[mask] / q[mask]))
# Due distribuzioni su 4 classi
p = np.array([0.25, 0.25, 0.25, 0.25]) # Uniforme
q1 = np.array([0.3, 0.2, 0.3, 0.2]) # Leggermente diversa
q2 = np.array([0.9, 0.03, 0.04, 0.03]) # Molto diversa
print(f"KL(p || q1) = {kl_divergence(p, q1):.6f}")
print(f"KL(p || q2) = {kl_divergence(p, q2):.6f}")
# Asimmetria della KL
print(f"\nKL(p || q1) = {kl_divergence(p, q1):.6f}")
print(f"KL(q1 || p) = {kl_divergence(q1, p):.6f}")
# KL per VAE (Gaussiana vs standard normal)
def kl_gaussian(mu, log_var):
"""KL divergence tra N(mu, sigma^2) e N(0, 1)."""
return -0.5 * np.sum(1 + log_var - mu**2 - np.exp(log_var))
mu = np.array([0.5, -0.3, 0.1])
log_var = np.array([-0.5, 0.2, -0.1])
print(f"\nKL(N(mu,sigma^2) || N(0,1)) = {kl_gaussian(mu, log_var):.4f}")
Mutual Information
La mutual information misura quanta informazione una variabile aleatoria fornisce su un'altra:
Se I(X; Y) = 0, le variabili sono indipendenti. In ML, la mutual information e usata per: feature selection (selezionare le feature più informative), valutazione del clustering, e come obiettivo nell'InfoNCE loss del contrastive learning.
Perplexity: Valutare i Modelli di Linguaggio
La perplexity e una metrica standard per valutare i language model. E definita come l'esponenziale della cross-entropy media per token:
Una perplexity di k significa che, in media, il modello e "confuso" come se dovesse scegliere uniformemente tra k opzioni ad ogni passo. Più bassa e la perplexity, migliore e il modello.
Riepilogo e Connessioni con il ML
Punti Chiave da Ricordare
- Entropia H(X): misura l'incertezza, massima per distribuzione uniforme
- Cross-entropy H(p,q): la loss standard per classificazione
- KL divergence: distanza (asimmetrica) tra distribuzioni, usata nei VAE
- Minimizzare cross-entropy = massimizzare log-likelihood = minimizzare KL
- Mutual information: misura dipendenza, usata in feature selection e contrastive learning
- Perplexity: metrica standard per language model, più bassa e meglio e
Nel Prossimo Articolo: esploreremo PCA e riduzione dimensionale. Vedremo come la matrice di covarianza, gli autovettori e l'SVD permettono di comprimere i dati mantenendo la maggior parte dell'informazione.







