ML Atlas

Machine learning do zero · Aula 5.3 · 28 de 33 aulas prontas · 12 min

Gradient boosting: árvores que corrigem erros

Em resumo

Cada árvore corrige os erros das anteriores. Depois de 200 árvores com passo 1, o treino cai para 2287 e o teste sobe para 5944, pior que uma reta (4095).

Aquecimento Duas perguntas de aulas anteriores. Um minuto, e a aula nunca fica bloqueada.
Da aula 5.2: Ensembles: por que muitas árvores vencem uma só Você aumenta uma random forest de 300 para 3.000 árvores. Qual é o efeito mais provável?

Ver a resposta

Resposta certa: A acurácia fica mais ou menos igual, enquanto o treino demora muito mais

Depois que a parte independente do erro já se diluiu na média, mais árvores acrescentam computação, mas pouca acurácia e nenhuma memorização extra.

Da aula 5.1: Árvores de decisão: vinte perguntas com dados Como uma árvore de decisão escolhe a pergunta a cada passo?

Ver a resposta

Resposta certa: Testa as perguntas possíveis e fica com a que deixa os grupos mais puros

A busca gulosa avalia as divisões candidatas e fica com a que mais reduz a impureza, como o índice de Gini.

Na lição 5.2, uma floresta aleatória tirava a média de muitas árvores construídas de forma independente, e acrescentar árvores não fazia mal. O gradient boosting constrói as árvores uma depois da outra. Cada árvore nova aprende os resíduos, isto é, quanto o conjunto de árvores anterior ainda erra em cada exemplo. Ela soma sua correção multiplicada pela taxa de aprendizado, um número entre 0 e 1. As árvores são pequenas, muitas vezes com uma só pergunta (um toco) ou com três. Em tabelas de tamanho médio, os modelos de árvores, com o boosting à frente, costumam vencer as redes neurais (Grinsztajn et al., 2022). Mas o boosting tem um traço que a floresta não tem: as correções seguintes podem começar a corrigir ruído.

Preveja, depois confira Prevemos a progressão do diabetes depois de um ano só a partir do IMC. Uma regressão linear tem nos pacientes de teste um erro quadrático médio (MSE) de 4095. O gradient boosting acrescenta árvores com no máximo três perguntas, cada uma com o passo completo 1. Depois de 200 árvores, o MSE de treino cai de 3713 (uma árvore) para 2287. Como fica o teste?
Qual é o seu grau de certeza?

Experimento interativo

Este experimento interativo funciona em um navegador com JavaScript ativado. O texto ao redor descreve o que ele mostra.

Ver a resposta

Resposta certa: Pior que a reta, porque as árvores seguintes começaram a corrigir o ruído

Pior: o MSE de teste sobe para 5944, embora o de treino tenha caído para 2287. Cada árvore aprende os resíduos das anteriores, e depois de algumas rodadas o que sobra nos resíduos é sobretudo o ruído aleatório de pacientes específicos. Em outras 20 divisões, 200 árvores assim sempre perdem para a reta no teste.

Experimente

  • Comece onde o lab abre: passo 1, profundidade 2, 200 árvores. Quantos degraus tem a função do conjunto e quão afastadas estão as curvas de treino e de validação?
  • Baixe o número de árvores. Com quantas árvores o erro de validação é o mais baixo? Só então olhe o teste.
  • Reduza o passo para 0,1 e pegue um toco. Como fica agora a curva de validação à medida que as árvores aumentam?
  • Compare a melhor validação do boosting com a linha tracejada da reta. Qual fica mais embaixo?

Depois de conferir no lab, vamos dar nome ao que você vê.

A ideia em palavras simples

A primeira árvore faz algumas perguntas sobre o IMC e prevê a progressão média da doença em cada grupo. Ela erra, então calculamos os resíduos: quanto falta até a verdade em cada paciente. A segunda árvore já não prevê a doença, só esses resíduos. O resultado dela vezes a taxa de aprendizado é somado ao da primeira. A terceira árvore aprende o que sobra depois das duas, e assim por diante. O conjunto cresce a partir de pequenas correções.

No começo, as correções capturam o padrão real: mais IMC, mais progressão. Depois que o padrão está capturado, o que sobra nos resíduos é sobretudo ruído, os desvios aleatórios dos pacientes com que o modelo aprende. As árvores seguintes aprendem justamente isso. Com passo 1 e árvores de três perguntas, o treino cai de 3713 com uma árvore para 2287 com 200, enquanto o teste sobe de 4319 para 5944. Isso é sobreajuste, como numa árvore profunda demais, só que desta vez ele cresce com o número de árvores. Numa floresta aleatória, cada árvore vê os dados por conta própria, e a média apaga os erros delas. No boosting, cada árvore se soma aos erros das anteriores.

