Seleção de Features
O que é Seleção de Atributos?
Seleção de atributos (feature selection) é o processo de escolher um subconjunto das variáveis de entrada disponíveis (“atributos”) que são mais úteis para uma tarefa preditiva. O objetivo é selecionar atributos informativos e reduzir redundância — mantendo o sinal enquanto remove ruído, variáveis irrelevantes e informação duplicada.
A seleção de atributos fica dentro de Engenharia de Atributos e costuma ser usada junto com criação de atributos e limpeza de dados. Ela é distinta de métodos de redução de dimensionalidade (dimensionality reduction) como a Análise de Componentes Principais, que transformam atributos em novos; a seleção de atributos mantém os atributos originais, mas descarta alguns deles.
Razões comuns para realizar seleção de atributos:
- Melhor generalização (generalization): menos correlações espúrias, menor variância (relacionado ao Compromisso Viés–Variância)
- Treinamento e inferência mais rápidos: menos entradas, modelos menores
- Menor custo de coleta de dados: em produção, menos sensores/campos para computar
- Melhor interpretabilidade (interpretability): conjunto menor de preditores (veja Interpretabilidade de Modelos)
- Multicolinearidade reduzida (multicollinearity): menos entradas altamente correlacionadas que tornam modelos lineares instáveis
Por que “informativo” e “não redundante” importam ao mesmo tempo
Um atributo pode ser:
- Irrelevante: não relacionado ao alvo (ruído puro).
- Redundante: fortemente relacionado ao alvo, mas em grande parte duplicando informação já presente em outros atributos.
- Informativo e único: adiciona um novo sinal preditivo.
A redundância é comum quando:
- múltiplos sensores medem o mesmo fenômeno,
- você inclui versões brutas e agregadas de uma variável,
- a codificação one-hot (one-hot encoding) produz muitos indicadores correlacionados,
- janelas de séries temporais se sobrepõem fortemente.
Reduzir redundância pode melhorar estabilidade e interpretabilidade e, às vezes, a acurácia — especialmente para modelos sensíveis a entradas correlacionadas (por exemplo, modelos lineares).
Seleção de atributos vs. redução de dimensionalidade
Seleção de atributos
- Saída: subconjunto dos atributos originais
- Prós: interpretabilidade, depuração mais fácil, semântica consistente
- Contras: pode deixar passar combinações úteis de atributos
Redução de dimensionalidade (por exemplo, PCA)
- Saída: atributos transformados (componentes)
- Prós: pode capturar sinal espalhado por muitos atributos fracos
- Contras: interpretabilidade reduzida; a transformação deve ser aplicada de forma consistente
Na prática, a seleção de atributos costuma ser preferida quando os atributos têm significado claro (dados tabulares), enquanto a redução de dimensionalidade é comum para representações contínuas de alta dimensionalidade (por exemplo, vetores de incorporação (embeddings)).
Abordagens centrais: métodos de filtro, wrapper e embutidos
Uma taxonomia padrão divide métodos de seleção de atributos em abordagens de filtro, wrapper e embutidas. Elas diferem em usar (ou não) o modelo durante a seleção.
Métodos de filtro (pontuação independente do modelo)
Métodos de filtro (filter methods) ranqueiam ou selecionam atributos usando critérios estatísticos computados a partir dos dados, independentemente do modelo final.
Exemplos típicos:
- Correlação / covariância (para regressão): descartar um de cada par altamente correlacionado
- Teste F da ANOVA (ANOVA F-test) (para classificação): mede diferenças de média entre classes
- Teste qui-quadrado (chi-square test) (para atributos categóricos vs. alvo categórico)
- Informação mútua (mutual information, MI): captura dependência não linear
- Limiar de variância (variance threshold): remove atributos quase constantes
Pontos fortes:
- Rápidos e escaláveis
- Menor risco de sobreajuste (overfitting) do que métodos wrapper
- Funcionam como uma boa linha de base em alta dimensionalidade (texto, genômica)
Pontos fracos:
- Podem ignorar interações entre atributos (dois atributos fracos podem ser fortes juntos)
- Alguns testes assumem distribuições/relacionamentos específicos
Exemplo prático: SelectKBest com informação mútua (classificação)
import numpy as np
from sklearn.datasets import make_classification
from sklearn.feature_selection import SelectKBest, mutual_info_classif
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
X, y = make_classification(
n_samples=2000, n_features=200, n_informative=15, n_redundant=20,
random_state=0
)
pipe = Pipeline([
("select", SelectKBest(score_func=mutual_info_classif, k=30)),
("clf", LogisticRegression(max_iter=2000))
])
scores = cross_val_score(pipe, X, y, cv=5, scoring="roc_auc")
print(scores.mean(), scores.std())
Ponto-chave: a seleção de atributos está dentro de um Pipeline, então a seleção acontece dentro de cada dobra de treino, evitando vazamento de dados (leakage) (mais sobre isso abaixo).
Métodos wrapper (busca usando desempenho do modelo)
Métodos wrapper (wrapper methods) tratam a seleção de atributos como um problema de busca: avaliam subconjuntos treinando um modelo e medindo desempenho, geralmente com validação cruzada.
Estratégias comuns:
- Seleção forward (forward selection): começa vazio, adiciona o melhor atributo a cada etapa
- Eliminação backward (backward elimination): começa com todos os atributos, remove o pior a cada etapa
- Seleção stepwise (stepwise selection): combinação de forward/backward
- Eliminação Recursiva de Atributos (Recursive Feature Elimination, RFE): ajusta o modelo, remove os atributos menos importantes, repete
- Algoritmos genéticos / busca heurística (heuristic search): para espaços complexos (menos comum na prática padrão)
Pontos fortes:
- Podem capturar interações (dependendo do modelo e da busca)
- Frequentemente apresentam bom desempenho quando a contagem de atributos é moderada
Pontos fracos:
- Computacionalmente caros
- Maior risco de sobreajustar a seleção ao procedimento de validação se não for feito com cuidado (validação cruzada aninhada (nested cross-validation))
Exemplo prático: RFECV com um modelo linear
from sklearn.feature_selection import RFECV
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold
from sklearn.pipeline import Pipeline
estimator = LogisticRegression(max_iter=2000, solver="liblinear")
selector = RFECV(
estimator=estimator,
step=1,
cv=StratifiedKFold(5),
scoring="roc_auc",
min_features_to_select=10
)
pipe = Pipeline([
("select", selector),
("clf", estimator)
])
# Now pipe can be cross-validated or fit on the full training set.
Se você também precisa de uma estimativa não enviesada de generalização enquanto ajusta a seleção, use Validação Cruzada aninhada: laço interno para selecionar atributos/hiperparâmetros, laço externo para avaliação.
Métodos embutidos (seleção acontece durante o treinamento)
Métodos embutidos (embedded methods) integram a seleção de atributos ao ajuste do modelo.
Exemplos comuns:
- Regularização L1 (L1 regularization, Lasso): força alguns coeficientes a exatamente zero
- Elastic Net (Elastic Net): combina L1 e L2 para lidar melhor com atributos correlacionados
- Modelos baseados em árvores (tree-based models): divisões (splits) selecionam atributos implicitamente (pode-se derivar importância de atributos (feature importance))
- Modelos lineares esparsos (sparse linear models) / group lasso: esparsidade estruturada para atributos agrupados
Pontos fortes:
- Geralmente mais eficientes que wrappers
- Frequentemente bons padrões para ML tabular
- Naturalmente ligados ao modelo que você vai implantar
Pontos fracos:
- Os atributos “selecionados” dependem das suposições do modelo e dos hiperparâmetros
- Importâncias em árvores podem ser enganosas sob correlação ou atributos de alta cardinalidade
Exemplo prático: seleção baseada em L1 para soluções esparsas
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipe = Pipeline([
("select", SelectFromModel(
LogisticRegression(penalty="l1", solver="liblinear", C=0.5, max_iter=2000)
)),
("clf", LogisticRegression(max_iter=2000))
])
Isso seleciona atributos com coeficientes não nulos no modelo L1 e depois treina um classificador (possivelmente diferente). Muitas vezes, você pode simplesmente usar o próprio modelo L1 como modelo final.
Medindo “informatividade”: critérios comuns
Tarefas e tipos de dados diferentes exigem medidas diferentes.
Para regressão
- Correlação de Pearson (Pearson correlation) com o alvo: rápida, mas linear
- Informação mútua para regressão (mutual information regression): dependência não linear
- Testes univariados de regressão linear (univariate linear regression tests) (estatísticas F)
Para classificação
- Teste F da ANOVA: bom para atributos contínuos, alvo categórico
- Qui-quadrado (chi-square): atributos não negativos baseados em contagem (por exemplo, bag-of-words)
- Informação mútua: não linear, amplamente aplicável
- ReliefF (ReliefF): considera vizinhanças locais; pode capturar interações melhor do que testes univariados
Controle de redundância (além da relevância univariada)
Filtros univariados podem manter múltiplas cópias correlacionadas do mesmo sinal. Métodos que explicitamente equilibram relevância e redundância incluem:
- Seleção de atributos baseada em correlação (correlation-based feature selection): manter atributos correlacionados com o alvo, mas não entre si
- mRMR (mínima redundância e máxima relevância; minimum redundancy maximum relevance): maximiza relevância ao alvo enquanto minimiza dependência entre atributos (frequentemente via MI)
- Agrupar atributos por correlação (clustering features by correlation) e escolher representantes de cada grupo
Uma heurística prática simples para redundância:
- Ranqueie atributos por relevância (por exemplo, MI).
- Percorra a lista e mantenha um atributo apenas se sua correlação com os já mantidos estiver abaixo de um limiar (por exemplo, |ρ| < 0.9).
Interações e não linearidade: quando “fraco sozinho” pode ser forte em conjunto
Uma limitação clássica de muitos métodos de filtro é que eles pontuam cada atributo de forma independente. Mas alguns sinais são apenas de interação (interaction-only).
Exemplo (XOR):
- Dois atributos binários
x1ex2são individualmente não informativos sobrey, - mas juntos eles determinam perfeitamente
y = x1 XOR x2.
Métodos wrapper e alguns modelos embutidos (árvores, boosting) podem capturar essas interações. Este é um motivo pelo qual a seleção de atributos deve ser combinada com a família de modelos que você planeja usar (por exemplo, modelos lineares vs. baseados em árvores vs. métodos de kernel (kernel methods)).
Seleção de atributos em fluxos de trabalho comuns de ML
Dados esparsos e de alta dimensionalidade (texto, logs de cliques)
Em classificação de texto com saco de palavras (bag-of-words), você pode começar com 100k+ atributos.
Abordagens típicas:
- Filtrar por frequência de documento (document frequency) (descartar termos extremamente raros)
- Usar qui-quadrado ou informação mútua para manter os top-k tokens
- Usar modelos lineares com L1/Elastic Net para esparsidade
Dados tabulares de negócios/medicina
Problemas comuns:
- medições correlacionadas (redundância),
- padrões de ausência (missingness),
- variáveis derivadas propensas a vazamento (por exemplo, atributos pós-desfecho).
Abordagens típicas:
- Remover colunas quase constantes e duplicadas
- Descartar um de pares altamente correlacionados
- Seleção embutida com L1/Elastic Net
- Modelos baseados em árvores como benchmark, mas interpretar importâncias com cuidado
Genômica / proteômica
Frequentemente: p >> n (muito mais atributos do que amostras), com forte estrutura de correlação.
Abordagens comuns:
- Linhas de base fortes de filtro (MI, testes t, controle de FDR)
- Modelos lineares regularizados (Lasso/Elastic Net)
- Seleção por estabilidade (stability selection) (selecionar atributos que se repetem em reamostragens)
Evitando armadilhas comuns
Vazamento: a seleção de atributos deve acontecer dentro da dobra de treino
Se você seleciona atributos usando o conjunto de dados inteiro e depois faz validação cruzada, você vaza informação das dobras de teste para o processo de treinamento, inflando o desempenho.
Abordagem correta:
- Colocar a seleção dentro de um
Pipeline - Avaliar com Validação Cruzada
- Ter cuidado extra com divisões de séries temporais e dados agrupados
Veja Vazamento para um tratamento mais aprofundado de como o vazamento acontece e como preveni-lo.
Viés de seleção e “double dipping”
Testar muitos seletores de atributos e reportar o melhor score sem validação adequada leva a estimativas otimistas.
Mitigações:
- Usar validação cruzada aninhada ao comparar seletores/hiperparâmetros
- Manter um conjunto de teste holdout (holdout test set) intocado até o final
- Pré-registrar decisões ao fazer estudos científicos
Instabilidade sob atributos correlacionados
Com preditores correlacionados, muitos subconjuntos diferentes podem ter desempenho semelhante. Pequenas mudanças nos dados podem inverter qual atributo é escolhido.
Mitigações:
- Preferir Elastic Net em vez de L1 puro quando os atributos são correlacionados
- Usar seleção por grupos (por exemplo, selecionar um por cluster)
- Usar seleção por estabilidade (contar a frequência de seleção em amostras bootstrap)
Dependência excessiva de importâncias de atributos em árvores
Modelos de árvores “selecionam” atributos via splits, mas as importâncias derivadas podem ser enviesadas:
- a favor de variáveis contínuas ou de alta cardinalidade,
- instáveis sob correlação,
- enganosas quando atributos são intercambiáveis.
Considere:
- importância por permutação (permutation importance) (computada em dados de validação),
- explicações aditivas de Shapley (SHAP) (com cuidado),
- ou usar modelos lineares regularizados como uma linha de base mais simples.
Uma receita prática (bom processo padrão)
Comece com restrições do domínio e dos dados
- Remova identificadores, timestamps que codificam o alvo, variáveis pós-desfecho.
- Considere custos: você precisa de atributos computáveis em tempo real?
Filtros básicos de limpeza
- Descartar colunas constantes/quase constantes
- Descartar duplicatas
- Tratar valores ausentes (imputação ou indicadores de ausência)
Redução de redundância
- Agrupamento por correlação / limiarização
- Manter um representante por grupo correlacionado
Seleção sensível ao modelo
- Se usar modelos lineares: Elastic Net / L1
- Se usar árvores/boosting: considere não selecionar primeiro; adicione seleção se necessário por velocidade/interpretabilidade
Valide corretamente
- Pipeline + validação cruzada
- Validação cruzada aninhada se você estiver ajustando fortemente a estratégia de seleção
Reverifique interpretabilidade e implantação
- Os atributos selecionados são estáveis ao longo do tempo?
- Eles estão disponíveis no momento da inferência?
- Eles criam problemas de justiça (fairness) ou privacidade?
Exemplo: redução de redundância + seleção embutida (tabular)
Abaixo está um fluxo compacto que (a) remove colunas altamente correlacionadas e depois (b) usa L1 para esparsidade.
import numpy as np
import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
class CorrelationFilter(BaseEstimator, TransformerMixin):
def __init__(self, threshold=0.95):
self.threshold = threshold
self.keep_mask_ = None
def fit(self, X, y=None):
# X assumed to be a pandas DataFrame for column tracking
corr = X.corr(numeric_only=True).abs()
upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))
to_drop = [col for col in upper.columns if any(upper[col] > self.threshold)]
self.keep_columns_ = [c for c in X.columns if c not in to_drop]
return self
def transform(self, X):
return X[self.keep_columns_]
pipe = Pipeline([
("corr", CorrelationFilter(threshold=0.95)),
("scale", StandardScaler(with_mean=False)), # with_mean=False if X can be sparse
("select", SelectFromModel(
LogisticRegression(penalty="l1", solver="liblinear", C=0.5, max_iter=2000)
)),
("clf", LogisticRegression(max_iter=2000))
])
Notas:
- Em projetos reais, você também precisará de uma etapa de pré-processamento para atributos categóricos (por exemplo, codificação one-hot) e valores ausentes.
- Mantenha todas as etapas dentro do pipeline para evitar vazamento.
Como a seleção de atributos interage com modelos modernos
Aprendizado profundo
Para redes profundas, a seleção explícita de atributos é menos comum porque:
- redes podem aprender representações internas,
- regularização e arquitetura frequentemente importam mais do que descartar entradas.
Ainda assim, a seleção de atributos pode ajudar quando:
- as entradas são extremamente alta-dimensionais e caras,
- você precisa de interpretabilidade ou conformidade (compliance),
- você está construindo modelos com dados tabulares onde linhas de base lineares esparsas são competitivas.
Impulsionamento por gradiente em dados tabulares
Com Impulsionamento por Gradiente (por exemplo, XGBoost/LightGBM/CatBoost), muitos praticantes pulam a seleção explícita no início porque o modelo lida razoavelmente bem com atributos irrelevantes. A seleção de atributos então é usada para:
- reduzir latência,
- simplificar a implantação,
- melhorar robustez contra deriva (drift).
Quando não fazer seleção de atributos
Você pode pular ou minimizar a seleção de atributos quando:
- a contagem de atributos já é pequena e a computação é barata,
- o modelo é robusto a atributos irrelevantes e você tem muitos dados,
- descartar atributos pode remover sinais raros porém importantes (por exemplo, fraude),
- você precisa de incerteza calibrada (calibrated uncertainty) e a instabilidade da seleção atrapalharia.
Nesses casos, foque mais em regularização, qualidade dos dados e avaliação adequada.
Resumo
Seleção de atributos trata de manter sinal informativo enquanto remove entradas irrelevantes e redundantes. Ela pode melhorar generalização, velocidade, interpretabilidade e custo operacional — mas apenas se for feita com validação cuidadosa para evitar Vazamento e viés de seleção.
Um modelo mental prático:
- Use métodos de filtro por velocidade e como linha de base,
- métodos wrapper quando interações importam e a contagem de atributos é gerenciável,
- métodos embutidos (L1/Elastic Net, árvores) como escolhas padrão fortes ligadas ao modelo implantado,
- e sempre valide dentro de um pipeline com Validação Cruzada adequada.