Representação de Texto

Visão geral: por que “representação de texto” importa

Modelos de aprendizado de máquina (machine learning) consomem números, não texto bruto. Representação de texto (text representation) é o conjunto de técnicas que transforma uma string como:

“O filme foi surpreendentemente bom.”

em uma estrutura numérica com a qual um modelo consegue calcular — tipicamente um vetor, uma sequência de IDs de token (token IDs) ou uma matriz de embeddings. A representação que você escolhe afeta fortemente:

  • Quais informações o modelo pode usar (presença de palavras vs ordem das palavras vs significado)
  • Generalização para novos domínios e novo vocabulário
  • Computação e memória (vetores esparsos de alta dimensionalidade vs embeddings densos de baixa dimensionalidade)
  • Interpretabilidade (contagens transparentes vs características aprendidas opacas)

Historicamente, o processamento de linguagem natural (PLN, NLP) migrou de características esparsas baseadas em contagem (saco de palavras, n-gramas, TF‑IDF) para representações densas aprendidas (embeddings de palavras) e depois para embeddings contextuais produzidos por modelos de Arquitetura Transformer (Transformer Architecture) (por exemplo, codificadores no estilo BERT e modelos de linguagem de grande porte).

Este artigo cobre essa progressão — de n-gramas a embeddings — e como essas representações viram entradas de modelos na prática.

Do texto às “unidades”: tokens, vocabulários e sequências

Antes da representação, você precisa decidir quais são as unidades básicas:

  • Caracteres (incluindo n-gramas de caracteres)
  • Palavras (tokens separados por espaço; dependente do idioma)
  • Subpalavras (subwords) (fragmentos BPE/Unigram; comuns em modelos modernos)
  • Bytes (BPE em nível de byte (byte-level BPE), robusto a texto arbitrário)

Essa etapa é chamada de tokenização (tokenization), e ela determina como o texto é segmentado e mapeado para índices. O PLN moderno tipicamente usa tokenização por subpalavras para equilibrar:

  • Tratamento de vocabulário aberto (palavras raras se quebram em pedaços)
  • Comprimentos de sequência razoáveis
  • Cobertura multilíngue

Para detalhes, veja Análise Aprofundada de Tokenização (Tokenization Deep Dive).

Uma vez tokenizado, o texto pode ser representado como:

  1. Vetores esparsos sobre um vocabulário (contagens/pesos)
  2. Vetores densos aprendidos a partir de dados (embeddings)
  3. Sequências de IDs usadas por redes neurais (IDs → consulta de embeddings → modelo)

Representações esparsas: saco de palavras, n-gramas e TF‑IDF

One-hot e saco de palavras (bag-of-words, BoW)

Um vetor one-hot (one-hot) representa um único token como um vetor de comprimento (|V|) (tamanho do vocabulário), com 1 no índice do token e 0 no restante. Para documentos, normalmente somamos esses one-hots para obter um vetor de contagens de saco de palavras (bag-of-words):

  • Ignora a ordem das palavras
  • Captura presença/frequência de palavras
  • Produz vetores esparsos de alta dimensionalidade

Exemplo:

  • Vocabulário: ["good", "movie", "surprisingly", "was"]
  • Texto: “movie was good”
  • Contagens do saco de palavras: [1, 1, 0, 1] (good=1, movie=1, surprisingly=0, was=1)

O saco de palavras funciona surpreendentemente bem para:

  • Classificação de tópicos
  • Detecção de spam
  • Tarefas simples de sentimento (especialmente com n-gramas)

N-gramas: adicionando ordem local das palavras

Uma grande limitação do saco de palavras é que ele perde a ordem das palavras. n-gramas (n-grams) corrigem parte disso contando sequências contíguas de (n) tokens:

  • Unigramas: “good”, “movie”
  • Bigramas: “not good”, “very good”
  • Trigramas: “a lot better”

Isso ajuda com fenômenos como negação:

  • “good” vs “not good” tornam-se distinguíveis se bigramas forem incluídos.

Você pode construir n-gramas em diferentes níveis:

  • n-gramas de palavras: bons para padrões locais meio sintáticos
  • n-gramas de caracteres: robustos a erros de digitação e morfologia (por exemplo, “running” vs “runner” compartilham n-gramas de caracteres)

Trade-off: valores maiores de (n) aumentam a dimensionalidade e a esparsidade.

TF‑IDF: reduzindo o peso de palavras comuns

