Árvores de decisão e ensembles

Visão geral

Árvores de decisão (decision trees) são uma das famílias de modelos mais práticas no aprendizado de máquina (machine learning): elas funcionam bem em dados heterogêneos, bagunçados e tabulares (tabular data) (colunas numéricas/categóricas mistas, valores ausentes, interações não lineares), exigem pouco escalonamento de atributos (feature scaling) e produzem lógica legível por humanos.

Uma única árvore de decisão, no entanto, costuma ser instável (pequenas mudanças nos dados podem gerar uma árvore diferente) e pode superajustar facilmente. A abordagem mais bem-sucedida na prática é construir conjuntos (ensembles) de árvores:

  • Florestas aleatórias (random forests): muitas árvores profundas treinadas em dados e atributos reamostrados (agregação por bootstrap (bagging)) → linha de base padrão forte, robusta, pouca necessidade de ajuste.
  • Árvores de decisão com boosting de gradiente (gradient-boosted decision trees, GBDTs): árvores adicionadas sequencialmente para corrigir erros (boosting (boosting)) → desempenho de ponta em muitos problemas tabulares com ajuste cuidadoso.

Conjuntos de árvores são amplamente usados para pontuação de crédito, detecção de fraude, previsão de taxa de clique em anúncios, modelagem de evasão (churn), precificação, seguros e muitos outros problemas de negócio em que dados tabulares predominam.

Famílias de modelos relacionadas com as quais você pode comparar incluem Regressão Linear/Logística (mais simples, mais interpretável), SVMs (fortes em certos espaços de atributos) e aprendizado profundo (deep learning) (muitas vezes melhor em texto/imagens, menos consistentemente dominante em dados tabulares brutos, a menos que haja engenharia de atributos ou muitos dados disponíveis).

Árvores de decisão: Fundamentos

O que uma árvore de decisão aprende

Uma árvore de decisão particiona o espaço de atributos (feature space) usando uma sequência de regras se/então. Cada nó interno testa um atributo, por exemplo:

  • idade <= 37.5
  • renda > 52_000

Uma previsão é feita em uma folha:

  • Classificação (classification): distribuição de probabilidade sobre classes (frequentemente a classe majoritária).
  • Regressão (regression): valor-alvo médio (ou outro resumo) dos pontos de treinamento naquela folha.

Árvores capturam naturalmente não linearidades e interações entre atributos (feature interactions) (por exemplo, “se região = oeste E idade < 30 E renda > 50k…”).

O critério de divisão (redução de impureza)

Em cada nó, a árvore busca a divisão que mais melhora um objetivo de pureza.

Para classificação, medidas comuns de impureza:

  • Impureza de Gini (Gini impurity):
    [ G = 1 - \sum_k p_k^2 ]
  • Entropia (entropy):
    [ H = - \sum_k p_k \log p_k ]

Para regressão, um objetivo típico é o erro quadrático médio (mean squared error, MSE) (redução de variância):

[ \text{MSE} = \frac{1}{n}\sum_i (y_i - \bar{y})^2 ]

Uma divisão é escolhida para maximizar a redução de impureza:

[ \Delta = I(\text{parent}) - \frac{n_L}{n}I(L) - \frac{n_R}{n}I(R) ]

Esse procedimento guloso (greedy) é eficiente e eficaz, mas não garante uma árvore globalmente ótima.

Por que árvores únicas superajustam

Uma árvore pode continuar dividindo até que as folhas contenham pouquíssimas amostras, efetivamente memorizando ruído. A regularização (regularization) controla isso:

  • max_depth: limita a profundidade
  • min_samples_leaf: mínimo de amostras por folha
  • min_samples_split: mínimo de amostras para dividir
  • max_features: restringe os atributos considerados em cada divisão
  • Poda (pruning) (poda de custo-complexidade (cost-complexity pruning)): remove divisões fracas após crescer a árvore

Mesmo assim, uma árvore única continua sendo de alta variância. Conjuntos reduzem a variância (florestas aleatórias) ou reduzem o viés enquanto gerenciam a variância (boosting).

Conjuntos: Por que várias árvores funcionam melhor

Métodos de conjunto combinam múltiplos modelos para produzir um preditor mais forte. Duas ideias-chave:

  • Agregação por bootstrap (Bootstrap Aggregating): treinar modelos independentemente em dados reamostrados, depois fazer média → reduz variância.
  • Boosting (boosting): treinar modelos sequencialmente, cada um corrigindo os predecessores → reduz viés (e pode ser altamente preciso).

Isso se conecta ao trade-off viés–variância (bias–variance tradeoff):

  • Uma árvore profunda tem baixo viés, alta variância.
  • Uma floresta aleatória reduz a variância ao fazer a média de muitas árvores descorrelacionadas.
  • O boosting de gradiente constrói um modelo aditivo que pode atingir baixo viés com regularização cuidadosa.

