Engenharia de Atributos

Visão geral

Engenharia de atributos (feature engineering) é o processo de transformar dados brutos (tabelas, logs, texto, imagens, eventos) em entradas do modelo (“atributos”) que tornam o aprendizado mais fácil, mais confiável e mais alinhado com a tarefa real de previsão. Isso inclui:

  • Criar novas variáveis (por exemplo, “dias desde o cadastro”)
  • Transformar variáveis (por exemplo, aplicar escala logarítmica à renda)
  • Codificar dados não numéricos (por exemplo, codificação one-hot de categorias)
  • Lidar com valores ausentes e outliers
  • Garantir que o cálculo de atributos corresponda ao que estará disponível no momento da previsão

Um modelo mental útil é que você está projetando uma função:

[ \phi(\text{dados brutos no momento da previsão}) \rightarrow \mathbf{x} \in \mathbb{R}^d ]

Seu modelo nunca “vê” o mundo bruto — ele só vê (\mathbf{x}). A engenharia de atributos é, portanto, uma parte importante de um fluxo de trabalho de IA Centrada em Dados (Data-Centric AI): melhorar resultados ao melhorar o que o modelo aprende.

Tão importante quanto construir atributos é evitar armadilhas comuns, especialmente vazamento de dados (data leakage), contaminação entre treino e teste (train/test contamination) e atributos que não existirão em produção.

Por que a engenharia de atributos importa (a teoria por trás da prática)

Os atributos definem o que o modelo pode aprender

Um modelo é uma classe de funções restrita. Por exemplo, um modelo linear aprende:

[ \hat{y} = \mathbf{w}^\top \mathbf{x} ]

Se a relação verdadeira for não linear nas variáveis brutas, o modelo pode falhar — a menos que você forneça atributos que tornem a relação mais fácil de representar (por exemplo, interações, logaritmos, razões, faixas por intervalos). Nesse sentido, a engenharia de atributos muda a representação para que o mapeamento desejado se torne mais simples.

Isso se conecta diretamente ao raciocínio de viés–variância:

  • Atributos melhores podem reduzir o viés (tornar padrões representáveis)
  • Mas atributos excessivamente complexos ou numerosos podem aumentar a variância (sobreajustar), especialmente com dados limitados

Bons atributos codificam “invariâncias” e “equivariância”

Muitas tarefas têm estrutura que você pode explorar:

  • Para tempo cíclico, “hora do dia” deve tratar 23 e 0 como próximos (codificação cíclica).
  • Para distâncias, latitude/longitude brutas podem ser menos úteis do que “distância até a loja mais próxima”.
  • Para texto, posições exatas de tokens podem importar menos do que o significado semântico — daí as representações vetoriais (embeddings).

Modelos de aprendizado profundo (deep learning) (por exemplo, Redes Neurais (Neural Networks), Arquitetura Transformer (Transformer Architecture)) muitas vezes aprendem representações automaticamente, mas ainda dependem de decisões a montante: tokenização (tokenization), normalização (normalization), segmentação em janelas (windowing), agregação (aggregation) e qual contexto é incluído.

Os atributos devem refletir o *momento da previsão*

Um atributo só é válido se puder ser calculado usando informações disponíveis no momento em que você fará previsões. Essa restrição de “viagem no tempo” é o principal motivo de ocorrer vazamento e a razão pela qual a engenharia de atributos está fortemente ligada ao desenho da avaliação (ver Avaliação).

Um fluxo de trabalho prático de engenharia de atributos

1) Defina a tarefa de previsão com precisão

Escreva:

  • Qual é a entidade? (usuário, transação, conta, documento)
  • Qual é o momento da previsão? (no cadastro, no checkout, fim do dia)
  • Quais dados estão disponíveis naquele momento?
  • Qual é a janela de definição do rótulo? (por exemplo, churn nos próximos 30 dias)

Isso evita a inclusão acidental de dados pós-desfecho.

2) Construa um baseline simples primeiro

Comece com um conjunto mínimo de atributos obviamente válidos. Isso cria:

  • Um teste de sanidade para vazamento (um baseline suspeitosamente alto pode ser um sinal de alerta)
  • Um ponto de referência para medir ganhos incrementais

3) Adicione atributos iterativamente com testes de ablação (ablation testing)

Adicione grupos de atributos (atributos de tempo, agregações, atributos de texto) e meça melhorias usando divisões apropriadas (aleatória, agrupada, baseada em tempo). Use ablações para entender o que realmente ajuda.

4) Torne o pré-processamento reprodutível com pipelines

Use um pipeline de processamento (pipeline) único que seja:

  • Ajustado apenas nos folds de treino
  • Aplicado de forma consistente a validação/teste/produção
  • Versionado e monitorado