Contagens brutas supervalorizam tokens frequentes como “the” ou “movie”. TF‑IDF (frequência do termo–frequência inversa do documento) reescala contagens pelo quão informativo um token é ao longo de documentos:

  • TF (term frequency): com que frequência um termo aparece em um documento
  • IDF (inverse document frequency): reduz o peso de termos que aparecem em muitos documentos

Intuição: uma palavra que aparece em todo documento tem pouco poder discriminativo.

Exemplo prático: TF‑IDF + classificador linear

Uma linha de base clássica e forte para classificação de texto é TF‑IDF + Regressão Logística (Logistic Regression) (ou SVM linear (Linear SVM)).

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline

texts = [
    "I loved this movie, it was great",
    "Terrible film, boring and slow",
    "Great acting and great story",
    "Worst movie I've seen"
]
labels = [1, 0, 1, 0]  # 1=positive, 0=negative

model = make_pipeline(
    TfidfVectorizer(ngram_range=(1, 2), min_df=1),
    LogisticRegression(max_iter=1000)
)

model.fit(texts, labels)
print(model.predict(["not great, pretty boring"]))

Por que isso funciona bem:

  • Modelos lineares são eficientes e estáveis
  • TF‑IDF + n-gramas captura muitos sinais lexicais úteis
  • O treinamento é rápido mesmo em grandes corpora

Truque de hashing: características esparsas de tamanho fixo sem vocabulário

Em vez de construir um vocabulário, hashing de características (feature hashing) mapeia tokens diretamente para um espaço de dimensionalidade fixa usando uma função de hash. Isso é útil quando:

  • O vocabulário é enorme ou chega em fluxo (streaming)
  • Você quer memória constante

Desvantagem: colisões (tokens diferentes podem mapear para o mesmo índice), embora isso frequentemente seja tolerável.

Semântica distribucional: embeddings densos de palavras

Vetores esparsos tratam cada palavra como independente. Embeddings densos codificam a ideia de que:

“Você conhecerá uma palavra pela companhia que ela mantém.”

Palavras usadas em contextos semelhantes devem ter vetores semelhantes. Isso é semântica distribucional (distributional semantics).

Word2Vec (CBOW / Skip-gram)

Word2Vec aprende um vetor denso para cada palavra resolvendo uma tarefa preditiva:

  • CBOW: prever uma palavra a partir do seu contexto ao redor
  • Skip-gram: prever palavras ao redor a partir de uma palavra central

Os embeddings aprendidos capturam regularidades semânticas e sintáticas (por exemplo, analogias) porque o modelo comprime padrões de coocorrência em um espaço de baixa dimensionalidade.

GloVe e a intuição de fatoração de matriz

GloVe pode ser visto como aprendendo embeddings a partir de estatísticas globais de coocorrência (uma matriz palavra-palavra de coocorrência), combinando abordagens baseadas em contagem e abordagens preditivas.

fastText: embeddings de palavras conscientes de subpalavras

fastText representa uma palavra como um saco de n-gramas de caracteres, ajudando com:

  • Palavras raras
  • Erros de digitação
  • Idiomas morfologicamente ricos

Limitações de embeddings estáticos de palavras

Embeddings estáticos atribuem um vetor por palavra, independentemente do contexto:

  • “bank” em “river bank” vs “bank account” recebe o mesmo vetor
  • Polissemia e significado específico do contexto não são modelados
  • Palavras fora do vocabulário (out-of-vocabulary, OOV) são problemáticas (mitigado por fastText/métodos de subpalavras)

Isso motiva embeddings contextuais (contextual embeddings).

Embeddings contextuais: representações a partir de codificadores Transformer

Modelos contextuais produzem embeddings que dependem do texto ao redor. Em:

“I went to the bank to deposit cash.”

o embedding de “bank” difere de:

“We sat by the bank of the river.”

Embeddings contextuais modernos são tipicamente gerados por codificadores Transformer (Transformer encoders) (do tipo BERT). Veja Arquitetura Transformer (Transformer Architecture) e Modelagem de Linguagem (Language Modeling) para os objetivos de treinamento que tornaram esses modelos eficazes.

Como embeddings contextuais são produzidos

Em alto nível:

  1. O texto é tokenizado em subpalavras (por exemplo, WordPiece/BPE)
  2. Tokens são mapeados para IDs de token
  3. IDs indexam uma matriz de embeddings (embedding matrix) (tabela de consulta aprendida)
  4. Informação posicional é adicionada (embeddings/codificações posicionais)
  5. Camadas Transformer computam representações sensíveis ao contexto

Saída: uma sequência de vetores — um por token — cada um codificando seu significado em contexto.

Embeddings de token vs embeddings de sentença

