Phase 01 - Lesson 09
Teoria dá Informação
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
A teoria dá informação mede surpresa. As funções de perda são construidas sobre ela.
Tipo: Learn Linguagem: Python Pré-requisitos: Fase 1, Lição 06 (Probabilidade) Tempo: ~60 minutos
Objetivos de Aprendizagem
- Calcular entropia, entropia cruzada e divergência KL do zero e explicar a relação entre elas
- Derivar por que minimizar a perda de entropia cruzada é equivalente a maximizar a log-verossimilhanca
- Calcular a informação mutua entre features é um alvo para ranquear a importancia das features
- Explicar perplexidade como o tamanho efetivo de vocabulário do qual um modelo de linguagem escolhe
O Problema
Você chama CrossEntropyLoss() em todo modelo de classificacao que treina. Você vê "perplexidade" em todo artigo de modelo de linguagem. Você lê sobre divergência KL em VAEs, destilacao e RLHF. Esses não são conceitos desconexos. Eles são todos a mesma ideia usando chapeus diferentes.
A teoria dá informação te dá a linguagem para raciocinar sobre incerteza, compressão e predição. Claude Shannon a inventou em 1948 para resolver problemas de comúnicação. Acontece que treinar uma rede neural é um problema de comúnicação: o modelo está tentando transmitir o rótulo correto atraves de um canal ruidoso de pesos aprendidos.
Está lição constrói cada formula do zero para que você veja de onde elas vêm e por que funcionam.
O Conceito
Conteudo de Informação (Surpresa)
Quando algo improvavel acontece, isso carrega mais informação. Uma moeda caindo cara? Não surpreendente. Ganhar na loteria? Muito surpreendente.
O conteudo de informação de um evento com probabilidade p e:
I(x) = -log(p(x))
Usar log na base 2 te dá bits. Usar log natural te dá nats. Mesma ideia, unidades diferentes.
Event Probability Surprise (bits)
Fair coin heads 0.5 1.0
Rolling a 6 0.167 2.58
1-in-1000 event 0.001 9.97
Certain event 1.0 0.0
Eventos certos carregam zero informação. Você já sabia que aconteceriam.
Entropia (Surpresa Média)
Entropia é a surpresa esperada ao longo de todos os resultados possíveis de uma distribuição.
H(P) = -sum( p(x) * log(p(x)) ) for all x
Uma moeda justa tem entropia máxima para uma variavel binária: 1 bit. Uma moeda viciada (99% cara) tem baixa entropia: 0,08 bits. Você já sabe o que vai acontecer, então cada lancamento te diz quase nada.
Fair coin: H = -(0.5 * log2(0.5) + 0.5 * log2(0.5)) = 1.0 bit
Biased coin: H = -(0.99 * log2(0.99) + 0.01 * log2(0.01)) = 0.08 bits
Entropia mede a incerteza irredutivel em uma distribuição. Você não consegue comprimir abaixo dela.
Entropia Cruzada (A Função de Perda que Você Usa Todo Dia)
A entropia cruzada mede a surpresa média quando você usa a distribuição Q para codificar eventos que na verdade vêm dá distribuição P.
H(P, Q) = -sum( p(x) * log(q(x)) ) for all x
P é a distribuição verdadeira (os rótulos). Q são as predições do seu modelo. Se Q corresponde a P perfeitamente, a entropia cruzada é igual a entropia. Qualquer discrepancia a torna maior.
Na classificacao, P é um vetor one-hot (a classe verdadeira tem probabilidade 1, todo o resto 0). Isso simplifica a entropia cruzada para:
H(P, Q) = -log(q(true_class))
Essa é a formula completa dá perda de entropia cruzada para classificacao. Maximize a probabilidade prevista dá classe correta.
Divergência KL (Distância Entre Distribuições)
A divergência KL mede quanta surpresa extra você obtém ao usar Q em vez de P.
D_KL(P || Q) = sum( p(x) * log(p(x) / q(x)) ) for all x
= H(P, Q) - H(P)
Entropia cruzada e entropia mais divergência KL. Como a entropia dá distribuição verdadeira é constante durante o treinamento, minimizar a entropia cruzada é o mesmo que minimizar a divergência KL. Você está empurrando a distribuição do seu modelo em direção a distribuição verdadeira.
A divergência KL não é simétrica: D_KL(P || Q) != D_KL(Q || P). Ela não é uma métrica de distância verdadeira.
Informação Mutua
A informação mutua mede quanto conhecer uma variavel te diz sobre outra.
I(X; Y) = H(X) - H(X|Y)
= H(X) + H(Y) - H(X, Y)
Se X e Y são independentes, a informação mutua é zero. Conhecer uma não te diz nada sobre a outra. Se elas são perfeitamente correlacionadas, a informação mutua é igual a entropia de qualquer uma das variaveis.
Na seleção de features, alta informação mutua entre uma feature é o alvo significa que a feature é útil. Baixa informação mutua significa que ela e ruido.
Entropia Condicional
H(Y|X) mede quanta incerteza permanece sobre Y depois que você observa X.
H(Y|X) = H(X,Y) - H(X)
Dois extremos:
- Se X determina completamente Y, então H(Y|X) = 0. Conhecer X elimina toda a incerteza sobre Y. Exemplo: X = temperatura em Celsius, Y = temperatura em Fahrenheit.
- Se X não te diz nada sobre Y, então H(Y|X) = H(Y). Conhecer X não reduz a sua incerteza de jeito nenhum. Exemplo: X = lancamento de moeda, Y = clima de amanha.
A entropia condicional e sempre não-negativa e nunca excede H(Y):
0 <= H(Y|X) <= H(Y)
Em machine learning, a entropia condicional aparece em arvores de decisão. Em cada split, o algoritmo escolhe a feature X que minimiza H(Y|X) -- a feature que remove a maior incerteza sobre o rótulo Y.
Entropia Conjunta
H(X,Y) é a entropia dá distribuição conjunta de X e Y juntos.
H(X,Y) = -sum sum p(x,y) * log(p(x,y)) for all x, y
Propriedade chave:
H(X,Y) <= H(X) + H(Y)
A igualdade vale quando X e Y são independentes. Se elas compartilham informação, a entropia conjunta é menor que a soma das entropias individuais. A entropia "faltante" é exatamente a informação mutua.
graph TD
subgraph "Information Venn Diagram"
direction LR
HX["H(X)"]
HY["H(Y)"]
MI["I(X;Y)<br/>Mutual<br/>Information"]
HXgY["H(X|Y)<br/>= H(X) - I(X;Y)"]
HYgX["H(Y|X)<br/>= H(Y) - I(X;Y)"]
HXY["H(X,Y) = H(X) + H(Y) - I(X;Y)"]
end
HXgY --- MI
MI --- HYgX
HX -.- HXgY
HX -.- MI
HY -.- MI
HY -.- HYgX
HXY -.- HXgY
HXY -.- MI
HXY -.- HYgX
As relações:
- H(X,Y) = H(X) + H(Y|X) = H(Y) + H(X|Y)
- I(X;Y) = H(X) - H(X|Y) = H(Y) - H(Y|X)
- H(X,Y) = H(X) + H(Y) - I(X;Y)
Informação Mutua (Mergulho Profundo)
A informação mutua I(X;Y) quantifica quanto conhecer uma variavel reduz a incerteza sobre a outra.
I(X;Y) = H(X) - H(X|Y)
= H(Y) - H(Y|X)
= H(X) + H(Y) - H(X,Y)
= sum sum p(x,y) * log(p(x,y) / (p(x) * p(y)))
Propriedades:
- I(X;Y) >= 0 sempre. Você nunca perde informação ao observar algo.
- I(X;Y) = 0 se e somente se X e Y são independentes.
- I(X;Y) = I(Y;X). Ela é simétrica, diferente dá divergência KL.
- I(X;X) = H(X). Uma variavel compartilha toda a sua informação consigo mesma.
Informação mutua para seleção de features. Em ML, você quer features que sejam informativas sobre o alvo. A informação mutua te dá uma forma fundamentada de ranquear features:
- Para cada feature X_i, calcule I(X_i; Y) onde Y é a variavel alvo.
- Ranqueie as features pelo score de MI.
- Mantenha as top k features.
Isso funciona para qualquer relação entre feature e alvo -- linear, não-linear, monotônica ou não. A correlação só captura relações lineares. A MI captura tudo.
| Method | Detects | Computational cost | Handles categorical? |
|---|---|---|---|
| Pearson correlation | Relações lineares | O(n) | Não |
| Spearman correlation | Relações monotônicas | O(n log n) | Não |
| Mutual information | Qualquer dependência estatística | O(n log n) com binning | Sim |
Label Smoothing e Entropia Cruzada
A classificacao padrão usa alvos rigidos: [0, 0, 1, 0]. A classe verdadeira recebe probabilidade 1, todo o resto recebe 0. O label smoothing substitui esses por alvos suaves:
soft_target = (1 - epsilon) * hard_target + epsilon / num_classes
Com epsilon = 0.1 e 4 classes:
- Hard target: [0, 0, 1, 0]
- Soft target: [0.025, 0.025, 0.925, 0.025]
De uma perspectiva de teoria dá informação, o label smoothing aumenta a entropia dá distribuição alvo. Alvos one-hot rigidos tem entropia 0 -- não ha incerteza. Alvos suaves tem entropia positiva.
Por que isso ajuda:
- Impede o modelo de levar os logits a valores extremos (logits infinitos seriam necessarios para corresponder perfeitamente a um alvo one-hot sob entropia cruzada)
- Atua como regularização: o modelo não pode ter 100% de confiança
- Melhora a calibração: as probabilidades previstas refletem melhor a incerteza verdadeira
- Reduz a diferença entre o comportamento de treinamento e de inferencia
A perda de entropia cruzada com label smoothing se torna:
L = (1 - epsilon) * CE(hard_target, prediction) + epsilon * H_uniform(prediction)
O segundo termo penaliza predições que estão longe do uniforme -- uma regularização direta sobre a confiança.
Por que a Entropia Cruzada e A Perda de Classificacao
Três perspectivas, a mesma conclusao.
Visao dá teoria dá informação. A entropia cruzada mede quantos bits você desperdica ao usar a distribuição do seu modelo em vez dá distribuição verdadeira. Minimizá-la torna o seu modelo o codificador mais eficiente dá realidade.
Visao de máxima verossimilhanca. Para N amostras de treinamento com classes verdadeiras y_i:
Likelihood = product( q(y_i) )
Log-likelihood = sum( log(q(y_i)) )
Negative log-likelihood = -sum( log(q(y_i)) )
Essa ultima linha é a perda de entropia cruzada. Minimizar a entropia cruzada = maximizar a verossimilhanca dos dados de treinamento sob o seu modelo.
Visao do gradiente. O gradiente dá entropia cruzada em relação aos logits e simplesmente (predicted - true). Limpo, estável é rápido de calcular.É por isso que ela combina perfeitamente com softmax.
Bits vs Nats
A única diferença é a base do log.
log base 2 -> bits (information theory tradition)
log base e -> nats (machine learning convention)
log base 10 -> hartleys (rarely used)
1 nat = 1/ln(2) bits = 1.4427 bits. PyTorch e TensorFlow usam log natural (nats) por padrão.
Perplexidade
A perplexidade é o exponencial dá entropia cruzada. Ela te diz o número efetivo de escolhas igualmente prováveis entre as quais o modelo está incerto.
Perplexity = 2^H(P,Q) (if using bits)
Perplexity = e^H(P,Q) (if using nats)
Um modelo de linguagem com perplexidade 50 está, em média, tao confuso quanto se tivesse que escolher uniformemente entre 50 possíveis próximos tokens. Menor é melhor.
O GPT-2 atingiu perplexidade ~30 em benchmarks comuns. Modelos modernos estão na casa dos dígitos únicos para dominios bem representados.
Construa
Passo 1: Conteudo de informação e entropia
import math
def information_content(p, base=2):
if p <= 0 or p > 1:
return float('inf') if p <= 0 else 0.0
return -math.log(p) / math.log(base)
def entropy(probs, base=2):
return sum(
p * information_content(p, base)
for p in probs if p > 0
)
fair_coin = [0.5, 0.5]
biased_coin = [0.99, 0.01]
fair_die = [1/6] * 6
print(f"Fair coin entropy: {entropy(fair_coin):.4f} bits")
print(f"Biased coin entropy: {entropy(biased_coin):.4f} bits")
print(f"Fair die entropy: {entropy(fair_die):.4f} bits")
Passo 2: Entropia cruzada e divergência KL
def cross_entropy(p, q, base=2):
total = 0.0
for pi, qi in zip(p, q):
if pi > 0:
if qi <= 0:
return float('inf')
total += pi * (-math.log(qi) / math.log(base))
return total
def kl_divergence(p, q, base=2):
return cross_entropy(p, q, base) - entropy(p, base)
true_dist = [0.7, 0.2, 0.1]
good_model = [0.6, 0.25, 0.15]
bad_model = [0.1, 0.1, 0.8]
print(f"Entropy of true dist: {entropy(true_dist):.4f} bits")
print(f"CE (good model): {cross_entropy(true_dist, good_model):.4f} bits")
print(f"CE (bad model): {cross_entropy(true_dist, bad_model):.4f} bits")
print(f"KL divergence (good): {kl_divergence(true_dist, good_model):.4f} bits")
print(f"KL divergence (bad): {kl_divergence(true_dist, bad_model):.4f} bits")
Passo 3: Entropia cruzada como perda de classificacao
def softmax(logits):
max_logit = max(logits)
exps = [math.exp(z - max_logit) for z in logits]
total = sum(exps)
return [e / total for e in exps]
def cross_entropy_loss(true_class, logits):
probs = softmax(logits)
return -math.log(probs[true_class])
logits = [2.0, 1.0, 0.1]
true_class = 0
probs = softmax(logits)
loss = cross_entropy_loss(true_class, logits)
print(f"Logits: {logits}")
print(f"Softmax: {[f'{p:.4f}' for p in probs]}")
print(f"True class: {true_class}")
print(f"Loss: {loss:.4f} nats")
print(f"Perplexity: {math.exp(loss):.2f}")
Passo 4: Entropia cruzada é igual a log-verossimilhanca negativa
import random
random.seed(42)
n_samples = 1000
n_classes = 3
true_labels = [random.randint(0, n_classes - 1) for _ in range(n_samples)]
model_logits = [[random.gauss(0, 1) for _ in range(n_classes)] for _ in range(n_samples)]
ce_loss = sum(
cross_entropy_loss(label, logits)
for label, logits in zip(true_labels, model_logits)
) / n_samples
nll = -sum(
math.log(softmax(logits)[label])
for label, logits in zip(true_labels, model_logits)
) / n_samples
print(f"Cross-entropy loss: {ce_loss:.6f}")
print(f"Negative log-likelihood: {nll:.6f}")
print(f"Difference: {abs(ce_loss - nll):.2e}")
Passo 5: Informação mutua
def mutual_information(joint_probs, base=2):
rows = len(joint_probs)
cols = len(joint_probs[0])
margin_x = [sum(joint_probs[i][j] for j in range(cols)) for i in range(rows)]
margin_y = [sum(joint_probs[i][j] for i in range(rows)) for j in range(cols)]
mi = 0.0
for i in range(rows):
for j in range(cols):
pxy = joint_probs[i][j]
if pxy > 0:
mi += pxy * math.log(pxy / (margin_x[i] * margin_y[j])) / math.log(base)
return mi
independent = [[0.25, 0.25], [0.25, 0.25]]
dependent = [[0.45, 0.05], [0.05, 0.45]]
print(f"MI (independent): {mutual_information(independent):.4f} bits")
print(f"MI (dependent): {mutual_information(dependent):.4f} bits")
Use
Os mesmos conceitos usando NumPy, do jeito que você vai usá-los na prática:
import numpy as np
def np_entropy(p):
p = np.asarray(p, dtype=float)
mask = p > 0
result = np.zeros_like(p)
result[mask] = p[mask] * np.log(p[mask])
return -result.sum()
def np_cross_entropy(p, q):
p, q = np.asarray(p, dtype=float), np.asarray(q, dtype=float)
mask = p > 0
return -(p[mask] * np.log(q[mask])).sum()
def np_kl_divergence(p, q):
return np_cross_entropy(p, q) - np_entropy(p)
true = np.array([0.7, 0.2, 0.1])
pred = np.array([0.6, 0.25, 0.15])
print(f"Entropy: {np_entropy(true):.4f} nats")
print(f"Cross-ent: {np_cross_entropy(true, pred):.4f} nats")
print(f"KL div: {np_kl_divergence(true, pred):.4f} nats")
Você construiu do zero o que torch.nn.CrossEntropyLoss() faz internamente. Agora você sabe por que a perda cai durante o treinamento: a distribuição prevista do seu modelo está ficando mais próxima dá distribuição verdadeira, medida em nats de informação desperdicada.
Exercícios
Calcule a entropia do alfabeto ingles assumindo distribuição uniforme (26 letras). Depois estime-a usando frequências reais de letras. Qual é maior e por que?
Um modelo gera logits [5.0, 2.0, 0.5] para uma amostra com classe verdadeira 1. Calcule a perda de entropia cruzada à mão, depois verifique com a sua função
cross_entropy_loss. Quais logits dariam perda zero?Mostre que a divergência KL não é simétrica. Escolha duas distribuições P e Q e calcule D_KL(P || Q) e D_KL(Q || P). Explique por que elas diferem.
Construa uma função que calcule a perplexidade para uma sequência de predições de tokens. Dada uma lista de pares (true_token_index, predicted_logits), retorne a perplexidade dá sequência.
Termos-Chave
| Term | What people say | What it actually means |
|---|---|---|
| Information content | "Surpresa" | O número de bits (ou nats) necessarios para codificar um evento: -log(p) |
| Entropy | "Aleatoriedade" | A surpresa média ao longo de todos os resultados de uma distribuição. Mede a incerteza irredutivel. |
| Cross-entropy | "A função de perda" | Surpresa média ao usar a distribuição do modelo Q para codificar eventos dá distribuição verdadeira P. |
| KL divergence | "Distância entre distribuições" | Bits extras desperdicados ao usar Q em vez de P. Igual a entropia cruzada menos entropia. Não simétrica. |
| Mutual information | "Quao relacionados são X e Y" | Redução na incerteza sobre X ao conhecer Y. Zero significa independente. |
| Softmax | "Transformar logits em probabilidades" | Exponencia e normaliza. Mapeia qualquer vetor de valores reais para uma distribuição de probabilidade valida. |
| Perplexity | "Quao confuso o modelo está" | Exponencial dá entropia cruzada. O tamanho efetivo de vocabulário do qual o modelo escolhe a cada passo. |
| Bits | "Unidade de Shannon" | Informação medida com log na base 2. Um bit resolve um lancamento de moeda justa. |
| Nats | "Unidade do ML" | Informação medida com log natural. Usada por PyTorch e TensorFlow por padrão. |
| Negative log-likelihood | "Perda NLL" | Identica a perda de entropia cruzada para rótulos one-hot. Minimizá-la maximiza a probabilidade de predições corretas. |
Leitura Adicional
- Shannon 1948: A Mathematical Theory of Commúnication - o artigo original, ainda legível
- Visual Information Theory (Chris Olah) - a melhor explicacao visual de entropia e divergência KL
- PyTorch CrossEntropyLoss docs - como o framework implementa o que você acabou de construir