Essa é uma das maneiras mais simples de evitar contaminação entre treino e teste.

Técnicas comuns de engenharia de atributos (com exemplos)

Atributos numéricos

Transformações comuns:

  • Padronização (standardization) (média 0, variância 1): frequentemente importante para modelos lineares, máquinas de vetores de suporte (SVMs), k-vizinhos mais próximos (k-NN)
  • Transformações logarítmicas / de potência (log / power transforms): estabilizam a variância, reduzem a assimetria (por exemplo, renda, contagens)
  • Recorte / winsorização (clipping / winsorizing): reduz a influência de outliers
  • Discretização em faixas (binning): converte valores contínuos em “baldes” (às vezes ajuda na interpretabilidade ou na estabilidade de árvores)

Exemplo: aplicar transformação logarítmica com segurança a um atributo de contagem assimétrico:

import numpy as np

x = np.array([0, 1, 2, 10, 200])
x_log = np.log1p(x)  # log(1 + x) handles zeros

Notas práticas:

  • Modelos baseados em árvores (tree-based models) (GBDT, random forest) frequentemente lidam com escala sem padronização.
  • Modelos lineares frequentemente se beneficiam de escalonamento e distribuições bem comportadas.

Atributos categóricos

As escolhas de codificação dependem do modelo e da cardinalidade:

  • Codificação one-hot (one-hot encoding): baseline forte para cardinalidade baixa/média
  • Codificação ordinal (ordinal encoding): apenas quando a ordem das categorias é significativa
  • Truque de hashing (hashing trick): para cardinalidade muito alta (por exemplo, URLs), com uso de memória controlado
  • Codificação por alvo / codificação pela média (target encoding / mean encoding): poderosa, mas com alto risco de vazamento se não for feita corretamente
  • Representações vetoriais (embeddings): comuns em aprendizado profundo e em alguns modelos tabulares híbridos

Principal preocupação em produção: categorias não vistas. Use codificadores com tratamento explícito (por exemplo, balde “desconhecido”).

Valores ausentes

A ausência de dados costuma ser informativa (“não fornecido” pode correlacionar com o desfecho). Abordagens comuns:

  • Imputar valores numéricos com mediana/média; categóricos com o mais frequente ou “ausente”
  • Adicionar um atributo indicador de ausência (especialmente útil para modelos lineares)

Evite calcular estatísticas de imputação usando o dataset inteiro; ajuste apenas no treino.

Atributos de tempo e data

Tempo é uma fonte frequente de vazamento oculto e deslocamento de distribuição.

Transformações comuns e seguras:

  • Partes do calendário: dia da semana, hora do dia, mês
  • Codificação cíclica (cyclical encoding) para variáveis periódicas (hora, dia da semana)
  • Atributos de “idade”: tempo desde o último evento, idade da conta
  • Atributos defasados (lag features) (séries temporais): valores anteriores, médias móveis (calculadas de forma causal)

Exemplo de codificação cíclica:

import numpy as np

hour = np.array([0, 6, 12, 18, 23])
hour_sin = np.sin(2 * np.pi * hour / 24)
hour_cos = np.cos(2 * np.pi * hour / 24)

Se você tem logs de atividade do usuário e quer “eventos nos últimos 7 dias”, garanta que a janela termine no momento da previsão (e não no fim do dataset).

Agregações e atributos “no nível da entidade” (entity-level)

Uma grande fração da engenharia de atributos no mundo real é agregar eventos:

  • Contagens: número de compras, número de chamados
  • Taxas: compras por dia, cliques por sessão
  • Recência: tempo desde a última compra
  • Diversidade: número de categorias distintas compradas
  • Estatísticas: valor médio do pedido, duração máxima de sessão

Esses atributos podem ser muito preditivos, mas precisam estar corretos no ponto no tempo (sem eventos futuros). É aqui que muitos bugs de vazamento ficam escondidos.

Atributos de texto

As abordagens vão do clássico ao profundo:

  • Saco de palavras (bag-of-words) / n-gramas (n-grams)
  • TF–IDF
  • n-gramas de caracteres (character n-grams) (robustos a erros de digitação)
  • Representações vetoriais pré-treinadas ou codificadores Transformer

A escolha depende do tamanho da tarefa, latência e se o modelo será treinado de ponta a ponta. Mesmo com Transformers, você ainda projeta a estrutura de entrada: quais campos incluir, tamanho de truncamento, normalização e se deve incluir tokens de metadados.

Atributos de interação (cruzamentos de atributos) (feature crosses)

Interações ajudam quando o efeito de uma variável depende de outra:

  • preço × desconto
  • região × categoria de produto
  • faixa de tempo de casa × tipo de plano