Transformers naturalmente produzem vetores em nível de token. Muitas aplicações precisam de um único vetor para um trecho, sentença ou documento. Estratégias comuns:

  • Pooling de [CLS] ([CLS] pooling) (BERT): usar o vetor do token especial de classificação
  • Pooling de média (mean pooling): fazer a média dos vetores de tokens (frequentemente forte e simples)
  • Pooling de máximo (max pooling): pegar o máximo sobre tokens (menos comum hoje)
  • Pooling por atenção (attention pooling): aprender pesos sobre tokens

A escolha depende do modelo e da tarefa; muitos modelos focados em embeddings são treinados para que um método específico de pooling produza vetores de sentença de alta qualidade.

Embeddings de sentença e documento: vetores densos para busca e similaridade

Embeddings densos tornam-se especialmente úteis quando você quer comparar textos por significado (similaridade semântica), agrupar documentos ou fazer recuperação além de correspondência exata por palavras-chave.

Codificadores duplos e treinamento contrastivo (comum hoje)

Muitos modelos modernos de embeddings são treinados como codificadores duplos (dual-encoders):

  • Codificar consulta (q) → vetor (v_q)
  • Codificar documento (d) → vetor (v_d)
  • Pontuar com produto escalar ou similaridade do cosseno

Eles frequentemente são treinados com objetivos contrastivos (contrastive objectives): aproximar pares correspondentes e afastar pares não correspondentes. Isso é fundamental para Busca Semântica (Semantic Search) e é coberto mais em Modelos de Embeddings (Embedding Models).

Exemplo prático: similaridade semântica com embeddings de sentença

Abaixo há um exemplo mínimo usando um modelo de embedding de sentenças (a API depende do seu stack; mostrado conceitualmente no estilo sentence-transformers):

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer("all-MiniLM-L6-v2")

sentences = [
    "A cat sits on the mat.",
    "A dog plays in the park.",
    "There is a feline on a rug."
]
emb = model.encode(sentences, normalize_embeddings=True)

# cosine similarity between sentence 0 and others (since normalized, dot == cosine)
sims = emb @ emb[0]
print(sims)  # higher means more similar

Isso permite:

  • Detecção de quase duplicatas
  • Agrupamento de notícias por tópico
  • Correspondência de FAQ (“How do I reset my password?” vs “I forgot my password”)
  • Recuperação densa (busca vetorial)

Recuperação densa vs esparsa (e híbridos)

Métodos esparsos como TF‑IDF ou BM25 (comuns em Recuperação de Informação (Information Retrieval)) se destacam em:

  • Correspondência exata de termos
  • Nomes próprios raros
  • Consultas por palavras-chave altamente precisas

Métodos densos se destacam em:

  • Sinônimos e paráfrases
  • Similaridade conceitual
  • Correspondências semânticas ou multilíngues (com modelos apropriados)

Muitos sistemas em produção usam recuperação híbrida (hybrid retrieval): combinar sinais esparsos e densos para robustez.

Como o texto se torna entradas de modelos em redes neurais

Para modelos neurais de PLN, a “representação” costuma ser um pipeline:

  1. Texto → tokens
  2. Tokens → IDs de token (inteiros)
  3. IDs de token → embeddings (vetores densos via consulta)
  4. Embeddings → modelo (Transformer/RNN/CNN)
  5. Saídas do modelo → cabeça de tarefa (classificação, rotulagem, geração)

Tensores-chave de entrada

Entradas comuns para codificadores baseados em Transformer:

  • input_ids: IDs de token (shape [batch, seq_len])
  • attention_mask: 1 para tokens reais, 0 para padding
  • (opcional) token_type_ids: IDs de segmento (sentença A vs B; usado em algumas variantes de BERT)

Exemplo com tokenização no estilo Hugging Face:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
batch = tokenizer(
    ["hello world", "not great, pretty boring"],
    padding=True,
    truncation=True,
    return_tensors="pt"
)

print(batch["input_ids"].shape)
print(batch["attention_mask"])

Informação posicional

Como a atenção é invariante a permutação por si só, modelos adicionam codificações/embeddings posicionais (positional encodings/embeddings) para que o modelo possa representar ordem. Arquiteturas diferentes usam:

  • Posições absolutas aprendidas
  • Posições senoidais
  • Codificações de posição relativas (comuns em modelos mais novos)

Comprimento de sequência e truncamento

Modelos têm um comprimento máximo de sequência (por exemplo, 512, 4k, 128k). Quando o texto é mais longo:

  • Truncar (risco de perder informação)
  • Dividir em blocos e fazer pooling (usar múltiplas janelas)
  • Usar modelos de contexto longo (dependente de arquitetura)