Por isso o número de árvores, o passo e a profundidade são escolhidos pela validação, não pelo teste. O lab calcula o erro de validação com uma validação cruzada em 5 partes dentro dos 309 pacientes de treino. O mais baixo é um toco com passo 0,1 e 50 árvores: validação 3960. A reta tem 3823 na mesma validação, então só com o IMC quem vence é a reta. O teste confirma isso só no fim: 4154 para o boosting contra 4095 para a reta.

Jak to policzono
  • Dados: Diabetes (Efron et al., 2004), no scikit-learn sob a licença BSD-3-Clause. 442 pacientes, 10 medidas, progressão da doença depois de um ano. Usamos só o IMC. Divisão: 309 pacientes para aprender, 133 para o teste.
  • Modelo: gradient boosting com árvores de regressão de profundidade 1 ou 2 só sobre o IMC, perda quadrática, passo de 0,05 a 1, até 200 árvores; uma regressão linear sobre o IMC para comparar. Os números do lab batem com o GradientBoostingRegressor do scikit-learn.
  • Validação: validação cruzada em 5 partes dentro dos 309 pacientes de treino, as mesmas partes para cada ajuste e para a reta.

Por que funciona

O resíduo y − F(x) é a direção em que a previsão precisa se mover para o erro quadrático cair o mais rápido possível. Cada árvore dá, portanto, um pequeno passo de descida do gradiente, só que no espaço das funções e não dos pesos. Daí o nome: gradient boosting. Um passo pequeno significa que uma árvore corrige só parte do erro. São precisas mais árvores, mas cada uma acrescenta menos ruído. Em outras 20 divisões, 200 árvores de três perguntas com passo 0,1 têm no teste um MSE de 3747 a 4802, sempre menos que as mesmas árvores com passo 1 (de 4617 a 6983).

Isso não quer dizer que o boosting sempre vença uma reta. Só com o IMC, a relação com a doença é quase linear, e as árvores só conseguem imitar uma reta com degraus. Em outras 20 divisões, o boosting escolhido pela validação vence a reta no teste em 7. O boosting brilha onde há muitos atributos e o efeito deles é de limiar e emaranhado. Aí as árvores seguintes capturam dependências que uma reta não consegue expressar.

Um parente mais antigo, o AdaBoost, em vez de resíduos muda os pesos dos exemplos. Os exemplos em que o conjunto erra pesam mais na rodada seguinte. No verbete do Atlas sobre AdaBoost, o primeiro toco em tumores de mama classifica errado 10,3% dos tumores de treino. Antes da segunda rodada, esses tumores mal classificados carregam exatamente 50% do peso total, então o segundo toco aprende sobretudo com eles.

Um erro comum

Verdadeiro ou falso: “mais rodadas de boosting sempre ajudam”. Falso. Cada rodada melhora o treino, mas o teste só até certo ponto. Com passo 1 e árvores de três perguntas, na validação o melhor é 1 árvore, e 200 árvores dão 5944 no teste em vez de 4319. No código abaixo, o teste sobe de 4079 depois de uma árvore para 6437 depois de 200, enquanto o treino cai de 3827 para 2044.

O caminho seguro é um passo pequeno, muitas árvores e a parada antecipada da lição 3.6: pare de acrescentar árvores quando o erro de validação parar de cair. No código abaixo, a parada fica com 83 de 1000 árvores.

Quiz

Três perguntas para você se testar. Escolha uma resposta ou abra a resposta embaixo de cada pergunta. No teclado: as setas escolhem, Enter ou Espaço confirma.

1. O que a segunda árvore aprende no gradient boosting?
Ver a resposta

Resposta certa: Os resíduos da primeira árvore, isto é, quanto ela ainda está errando

Cada árvore seguinte recebe os resíduos do conjunto anterior e soma uma correção vezes a taxa de aprendizado. Amostras aleatórias e árvores independentes são a floresta aleatória.

2. Passo 1, árvores de três perguntas: o treino cai de 3713 para 2287, o teste sobe de 4319 para 5944. O que está acontecendo?
Ver a resposta

Resposta certa: Sobreajuste: as árvores tardias corrigem o ruído dos pacientes de treino

Depois que o padrão real está capturado, sobra ruído nos resíduos. As árvores seguintes o aprendem, e em pacientes novos esse ruído não se repete.

3. Verdadeiro ou falso: “mais rodadas de boosting sempre ajudam”.
Ver a resposta

Resposta certa: Falso, porque depois de um tempo as rodadas extras só corrigem ruído

O treino cai a cada rodada, o teste não. Com passo 1, na validação o melhor é 1 árvore, e 200 árvores dão 5944 no teste.