Modelos lineares não conseguem aprender interações a menos que você as inclua explicitamente (ou use atributos polinomiais). Modelos de árvore aprendem algumas interações naturalmente, mas cruzamentos explícitos ainda podem ajudar em espaços categóricos esparsos.

Engenharia de atributos por família de modelos (orientação prática)

Regressão linear / logística

  • Frequentemente precisa de: escalonamento, transformações logarítmicas, interações cuidadosamente desenhadas
  • Se beneficia de categóricos one-hot esparsos
  • Sensível à multicolinearidade (multicollinearity) (regularização ajuda)

Modelos baseados em árvores (Floresta Aleatória (Random Forest), XGBoost/LightGBM/CatBoost)

  • Menos sensíveis a transformações monotônicas e escalonamento
  • Lidam bem com não linearidades e interações
  • Ainda se beneficiam de: bom tratamento de ausência, agregações sem vazamento, codificações categóricas sensatas (tratamento no estilo CatBoost, codificação por alvo feita com segurança)

Modelos baseados em distância (k-NN, SVM RBF)

  • Dependem fortemente de escalonamento de atributos e métricas de distância significativas
  • Muitas vezes são prejudicados por dimensões irrelevantes ou ruidosas

Redes neurais

  • Podem aprender interações e representações vetoriais
  • Ainda exigem um desenho cuidadoso de entrada:
    • normalização para atributos numéricos
    • representações vetoriais categóricas ou hashing
    • construção de sequências para séries temporais e texto
  • Vulneráveis ao aprendizado por atalhos (shortcut learning) se atributos vazarem o rótulo ou o “aproximarem” de forma direta demais

Evitando armadilhas comuns

Vazamento (a falha mais comum e custosa)

Vazamento acontece quando atributos contêm informações que não estariam disponíveis no momento da previsão, ou quando o treino vê informações da validação/teste.

Padrões comuns de vazamento:

  • Usar “delivered_date” para prever se um pedido será entregue
  • Usar “number_of_support_tickets_next_7_days” para prever churn
  • Agregar usando todos os dados (incluindo o futuro) em vez de snapshots corretos no ponto no tempo
  • Codificação por alvo calculada usando o dataset inteiro

Vazamento pode gerar métricas offline irrealisticamente altas e falhar de forma catastrófica em produção. Veja Vazamento para padrões e defesas mais aprofundados.

Contaminação entre treino/teste via pré-processamento

Mesmo que os atributos sejam conceitualmente válidos, você pode contaminar a avaliação ao ajustar o pré-processamento em todos os dados:

  • Normalização usando média/variância globais
  • Imputação usando medianas globais
  • Construção de vocabulário para texto usando todos os documentos

Correção: use pipelines de processamento e ajuste as transformações apenas nos folds de treino.

Codificação por alvo feita incorretamente

A codificação por alvo substitui categorias por estatísticas do rótulo (por exemplo, a média do alvo por categoria). Se calculada de forma ingênua, ela pode “memorizar” o conjunto de validação.

Abordagens corretas incluem:

  • Codificação por alvo com K-fold (K-fold) (fora do fold (out-of-fold))
  • Suavização (smoothing) em direção à média global
  • Tratamento cuidadoso de categorias raras
  • Separação estrita por tempo para problemas temporais

Se você usá-la, trate-a como um atributo de alto risco que exige Avaliação rigorosa.

Categóricos de alta cardinalidade e “atributos identificadores”

Colunas como user_id, transaction_id, device_id podem causar:

  • Memorização (sobreajuste)
  • Generalização espúria
  • Desempenho instável sob deriva (drift)

Às vezes, IDs ainda são úteis via agregados comportamentais (por exemplo, “contagem de compras passadas do usuário”) em vez de IDs brutos.

Divisões temporais e não estacionariedade (non-stationarity)

Se o mundo muda ao longo do tempo, divisões aleatórias podem ser enganosas. Exemplos:

  • Preços aumentam
  • Padrões de fraude se adaptam
  • O catálogo de produtos muda
  • Sazonalidade

Use validação baseada em tempo quando apropriado e garanta que os atributos usem apenas dados passados. Isso está intimamente relacionado à Seleção de Modelos, porque hiperparâmetros ajustados com a divisão errada não irão transferir.

Discriminação por proxy e atributos “bons demais”

Alguns atributos podem ser eticamente ou legalmente problemáticos, ou atuar como proxies de atributos protegidos (por exemplo, CEP correlacionando com raça). Mesmo que melhorem métricas, podem prejudicar justiça e confiança. A engenharia de atributos deve incluir revisão de proxies sensíveis e incentivos não intencionais.

Deriva de esquema silenciosa e definições inconsistentes de atributos