A representação de documentos longos é um desafio prático de projeto em sumarização, recuperação e IA de Documentos (Document AI).

Escolhendo uma representação: trade-offs práticos

Quando n-gramas/TF‑IDF esparsos são uma boa escolha

Use características esparsas quando você quer:

  • Linhas de base fortes com baixo custo de engenharia
  • Alta interpretabilidade (inspecionar n-gramas com maior peso)
  • Treinamento/inferência rápidos em CPU
  • Desempenho robusto para tarefas guiadas por palavras-chave (spam/tópico)

Modelos típicos:

  • Regressão logística, SVM linear
  • Naive Bayes (frequentemente forte com contagens)

Quando embeddings densos são uma boa escolha

Use embeddings densos quando você precisa:

  • Similaridade semântica e robustez a paráfrases
  • Agrupamento por significado
  • Recuperação densa / bancos de dados vetoriais
  • Aprendizado por transferência (transfer learning) com poucos dados rotulados

Modelos típicos:

  • Codificadores duplos para recuperação
  • Codificador + cabeça de classificador para ajuste fino (fine-tuning) de classificação

Quando representações contextuais em nível de token são necessárias

Use embeddings contextuais em nível de token para tarefas que exigem entendimento fino:

  • Reconhecimento de entidades nomeadas (named entity recognition)
  • Etiquetagem de classes gramaticais (part-of-speech tagging)
  • Perguntas e respostas extrativas (extractive QA)
  • Extração de relações (relation extraction)
  • Qualquer tarefa em que importa qual token significa o quê

Esses embeddings frequentemente alimentam cabeças de rotulagem de sequência (sequence labeling heads) (campos aleatórios condicionais (conditional random fields, CRF), camadas lineares) ou preditores de spans.

Armadilhas comuns e boas práticas

Incompatibilidade de vocabulário e tokenização

  • Um vocabulário de TF‑IDF construído em um domínio pode não transferir bem para outro.
  • Para modelos neurais, usar um tokenizador diferente do que o modelo pré-treinado espera pode degradar severamente o desempenho.

Boa prática: tratar tokenizador + modelo como uma unidade.

Overfitting com n-gramas de ordem alta

n-gramas grandes podem memorizar dados de treinamento:

  • Use min_df, max_df, regularização
  • Prefira bigramas em vez de (n) muito grande, a menos que você tenha muitos dados

Métricas de similaridade importam

Para embeddings:

  • Similaridade do cosseno (cosine similarity) é comum e robusta
  • Produto escalar (dot product) é equivalente ao cosseno se os vetores estiverem normalizados
  • Para recuperação, o objetivo de treinamento frequentemente determina a pontuação apropriada

Anisotropia de embeddings e escolhas de pooling

Vetores brutos de tokens de Transformer podem ser “anisotrópicos (anisotropic)” (agrupados em um cone estreito), o que pode prejudicar similaridade. Muitos modelos de embeddings de sentenças lidam com isso via treinamento e normalização.

Boa prática: usar modelos de embeddings treinados para similaridade de sentenças/recuperação (veja Modelos de Embeddings (Embedding Models)) em vez de codificadores “base” brutos.

Interpretabilidade vs desempenho

  • Modelos esparsos: fáceis de inspecionar pesos de características (“‘not good’ prediz fortemente negativo”)
  • Modelos densos: mais difíceis de interpretar; dependem mais de avaliação e sondagem

Juntando tudo: representação como uma interface entre linguagem e aprendizado

Representação de texto é a interface que determina o que seu modelo pode “ver”:

  • n-gramas / TF‑IDF: sinais lexicais, rápidos e fortes como linha de base
  • embeddings estáticos: semântica compacta, mas sem contexto
  • embeddings contextuais: significado em contexto, base do PLN moderno
  • embeddings de sentença/documento: similaridade semântica e recuperação em escala

Em sistemas reais, a melhor abordagem costuma ser iterativa:

  1. Comece com TF‑IDF + modelo linear como linha de base
  2. Passe para embeddings pré-treinados para robustez semântica
  3. Use modelos contextuais e treinamento específico da tarefa quando a tarefa exigir
  4. Combine esparso + denso para aplicações centradas em recuperação (Busca Semântica (Semantic Search), Recuperação de Informação (Information Retrieval))

À medida que os modelos evoluem, o problema central permanece o mesmo: escolher representações que preservem a informação de que sua tarefa precisa, dentro das suas restrições de latência e custo.