02-02-02 — Self-attention e multi-head attention (visual)
TL;DR
Self-attention é o mecanismo pelo qual cada token "consulta" todos os outros para montar sua representação contextual. Usa três vetores: Query (o que estou procurando), Key (o que eu ofereço), Value (o que entrego se forem compatíveis). Multi-head faz isso N vezes em paralelo, cada "cabeça" capturando um aspecto diferente da linguagem.
A analogia com banco de dados
A maneira mais intuitiva de entender Q/K/V é por analogia com um sistema de busca:
- Query (Q): A sua consulta — "o que estou procurando?"
- Key (K): O índice de cada item — "sobre o que sou eu?"
- Value (V): O conteúdo real de cada item — "o que você recebe se me selecionar"
No SQL, seria algo como: SELECT value FROM context WHERE similarity(query, key) > threshold
Mas em vez de binário (seleciona/não seleciona), attention é suave — cada token recebe uma mistura ponderada de todos os values, com pesos proporcionais à compatibilidade Q-K.
O cálculo de attention passo a passo
A fórmula completa:
import torch
import torch.nn.functional as F
import math
def attention(Q, K, V):
d_k = Q.size(-1)
# Scores: compatibilidade entre cada Q e cada K
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
# Softmax transforma scores em probabilidades (somam 1)
weights = F.softmax(scores, dim=-1)
# Output: soma ponderada dos Values
return torch.matmul(weights, V)
Exemplo concreto: pronome e referente
Frase: "O banco aprovou o empréstimo porque ele tinha boa reputação."
Para o token "ele", o mecanismo de attention calcula pesos aproximadamente assim:
O modelo "aprende" que "ele" provavelmente se refere a "banco" (não a "empréstimo") porque essas co-ocorrências aparecem nos dados de treino com essa frequência. O peso 0.72 em "banco" faz a representação de "ele" absorver contexto de "banco".
Multi-head attention: perspectivas simultâneas
Uma única cabeça de attention captura um tipo de relação. Multi-head attention roda N cabeças independentes em paralelo, cada uma com seus próprios pesos Q, K, V aprendidos.
O que cada cabeça aprende? Ninguém programa isso — emerge do treino. Pesquisas de interpretabilidade descobriram cabeças especializadas em:
- Rastrear sujeito-verbo em longas sentenças
- Identificar relações de co-referência
- Capturar proximidade posicional
- Detectar relações semânticas (hiperonímia, sinonímia)
Positional Encoding: como o modelo sabe a ordem
Self-attention é permutation-invariant — se você embaralhar os tokens, as operações Q/K/V não mudam. Para preservar a ordem, posição é injetada via positional encoding.
O Transformer original usa funções seno/coseno:
import numpy as np
def positional_encoding(seq_len, d_model):
PE = np.zeros((seq_len, d_model))
for pos in range(seq_len):
for i in range(0, d_model, 2):
PE[pos, i] = np.sin(pos / 10000 ** (2*i / d_model))
PE[pos, i+1] = np.cos(pos / 10000 ** (2*i / d_model))
return PE
LLMs modernos usam RoPE (Rotary Position Embedding) ou ALiBi — variantes que generalizam melhor para sequências mais longas do que as vistas no treino.
O encoding posicional original do Transformer generaliza mal para posições não vistas no treino. RoPE (usado em Llama, Mistral, GPT-NeoX) codifica posição de forma relativa via rotação de vetores — o que permite extensão de context window com menos degradação. É um dos motivos pelos quais modelos com context window de 128k+ são viáveis hoje.
Para N tokens, self-attention computa N × N pares de compatibilidade. Uma sequência de 32k tokens gera 1 bilhão de operações só na camada de attention — por layer. GPT-4 tem ~120 layers. Flash Attention (Dao et al., 2022) reescreveu esse cálculo para ser IO-aware, reduzindo uso de memória GPU em 10-20x sem alterar o resultado.
Como isso se conecta
Fontes
- Vaswani et al. (2017) — Attention Is All You Need — seções 3.2 e 3.3 cobrem Q/K/V e multi-head
- Dao et al. (2022) — FlashAttention: Fast and Memory-Efficient Exact Attention
- Su et al. (2021) — RoFormer: Enhanced Transformer with Rotary Position Embedding
- Elhage et al. (2021) — A Mathematical Framework for Transformer Circuits — Anthropic