Em produção, falhas frequentemente vêm de:

  • Conjuntos de categorias mudando
  • Novos padrões de ausência
  • Unidades diferentes (dólares vs centavos)
  • Fusos horários diferentes
  • Valores renomeados (“NY” vs “New York”)

Mitigue com:

  • Checagens de esquema e validação de dados
  • Testes unitários para funções de atributos
  • Monitoramento de distribuições (deriva de atributos)

Medindo se os atributos ajudam

A engenharia de atributos deve ser avaliada como qualquer outra mudança de modelagem:

  • Use divisões apropriadas (aleatória/por grupo/por tempo)
  • Acompanhe a métrica principal mais métricas secundárias (calibração, estabilidade, desempenho por subgrupo)
  • Rode ablações: adicione um grupo de atributos por vez
  • Inspecione a importância de atributos (feature importance) com responsabilidade (ver Interpretabilidade (AM Clássico))

Cuidado: “importância” pode ser enganosa sob colinearidade, vazamento ou deriva. Sempre valide via desempenho em dados retidos (held-out), não apenas com gráficos de interpretabilidade.

Exemplo prático ponta a ponta: pré-processamento seguro com scikit-learn

Abaixo está um padrão típico para dados tabulares que evita contaminação ao colocar todo o pré-processamento dentro de um pipeline.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score

# Example columns:
# numeric: age, income
# categorical: plan_type, region
# label: churned

X = df[["age", "income", "plan_type", "region"]]
y = df["churned"]

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

numeric_features = ["age", "income"]
categorical_features = ["plan_type", "region"]

numeric_transformer = Pipeline(steps=[
    ("imputer", SimpleImputer(strategy="median")),
    ("scaler", StandardScaler()),
])

categorical_transformer = Pipeline(steps=[
    ("imputer", SimpleImputer(strategy="most_frequent")),
    ("onehot", OneHotEncoder(handle_unknown="ignore")),
])

preprocess = ColumnTransformer(
    transformers=[
        ("num", numeric_transformer, numeric_features),
        ("cat", categorical_transformer, categorical_features),
    ]
)

model = Pipeline(steps=[
    ("preprocess", preprocess),
    ("clf", LogisticRegression(max_iter=2000))
])

model.fit(X_train, y_train)
proba = model.predict_proba(X_test)[:, 1]
print("Test ROC AUC:", roc_auc_score(y_test, proba))

Por que isso é um bom baseline:

  • Imputação e escalonamento são ajustados apenas nos dados de treino.
  • A codificação one-hot não vai quebrar com categorias não vistas (handle_unknown="ignore").
  • O mesmo pré-processamento roda no treino e na inferência.

Se você mais tarde adicionar atributos comportamentais agregados (por exemplo, “purchases_last_30_days”), garanta que eles sejam computados corretamente no ponto no tempo; caso contrário, o pipeline não vai te salvar de vazamento.

Engenharia de atributos em produção: reprodutibilidade e “correção no ponto no tempo” (point-in-time correctness)

À medida que sistemas de aprendizado de máquina (machine learning) amadurecem, a engenharia de atributos se torna uma disciplina de engenharia:

  • Versione seus atributos: definições e código devem ser reprodutíveis.
  • Garanta consistência offline/online (offline/online consistency): os atributos usados para treinar são exatamente os usados para servir.
  • Para atributos baseados em eventos, imponha junções no ponto no tempo (point-in-time joins) (sem dados futuros).
  • Monitore distribuições de atributos e padrões de ausência ao longo do tempo.

Muitas equipes usam repositórios de atributos (feature stores) ou pipelines de atributos padronizados, mas o requisito central é mais simples: o cálculo de atributos deve ser determinístico, testável e consciente do tempo.

Relação com seleção de atributos

A engenharia de atributos cria sinais candidatos; a seleção de atributos decide o que manter. Em geral, você faz ambos:

  • Produz um conjunto amplo de atributos plausíveis
  • Remove os redundantes, ruidosos ou instáveis
  • Prefere conjuntos mais simples e robustos quando os ganhos são marginais

Veja Seleção de Atributos para métodos como abordagens de filtro/wrapper, regularização e poda baseada em importância.

Principais aprendizados

  • Engenharia de atributos é projeto de representação: ela controla quais padrões são fáceis ou difíceis para um modelo aprender.
  • Os melhores atributos são válidos no momento da previsão, robustos à deriva e alinhados com a estrutura causal/temporal do problema.
  • A maioria das falhas no mundo real vem de vazamento, contaminação e definições offline/online incompatíveis, não da falta de transformações “criativas”.
  • Use pipelines de processamento, divisões corretas de validação e ablação iterativa para melhorar de forma segura e mensurável.