Camada de Atenção em Transformers: Teoria, Prática e Código

Entenda na prática como a atenção revolucionou o processamento de linguagem.

O que é e por que atenção é tão importante?

A camada de atenção é o coração dos modelos Transformer. Ela permite que, ao processar cada token, o modelo "olhe" para todos os outros tokens da sequência e pese o quanto cada um deles é relevante para gerar a próxima saída.

Modelos anteriores (RNNs/LSTMs) só enxergavam o passado imediato. A atenção revolucionou o campo ao permitir visão global sobre a sequência.

Como a atenção funciona?

Cada palavra/token vira três vetores:

Para cada par (Q, K), calcula-se uma "pontuação" de atenção, define-se o peso de cada token, e faz-se uma soma ponderada dos Values. O resultado é um novo vetor contextualizado para cada token.

# Atenção escalada simples em NumPy
import numpy as np

def softmax(x):
    e_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
    return e_x / e_x.sum(axis=-1, keepdims=True)

# Suponha Q, K, V como matrizes (batch_size, seq_len, d_k)
def attention(Q, K, V):
    d_k = Q.shape[-1]
    scores = np.matmul(Q, K.transpose(0,2,1)) / np.sqrt(d_k)
    weights = softmax(scores)
    return np.matmul(weights, V)  # (batch_size, seq_len, d_v)
      

O segredo: Tudo pode ser calculado em lote (batch), e a fórmula se aplica para textos, imagens, áudios e mais.

Fórmula matemática:
\[ \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V \]

Visualizando a Atenção

Eu gosto de pizza "Eu" Token em foco recebe contexto de todos

Atenção: cada token considera todos os outros ao gerar sua saída.

Exemplo prático em PyTorch

Veja como calcular self-attention com apenas algumas linhas usando PyTorch. Neste exemplo, temos uma sequência simples com 3 tokens e dimensão 4.

import torch
import torch.nn.functional as F

Q = torch.rand(1, 3, 4)  # (batch, seq_len, d_k)
K = torch.rand(1, 3, 4)
V = torch.rand(1, 3, 4)
d_k = Q.size(-1)

# Scaled dot-product attention
scores = torch.matmul(Q, K.transpose(-2, -1)) / d_k ** 0.5  # (1, 3, 3)
weights = F.softmax(scores, dim=-1)
output = torch.matmul(weights, V)  # (1, 3, 4)

print("Pesos de atenção:", weights)
print("Saída contextualizada:", output)
      

Assim, você pode visualizar os pesos de atenção que cada token atribui a todos os outros — e entender, por exemplo, que “pizza” pode depender muito de “gosto” e menos de “eu”.

Multi-Head Attention: mais contexto, mais poder

Na prática, os Transformers usam diversas "cabeças" de atenção em paralelo. Cada uma aprende relações diferentes e, depois, seus resultados são combinados. Isso permite capturar diversos padrões simultaneamente.

import torch
import torch.nn as nn

multi_head = nn.MultiheadAttention(embed_dim=8, num_heads=2, batch_first=True)
x = torch.rand(1, 5, 8)  # (batch, seq_len, embedding_dim)
attn_output, attn_weights = multi_head(x, x, x)
print("Saída com Multi-Head:", attn_output.shape)
print("Pesos das heads:", attn_weights.shape)
      

Usando nn.MultiheadAttention você ganha performance e flexibilidade, sem precisar implementar tudo na mão.

Onde a atenção é aplicada?

Hoje, o conceito de atenção já foi além do texto e se tornou onipresente em IA.

Resumo e referências

A camada de atenção é uma engrenagem fundamental para IA moderna — e dominar sua teoria, exemplos e prática te coloca na frente. Se quiser se aprofundar:

Nos próximos artigos, vamos explorar:

Fique de olho!