Codificação One-Hot
Visão geral
Muitos conjuntos de dados do mundo real contêm variáveis categóricas — atributos cujos valores são rótulos, e não números (por exemplo, city = "Paris", color = "red", browser = "Chrome"). A maioria dos algoritmos de aprendizado de máquina (machine learning), no entanto, opera sobre vetores numéricos. A codificação one-hot (one-hot encoding) é uma técnica padrão de engenharia de atributos (feature engineering) que converte valores categóricos em atributos indicadores binários, permitindo que modelos os consumam sem inventar uma ordenação numérica enganosa.
A codificação one-hot é uma ferramenta central em Engenharia de Atributos, e interage de perto com a escolha do modelo, a divisão dos dados e preocupações como Vazamento.
O que é codificação one-hot?
Dado um atributo categórico com (K) categorias possíveis, a codificação one-hot mapeia cada categoria para um vetor em ({0,1}^K) com exatamente um “1” e o restante “0”.
Se color ∈ {red, green, blue}, a codificação one-hot cria três atributos indicadores:
color_redcolor_greencolor_blue
e representa:
red → [1, 0, 0]green → [0, 1, 0]blue → [0, 0, 1]
Por que funciona
A codificação one-hot tem uma propriedade importante: ela não impõe uma ordem. Compare isso com atribuir red=0, green=1, blue=2, o que implica “blue > green > red” e faz modelos lineares ou baseados em distância se comportarem como se essas categorias estivessem em uma reta numérica.
Formalmente, vetores one-hot correspondem aos vetores da base padrão (standard basis vectors) (e_1, e_2, \dots, e_K). Em modelos lineares, cada categoria recebe seu próprio peso aprendido (em relação a uma referência), o que geralmente é o que queremos.
Quando a codificação one-hot é apropriada?
A codificação one-hot é uma boa escolha padrão quando:
- O atributo é nominal (sem ordem significativa): país, ID de produto (até certo ponto), tipo de dispositivo etc.
- Você usa modelos que assumem relações numéricas aproximadamente lineares:
- regressão linear / regressão logística
- SVM linear
- modelos lineares generalizados
- muitas redes neurais (embora incorporações sejam frequentemente melhores para alta cardinalidade)
- Você quer uma representação simples e interpretável: em modelos lineares, cada coeficiente corresponde a um indicador de categoria.
Observações específicas por modelo
- Regressão linear / regressão logística: a codificação one-hot costuma ser a abordagem padrão. Coeficientes são fáceis de interpretar como efeitos de categoria (com uma categoria de referência).
- Modelos baseados em árvores (árvores de decisão, florestas aleatórias, gradient boosting): podem funcionar com categorias codificadas ordinalmente, mas one-hot ainda é comum. Dependendo da implementação, one-hot pode aumentar a dimensionalidade e o tempo de treinamento; algumas bibliotecas de árvores suportam divisões categóricas nativas.
- Modelos baseados em distância (k-NN, k-means): one-hot evita ordenação artificial, mas distâncias em espaços esparsos de alta dimensionalidade podem se tornar menos significativas; considere alternativas ou um pré-processamento cuidadoso.
- Redes neurais: one-hot pode funcionar, mas, para muitas categorias, incorporações aprendidas (learned embeddings) normalmente são mais eficientes em termos de parâmetros.
Um exemplo prático (à mão)
Suponha que você tenha:
| user_id | plan | region |
|---|---|---|
| 1 | free | EU |
| 2 | pro | US |
| 3 | free | US |
A codificação one-hot produz:
| user_id | plan_free | plan_pro | region_EU | region_US |
|---|---|---|---|---|
| 1 | 1 | 0 | 1 | 0 |
| 2 | 0 | 1 | 0 | 1 |
| 3 | 1 | 0 | 0 | 1 |
Essas novas colunas são “flags” binárias que os modelos podem ingerir diretamente.
Implementando codificação one-hot na prática
Pandas: `get_dummies`
import pandas as pd
df = pd.DataFrame({
"plan": ["free", "pro", "free"],
"region": ["EU", "US", "US"]
})
encoded = pd.get_dummies(df, columns=["plan", "region"])
print(encoded)
Isso é conveniente para exploração e pipelines pequenos, mas, para aprendizado de máquina em produção, costuma ser mais seguro usar transformadores do scikit-learn para evitar inconsistências entre treino e teste.
Scikit-learn: `OneHotEncoder` (recomendado)
Principais vantagens:
- Ajusta os mapeamentos de categoria nos dados de treino
- Pode lidar com categorias desconhecidas no momento da inferência
- Funciona de forma eficiente com matrizes esparsas
- Integra-se de maneira limpa com pipelines
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
X = df # example features
y = [0, 1, 0] # example labels
categorical = ["plan", "region"]
preprocess = ColumnTransformer(
transformers=[
("cat", OneHotEncoder(handle_unknown="ignore"), categorical)
],
remainder="drop"
)
model = Pipeline(steps=[
("preprocess", preprocess),
("clf", LogisticRegression(max_iter=1000))
])
model.fit(X, y)
A configuração handle_unknown="ignore" é importante para robustez quando novas categorias aparecem no momento da predição (mais sobre isso abaixo).
A “armadilha das variáveis dummy” e a multicolinearidade
O que é a armadilha das variáveis dummy?
Se uma variável categórica tem (K) categorias e você inclui todas as (K) colunas one-hot mais um intercepto, os atributos se tornam linearmente dependentes:
[ \text{plan_free} + \text{plan_pro} + \dots + \text{plan_enterprise} = 1 ]
Isso cria multicolinearidade perfeita, o que significa que a matriz de projeto não tem posto completo. Em mínimos quadrados ordinários, isso faz com que os coeficientes não sejam identificáveis de forma única; muitos solucionadores derrubarão uma coluna automaticamente ou produzirão estimativas instáveis.
Como evitar
Estratégias comuns:
- Remover uma categoria por atributo (“codificação de referência”):
- Pandas:
pd.get_dummies(..., drop_first=True) - scikit-learn:
OneHotEncoder(drop="first")
- Pandas:
- Manter todas as colunas, mas remover o intercepto (menos comum)
- Confiar em regularização (por exemplo, regressão logística L2) e em um solucionador que lide com deficiência de posto — mas a interpretabilidade ainda fica mais difícil.
Exemplo com scikit-learn:
OneHotEncoder(drop="first", handle_unknown="ignore")
Isso sempre importa?
- Para muitos modelos baseados em árvores, multicolinearidade é menos um problema conceitual do que para regressão linear, mas remover um nível ainda pode reduzir redundância.
- Para modelos lineares, é uma boa prática evitar colinearidade perfeita se você quer coeficientes estáveis e interpretáveis.
Armadilhas comuns
1) Alta cardinalidade (categorias demais)
Se um atributo tem milhares (ou milhões) de valores únicos — como user_id, product_sku ou zip_code bruto — a codificação one-hot pode explodir o espaço de atributos:
- Memória: a matriz fica enorme (mesmo que esparsa).
- Computação: treinamento e inferência ficam mais lentos.
- Sobreajuste (overfitting): categorias raras podem receber pesos pouco confiáveis, especialmente em modelos lineares.
Mitigações
- Agrupar categorias raras em um bucket
"other"(limiar por frequência). - Usar hashing (o “hashing trick”) para mapear categorias em um número fixo de bins.
- Usar codificação por alvo ou incorporações (com controle cuidadoso de vazamento).
- Considerar se o atributo deve ser usado (veja Seleção de Atributos).
2) Incompatibilidades de categorias entre treino/teste (categorias não vistas)
Um bug clássico em produção: uma categoria aparece em validação/teste/inferência que nunca apareceu no treino. Por exemplo, o treino vê region ∈ {EU, US}, mas a inferência vê region="APAC".
O que acontece depende das suas ferramentas:
- One-hot ingênuo com um conjunto fixo de colunas pode dar erro ou desalinha colunas silenciosamente.
- Se você ajustar codificadores separadamente em treino e teste, você pode acabar com ordenações diferentes de colunas, o que é catastrófico.
Boas práticas
- Ajuste o codificador apenas nos dados de treino, e então reutilize-o para validação/teste.
- Use um pipeline para que o pré-processamento fique acoplado ao modelo.
- No scikit-learn, defina:
OneHotEncoder(handle_unknown="ignore")
Isso codifica categorias não vistas como todos zeros no bloco one-hot desse atributo. Em algumas aplicações, você pode preferir modelar explicitamente “desconhecido” adicionando uma categoria "__UNK__" durante o pré-processamento.
3) Matrizes esparsas e incompatibilidades a jusante
Matrizes codificadas com one-hot são tipicamente esparsas (a maioria dos valores é zero). Muitas bibliotecas de aprendizado de máquina lidam com entradas esparsas com eficiência, mas algumas etapas podem densificar a matriz e explodir o uso de memória.
Fique atento a:
- algoritmos ou transformadores que exigem arrays densos
- chamadas acidentais de
.toarray()em dados enormes - etapas de escalonamento de atributos que densificam
No scikit-learn, muitos modelos lineares funcionam bem com entradas esparsas; sempre verifique se o estimador escolhido suporta matrizes esparsas.
4) Tratar valores ausentes incorretamente
Valores ausentes em categorias precisam de tratamento explícito:
- Você pode tratar o ausente como sua própria categoria (por exemplo,
"__MISSING__") - Ou imputar a partir dos dados (moda/mais frequente)
No scikit-learn, OneHotEncoder pode tratar None/np.nan como uma categoria em versões mais novas, mas o comportamento depende do tipo de entrada; em pipelines robustos, considere imputação explícita com Imputação (Tratamento de Valores Ausentes).
5) Vazamento com codificações “espertas”
A codificação one-hot em si não é inerentemente sujeita a vazamento, mas o processo pode ser:
- Ajustar codificadores no conjunto completo antes de dividir pode vazar informação distribucional (geralmente pequeno, mas ainda evitável).
- Algumas alternativas (notavelmente codificação por alvo) podem vazar informação do rótulo de forma grave se não forem feitas corretamente (veja Vazamento).
Use divisão adequada de treino/validação e pipelines.
Visão teórica: codificação one-hot em modelos lineares
Considere regressão logística com indicadores categóricos codificados com one-hot. Suponha que plan tenha categorias {free, pro, enterprise} e você remova free como referência. O modelo é:
[ \log\frac{p(y=1)}{1-p(y=1)} = b + w_{\text{pro}} \cdot I(\text{plan=pro}) + w_{\text{enterprise}} \cdot I(\text{plan=enterprise}) + \dots ]
Interpretação:
- (b) é o log-odds de base para
free(mantendo os outros atributos fixos). - (w_{\text{pro}}) é a mudança no log-odds ao passar de
freeparapro.
Esse é um dos motivos pelos quais a codificação one-hot é popular: ela produz efeitos limpos no nível de categoria.
Variantes: one-hot vs multi-hot
O one-hot padrão assume exatamente uma categoria por exemplo (por exemplo, um único país).
Se um atributo pode conter múltiplos rótulos ao mesmo tempo (por exemplo, interesses do usuário: {sports, music, travel}), normalmente você usa uma representação multi-hot (também chamada binarização multi-rótulo): múltiplos 1s podem aparecer no vetor. A ideia é semelhante (indicadores binários), mas a semântica dos dados é diferente.
Alternativas à codificação one-hot
A codificação one-hot nem sempre é a melhor escolha. Alternativas comuns incluem:
Codificação ordinal
A codificação ordinal (ordinal encoding) mapeia categorias para inteiros: small=0, medium=1, large=2.
- Apropriada quando categorias têm uma ordem real (nível de escolaridade, faixas de tamanho).
- Frequentemente usada com modelos de árvore, especialmente se a ordem for significativa.
- Arriscada para categorias nominais: introduz uma ordenação artificial.
No scikit-learn, veja OrdinalEncoder.
Codificação por alvo (mean encoding)
A codificação por alvo (target encoding) substitui uma categoria por uma estatística do rótulo, como:
- classificação: (E[y \mid \text{category}])
- regressão: média do alvo por categoria
Prós:
- Lida com alta cardinalidade de forma eficiente (um atributo numérico em vez de milhares).
- Pode melhorar desempenho para modelos poderosos com poucos dados.
Contras / principal armadilha:
- Extremamente propensa a vazamento do alvo (target leakage) se calculada usando o rótulo do próprio ponto de dados.
- Deve ser feita com esquemas cuidadosos de validação cruzada (por exemplo, codificação K-fold out-of-fold) e suavização/regularização.
A codificação por alvo deve fazer parte de um pipeline consciente de vazamento; veja Vazamento.
Hashing trick (feature hashing)
Mapeia categorias em um vetor de tamanho fixo usando uma função de hash.
Prós:
- Memória constante em relação ao número de categorias
- Lida naturalmente com categorias não vistas
- Rápido
Contras:
- Colisões: categorias diferentes podem mapear para o mesmo índice de atributo
- Mais difícil de interpretar
Útil para sinais categóricos semelhantes a texto e atributos de cardinalidade muito alta.
Incorporações aprendidas
Comuns em aprendizado profundo e sistemas de recomendação:
- Cada categoria recebe um vetor denso aprendido (incorporação).
- Muito mais compacto que one-hot para alta cardinalidade.
- Pode capturar similaridade entre categorias.
Desvantagens:
- Exige mais complexidade de modelagem e treinamento cuidadoso
- Menos transparente que one-hot para interpretação
Orientação prática e boas práticas
Escolhendo uma estratégia de codificação
Uma regra prática razoável:
- Atributos nominais de baixa a moderada cardinalidade: one-hot
- Categorias ordenadas: codificação ordinal
- Cardinalidade muito alta: hashing / codificação por alvo (com controles de vazamento) / incorporações
- IDs sem significado semântico: frequentemente é melhor excluir ou tratar via modelos especializados (por exemplo, incorporações em sistemas de recomendação)
Boas práticas de pipeline (scikit-learn)
- Sempre divida os dados primeiro; ajuste o pré-processamento apenas no treino.
- Use
Pipeline+ColumnTransformerpara manter transformações consistentes. - Use
handle_unknown="ignore"para evitar falhas na inferência. - Considere
drop="first"para modelos lineares com intercepto para evitar colunas redundantes.
Exemplo combinando numérico + categórico:
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
X = pd.DataFrame({
"age": [25, np.nan, 40],
"plan": ["free", "pro", "free"],
"region": ["EU", "US", "US"]
})
y = [0, 1, 0]
numeric_features = ["age"]
categorical_features = ["plan", "region"]
numeric_pipe = Pipeline([
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler())
])
categorical_pipe = Pipeline([
("impute", SimpleImputer(strategy="most_frequent")),
("ohe", OneHotEncoder(handle_unknown="ignore", drop="first"))
])
preprocess = ColumnTransformer([
("num", numeric_pipe, numeric_features),
("cat", categorical_pipe, categorical_features)
])
clf = Pipeline([
("prep", preprocess),
("model", LogisticRegression(max_iter=1000))
])
clf.fit(X, y)
Esse desenho também funciona bem com validação cruzada e reduz o risco de vazamento acidental.
Lidando com categorias raras
Se as categorias têm uma cauda longa, one-hot pode criar muitas colunas que aparecem apenas algumas vezes, aumentando o risco de sobreajuste.
Táticas comuns:
- Combinar categorias raras em
"other"com base em um limiar de frequência. - Usar regularização (L1/L2) em modelos lineares para amortecer pesos ruidosos.
- Considerar codificação por alvo com suavização se a cardinalidade for alta e o vazamento estiver controlado.
Resumo
A codificação one-hot converte variáveis categóricas em atributos indicadores binários para que modelos de aprendizado de máquina possam usá-las sem impor uma ordem artificial. Ela é amplamente aplicável e especialmente eficaz para categorias nominais em modelos lineares, mas traz armadilhas práticas:
- Alta cardinalidade pode causar explosão de dimensionalidade e sobreajuste.
- A armadilha das variáveis dummy pode introduzir multicolinearidade perfeita (normalmente resolvida removendo um nível por atributo).
- Incompatibilidades entre treino/teste podem quebrar a inferência, a menos que você ajuste codificadores nos dados de treino e lide com categorias desconhecidas.
- Algumas alternativas — especialmente codificação por alvo — podem trazer resultados fortes, mas devem ser implementadas com cuidado para evitar Vazamento.
Na maioria dos fluxos de trabalho aplicados, a codificação one-hot continua sendo uma linha de base forte — desde que você use pipelines robustos, gerencie cardinalidade e escolha estratégias de codificação alinhadas tanto aos dados quanto ao modelo.