Florestas aleatórias

Ideia central

Uma floresta aleatória treina muitas árvores de decisão, cada uma em:

  1. Uma amostra bootstrap (bootstrap sample) dos dados (amostrando linhas com reposição).
  2. Um subconjunto aleatório de atributos considerados em cada divisão.

As previsões são agregadas:

  • Classificação: voto majoritário ou probabilidades médias
  • Regressão: previsão média

Isso reduz a correlação entre árvores e torna a média altamente eficaz.

Por que a aleatoriedade de atributos importa

Se um atributo for muito forte, muitas árvores podem dividir por ele primeiro, produzindo árvores similares. Restringir candidatos a divisão (max_features) força diversidade, diminuindo a variância do conjunto.

Validação fora-da-bolsa (out-of-bag, OOB)

Como cada árvore vê apenas ~63% das amostras únicas (em expectativa) devido ao bootstrap, as amostras restantes podem servir como um conjunto de validação embutido:

  • Erro OOB estima generalização sem uma divisão separada de validação (útil, mas validação cruzada ainda é comum).

Pontos fortes e fracos na prática

Forças

  • Excelente linha de base em dados tabulares
  • Pré-processamento mínimo (não precisa de escalonamento)
  • Robusto a outliers e a muitos atributos irrelevantes
  • Treinamento paralelizável
  • Bom “primeiro modelo” para um novo conjunto de dados

Fraquezas

  • Modelos grandes (pesados em memória)
  • Menos preciso do que GBDTs bem ajustadas em muitos problemas
  • Implementações padrão não lidam tão bem com categóricas de alta cardinalidade sem codificação
  • Probabilidades podem não estar calibradas (muitas vezes melhor do que alguns modelos, mas ainda vale verificar)

Exemplo: floresta aleatória no scikit-learn

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.metrics import roc_auc_score
from sklearn.ensemble import RandomForestClassifier

# X: pandas DataFrame, y: binary target (0/1)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

cat_cols = X.select_dtypes(include=["object", "category"]).columns
num_cols = X.columns.difference(cat_cols)

preprocess = ColumnTransformer(
    transformers=[
        ("cat", OneHotEncoder(handle_unknown="ignore"), cat_cols),
        ("num", "passthrough", num_cols),
    ]
)

rf = RandomForestClassifier(
    n_estimators=500,
    max_features="sqrt",
    min_samples_leaf=2,
    n_jobs=-1,
    random_state=42,
)

model = Pipeline([("prep", preprocess), ("rf", rf)])
model.fit(X_train, y_train)

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

Notas:

  • Codificação one-hot (one-hot encoding) é um padrão comum para colunas categóricas em pipelines (pipelines) do scikit-learn.
  • Se você tiver muitas categorias, considere codificação por alvo (target encoding) com cuidado (observe vazamento), ou use bibliotecas projetadas para lidar com categóricas (veja CatBoost abaixo).

Boosting de gradiente (GBDT): O carro-chefe para ML tabular

Conceito: modelagem aditiva via otimização por etapas

O boosting de gradiente constrói um modelo como uma soma de aprendizes fracos (weak learners) (árvores):

[ F_M(x) = \sum_{m=1}^{M} \eta , f_m(x) ]

Em cada etapa, adiciona uma nova árvore (f_m) que reduz uma função de perda (L) escolhida, como:

  • perda logística (classificação binária)
  • entropia cruzada (multiclasse)
  • erro quadrático / Huber (regressão)
  • perdas personalizadas de ranqueamento (ranking) (comuns em busca e anúncios)

O truque principal: ajustar a próxima árvore ao gradiente negativo (um sinal tipo resíduo) da perda em relação às previsões atuais. Isso é conceitualmente relacionado a Descida do Gradiente, mas realizado no espaço de funções (function space).

Intuição: “aprender com os erros”

  • Comece com um modelo simples (frequentemente uma previsão constante).
  • Calcule onde o modelo erra.
  • Ajuste uma árvore pequena para esses erros.
  • Adicione-a ao modelo com um passo pequeno (taxa de aprendizado (learning rate)).
  • Repita.

GBDTs tendem a performar extremamente bem em dados tabulares porque podem representar interações complexas enquanto são fortemente regularizadas por meio de:

  • árvores rasas,
  • encolhimento (shrinkage) (taxa de aprendizado),
  • subamostragem (subsampling),
  • amostragem de colunas (column sampling),
  • parada antecipada (early stopping).

Principais hiperparâmetros (e como se comportam)

  • n_estimators (número de rodadas de boosting): mais árvores podem melhorar o ajuste, mas aumenta o risco de superajuste.
  • learning_rate (η): valores menores geralmente exigem mais árvores; frequentemente melhora a generalização.
  • max_depth / num_leaves: complexidade de cada árvore (ordem de interação).
  • min_samples_leaf / min_child_weight: controla tamanho das folhas, reduz superajuste.
  • subsample: amostragem de linhas por árvore (boosting de gradiente estocástico).
  • colsample_bytree / max_features: amostragem de atributos por árvore.
  • Termos de regularização (dependem da implementação): L1/L2 em pesos de folha, penalidades de divisão.

Um padrão comum e eficaz é: taxa de aprendizado pequena + parada antecipada.

Exemplo: boosting de gradiente no scikit-learn

O scikit-learn fornece HistGradientBoosting*, que usa binning por histogramas (histogram binning) e escala bem:

from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.metrics import roc_auc_score

gbdt = HistGradientBoostingClassifier(
    learning_rate=0.05,
    max_depth=6,
    max_leaf_nodes=31,
    min_samples_leaf=20,
    max_bins=255,
    early_stopping=True,
    random_state=42,
)

# If you already encoded categoricals; otherwise use a pipeline like above.
gbdt.fit(X_train_encoded, y_train)
proba = gbdt.predict_proba(X_test_encoded)[:, 1]
print("ROC AUC:", roc_auc_score(y_test, proba))

Se você quer desempenho de primeira linha e mais recursos, muitos profissionais usam:

  • XGBoost (GBDT excelente de uso geral, regularização forte, ciente de esparsidade)
  • LightGBM (muito rápido em conjuntos de dados grandes, crescimento por folhas, baseado em histogramas)
  • CatBoost (excelente manejo de categóricas com boosting ordenado (ordered boosting))

Florestas aleatórias vs Boosting de gradiente: Quando escolher qual

Florestas aleatórias são ideais quando…

  • Você quer uma linha de base robusta rapidamente e com ajuste mínimo
  • Você tem dados ruidosos e quer menor risco de superajuste
  • Você quer paralelizar o treinamento com facilidade
  • Você se importa com boa precisão e estabilidade mais do que extrair os últimos pontos percentuais

Boosting de gradiente é ideal quando…

  • Você quer o melhor desempenho da categoria em dados tabulares
  • Você pode gastar tempo ajustando hiperparâmetros e usando um conjunto de validação
  • Você tem relações e interações não lineares complexas
  • Você quer recursos avançados: restrições monotônicas (monotonic constraints), perdas personalizadas, tratamento de valores ausentes/categóricas (dependente da biblioteca)

Em muitas competições e pipelines tabulares em produção, um GBDT ajustado é o padrão de “modelo forte”.

Lidando com dados tabulares do mundo real

Valores ausentes

  • Muitas bibliotecas de GBDT lidam com valores ausentes aprendendo uma direção padrão nas divisões.
  • Historicamente, árvores do scikit-learn exigiam imputação em muitos cenários; métodos mais novos baseados em histogramas e alguns pipelines de pré-processamento tornam isso mais fácil.

Dica prática: se a ausência de valor for informativa, árvores frequentemente exploram isso naturalmente (ou você pode adicionar atributos indicadores de ausência).

Variáveis categóricas

As opções incluem:

  • Codificação one-hot: boa para cardinalidade baixa/moderada.
  • Codificação por alvo: poderosa, mas deve ser feita com ajuste cruzado (cross-fitting) seguro contra vazamento.
  • Tratamento categórico nativo: CatBoost (e LightGBM com configuração adequada) pode ser excelente e mais simples.

Escalonamento de atributos

Conjuntos de árvores tipicamente não exigem escalonamento (ao contrário de muitos modelos baseados em distância ou margem). Isso é uma grande vantagem prática sobre algumas alternativas como SVMs.

Desbalanceamento de classes

Estratégias comuns:

  • Defina class_weight="balanced" (florestas aleatórias, alguns GBDTs)
  • Use parâmetros específicos da biblioteca como scale_pos_weight (XGBoost/LightGBM)
  • Escolha métricas como PR AUC e ajuste limiares com base em custos de negócio
  • Considere validação cruzada estratificada e divisões de validação cuidadosas

Dados dependentes do tempo

Para problemas temporais, evite vazamento usando validação sensível ao tempo (por exemplo, divisões em janela deslizante). Conjuntos de árvores podem funcionar bem para previsão com atributos tabulares, mas a avaliação deve respeitar a ordem temporal (veja Previsão de Séries Temporais).

Fluxo de trabalho de avaliação e ajuste do modelo

  1. Comece com uma linha de base forte
    • Floresta aleatória ou um GBDT padrão (com parada antecipada)
  2. Use uma estratégia de validação apropriada
    • validação cruzada k-fold (k-fold CV) para dados i.i.d.
    • divisões por grupo quando entidades se repetem (usuários, dispositivos)
    • divisões temporais para dados temporais
  3. Ajuste os poucos hiperparâmetros que mais importam
    • Para RF: n_estimators, max_features, min_samples_leaf
    • Para GBDT: learning_rate, n_estimators (com parada antecipada), max_depth/num_leaves, min_samples_leaf, subsample
  4. Verifique a calibração de probabilidades (probability calibration) se você usa probabilidades previstas para decisões
    • Métodos de calibração (escalonamento de Platt (Platt scaling) / regressão isotônica (isotonic regression)) podem ser aplicados pós-hoc
  5. Faça teste de estresse de robustez
    • desempenho por subgrupo
    • estabilidade ao longo do tempo
    • sensibilidade a padrões de ausência de valores

Interpretabilidade: de árvores a insights

Importância de atributos (com ressalvas)

Medidas comuns de importância:

  • Importância baseada em divisão (ganho / redução de impureza): rápida, mas pode ser enviesada em direção a atributos de alta cardinalidade.
  • Importância por permutação (permutation importance): mede a queda de desempenho quando um atributo é embaralhado; mais confiável, porém mais lenta.

Para explicações locais e melhor atribuição, muitas equipes usam valores SHAP (SHAP values) (TreeSHAP para conjuntos de árvores). Interpretabilidade é um tema amplo; conjuntos de árvores são mais interpretáveis do que muitos modelos neurais, mas menos transparentes do que um pequeno modelo linear de Regressão Linear/Logística.

Dependência parcial e ICE

  • Gráficos de dependência parcial (partial dependence plots, PDPs) mostram o efeito médio de um atributo.
  • Gráficos de Expectativa Condicional Individual (Individual Conditional Expectation, ICE) mostram efeitos por instância.

Cuidado: quando atributos são correlacionados, PDPs podem ser enganosos porque avaliam combinações irreais.

Armadilhas comuns

  • Vazamento de dados (data leakage): codificação por alvo ou pré-processamento feito nos dados completos antes da divisão; vazamento de informação futura em problemas temporais.
  • Superajuste com boosting: árvores demais, árvores profundas demais, sem parada antecipada.
  • Importância enganosa: interpretar importância baseada em divisão como efeito causal.
  • Ignorar grupos: vazamento no nível de usuário quando a mesma entidade aparece em treino e teste.
  • Tratar IDs como atributos: identificadores de alta cardinalidade podem causar memorização espúria.

Aplicações práticas

Conjuntos de árvores são uma escolha padrão para muitas tarefas tabulares de ML:

  • Risco de crédito / subscrição: desempenho forte com restrições monotônicas (por exemplo, renda mais alta não deveria aumentar risco de inadimplência).
  • Detecção de fraude: lida com interações não lineares e padrões esparsos; combine com abordagens de anomalia quando rótulos são limitados (veja Detecção de Anomalias).
  • Resposta de marketing / evasão: atributos de clientes heterogêneos, valores ausentes e interações são comuns.
  • Atributos para ranqueamento e recomendação: boosting de árvores é frequentemente usado como um ranqueador poderoso com atributos construídos (veja Aprendizado para Ranqueamento).

Como árvores de decisão se relacionam com outras famílias de modelos

  • Em comparação com Regressão Linear/Logística, conjuntos de árvores capturam não linearidades sem cruzamentos de atributos, ao custo de maior complexidade.
  • Em comparação com Redes Neurais, conjuntos de árvores frequentemente vencem em conjuntos de dados tabulares pequenos a médios com pouca engenharia de atributos, enquanto redes neurais dominam em dados não estruturados (texto/imagens/áudio).
  • Em comparação com Modelos Bayesianos, conjuntos de árvores padrão não são probabilísticos por padrão (embora você possa estimar incerteza via ensembling, perda quantílica ou métodos especializados).

Resumo

  • Árvores de decisão são modelos intuitivos e não paramétricos que dividem o espaço de atributos para reduzir impureza, mas uma árvore única costuma ser instável e propensa a superajuste.
  • Florestas aleatórias usam agregação por bootstrap + aleatoriedade de atributos para fazer a média de muitas árvores descorrelacionadas, produzindo uma linha de base robusta e forte para problemas tabulares.
  • Árvores com boosting de gradiente constroem um modelo aditivo ajustando sequencialmente árvores aos gradientes da perda; elas são frequentemente os modelos de melhor desempenho para dados tabulares quando ajustadas com regularização e parada antecipada.
  • O sucesso prático depende da estratégia de validação, prevenção de vazamento, tratamento cuidadoso de categóricas/valores ausentes e ferramentas de interpretabilidade.

Se você está começando um novo projeto de ML tabular, uma boa abordagem padrão é: criar uma linha de base com uma floresta aleatória, depois migrar para boosting de gradiente para máximo desempenho quando seu pipeline de avaliação estiver sólido.