Pontos-chave

  • O gradient boosting constrói árvores em sequência: cada uma aprende os resíduos do conjunto anterior e soma uma correção vezes a taxa de aprendizado.
  • Ao contrário da floresta, o boosting pode sobreajustar: com passo 1, o teste sobe de 4319 para 5944 enquanto o treino cai.
  • Escolha o número de árvores, o passo e a profundidade pela validação ou pela parada antecipada, nunca pelo teste.
  • O boosting nem sempre vence uma reta: só com o IMC, a reta tem 3823 na validação e o melhor boosting 3960.

Mais a fundo: fórmula, código, prática

A matemática

O conjunto depois de m árvores: F_m(x) = F_{m−1}(x) + η · h_m(x), em que F_0 é a média de y no treino, η é a taxa de aprendizado e a árvore h_m ajusta os resíduos r_i = y_i − F_{m−1}(x_i).

Para a perda quadrática L = (y − F)² / 2, a derivada em relação a F é −(y − F), então o resíduo é menos o gradiente da perda. Cada árvore dá um passo de descida do gradiente no espaço das funções. No AdaBoost, o peso de um exemplo mal classificado é multiplicado por e^α, em que α = ln((1 − ε) / ε) e ε é o erro ponderado do toco.

No código (Python)

O mesmo experimento no scikit-learn: 200 árvores com passo 1, etapa por etapa, depois três ajustes comparados por validação cruzada dentro do treino, e a parada antecipada.

from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error as mse

X, y = load_diabetes(return_X_y=True, as_frame=True)
x_tr, x_te, y_tr, y_te = train_test_split(X[["bmi"]], y, test_size=0.3, random_state=0)
big = GradientBoostingRegressor(n_estimators=200, max_depth=2, learning_rate=1.0, random_state=0).fit(x_tr, y_tr)
for m, (p_tr, p_te) in enumerate(zip(big.staged_predict(x_tr), big.staged_predict(x_te)), start=1):
    if m in (1, 10, 50, 200):
        print(f"step 1, depth 2, {m:3d} trees: train MSE {mse(y_tr, p_tr):.0f}, test MSE {mse(y_te, p_te):.0f}")
cv = KFold(5, shuffle=True, random_state=0)
models = {"line": LinearRegression(), "step 1, 200 trees": big,
          "step 0.1, 50 stumps": GradientBoostingRegressor(n_estimators=50, max_depth=1, learning_rate=0.1, random_state=0)}
for name, model in models.items():
    val = -cross_val_score(model, x_tr, y_tr, cv=cv, scoring="neg_mean_squared_error").mean()  # validação só dentro do treino
    print(f"{name}: validation MSE {val:.0f}")
stop = GradientBoostingRegressor(n_estimators=1000, max_depth=1, learning_rate=0.1, validation_fraction=0.2, n_iter_no_change=10, random_state=0).fit(x_tr, y_tr)
print(f"early stopping kept {stop.n_estimators_} of 1000 trees; test MSE {mse(y_te, stop.predict(x_te)):.0f}, line {mse(y_te, models['line'].fit(x_tr, y_tr).predict(x_te)):.0f}")

Saída

step 1, depth 2,   1 trees: train MSE 3827, test MSE 4079
step 1, depth 2,  10 trees: train MSE 3013, test MSE 4798
step 1, depth 2,  50 trees: train MSE 2122, test MSE 6233
step 1, depth 2, 200 trees: train MSE 2044, test MSE 6437
line: validation MSE 3956
step 1, 200 trees: validation MSE 5728
step 0.1, 50 stumps: validation MSE 4030
early stopping kept 83 of 1000 trees; test MSE 4062, line 3921

A divisão é diferente da do lab, então os números também são um pouco diferentes. O quadro é o mesmo: com passo 1, o treino cai de 3827 para 2044, enquanto o teste sobe de 4079 para 6437. Na validação, a reta (3956) vence o passo pequeno (4030), e 200 árvores com passo 1 ficam com o pior resultado (5728). A parada antecipada fica com 83 árvores.

Para quem pratica
  • No scikit-learn: HistGradientBoostingRegressor e HistGradientBoostingClassifier são rápidos em tabelas grandes, lidam sozinhos com dados faltantes e têm parada antecipada (early_stopping). Fora do scikit-learn: XGBoost, LightGBM, CatBoost.
  • Um começo típico: passo de 0,05–0,1, árvores rasas, muitas árvores e parada antecipada na validação. Ajuste a profundidade e o passo com validação cruzada (lição 3.5) e deixe o teste para o fim.
  • O boosting é mais sensível a ruído nos rótulos que uma floresta: cada exemplo errado fica nos resíduos e as árvores seguintes tentam corrigi-lo. Com dados sujos, ajudam um passo menor, a amostragem de linhas (subsample) e uma regularização mais forte das árvores.
  • Antes de recorrer ao boosting, meça um ponto de referência simples (lição 1.3). Quando a relação é quase linear, uma reta pode vencer.

Vá mais fundo no Atlas

Verbetes da enciclopédia sobre as ideias desta aula: