Árvores de decisão · Gradient boosting

Gradient Boosting: Uma Visão Rápida e Aprofundada

Construa o gradient boosting a partir de correções dos resíduos e conecte o mesmo procedimento aditivo à classificação e à otimização no espaço de funções.

Introdução

O aprendizado de máquina costuma ser apresentado por meio de redes neurais, mas os dados tabulares seguiram um caminho um pouco diferente.

Quando os inputs são colunas como idade, renda, saldo em conta, categoria de produto ou número de transações, modelos baseados em árvores continuam extremamente competitivos. As árvores se adaptam naturalmente a esse tipo de dado porque um padrão útil muitas vezes pode ser expresso por perguntas como se uma feature está acima de um limiar, se outra está dentro de um intervalo ou se duas condições ocorrem juntas.

Gradient Boosted Decision Trees, ou GBDTs, combinam essa força das árvores de decisão com uma ideia muito mais próxima da otimização numérica clássica.

Em vez de treinar uma única árvore grande para resolver o problema inteiro, construímos um modelo sequencialmente. Começamos com uma predição rudimentar, inspecionamos como ela deveria mudar para reduzir a loss, treinamos um modelo pequeno para generalizar essas correções pelo espaço de input e então adicionamos esse modelo ao que já temos.

O resultado é um modelo aditivo:

FM(x)=F0(x)+ηh1(x)+ηh2(x)++ηhM(x)F_M(x) = F_0(x) + \eta h_1(x) + \eta h_2(x) +\cdots+ \eta h_M(x)

em que F0F_0 é a predição inicial, cada hmh_m é um novo learner e η\eta controla o quanto cada learner pode modificar o modelo atual.

Isso cria uma ponte interessante entre árvores de decisão e gradient descent. Em uma rede neural, normalmente definimos uma função parametrizada f(x;θ)f(x;\theta) e modificamos repetidamente seus parâmetros θ\theta para reduzir uma loss. No gradient boosting, o próprio preditor atual é modificado gradualmente pela adição de novas funções.

Outra forma de pensar nisso é que deixamos de pedir a um único modelo que aprenda de uma vez o mapeamento completo de XX para yy. Em cada iteração, estudamos o padrão das correções de que o modelo atual ainda precisa. Um weak learner generaliza essa correção, nós o adicionamos ao modelo e então inspecionamos o que ainda resta.

Com iterações suficientes, funções surpreendentemente complexas podem surgir de muitas árvores individualmente simples.

Cada nova árvore se ajusta ao que o modelo atual ainda não captura, criando o modelo seguinte.

Intuição

Começando pelo mais simples

Algoritmos complexos costumam ser muito mais fáceis de entender quando primeiro removemos tudo o que não é essencial. Portanto, vamos começar com um problema de regressão intencionalmente simples.

Suponha que nosso dataset contenha apenas uma feature de input xx. O target segue um pequeno sinal sintético com uma tendência gradual, uma onda, duas mudanças de nível e algum ruído aleatório:

yf(x)+ϵy \approx f(x) + \epsilon

O problema ainda é pequeno o bastante para que tanto os dados quanto as predições do modelo sejam visualizados diretamente em duas dimensões. As mudanças adicionais fazem diferentes partes do espaço de input terem erros genuinamente diferentes para as árvores descobrirem.

Se treinássemos uma árvore de regressão nesse dataset, sua predição seria constante por partes. Diferentes intervalos do eixo xx cairiam em diferentes folhas, e todos os pontos dentro de uma folha receberiam a mesma predição.

Uma árvore de regressão produz uma predição em forma de degrausTrinta e seis observações seguem um sinal unidimensional. Uma árvore de regressão de profundidade dois prediz um valor constante em cada intervalo aprendido.-101-303input xtarget yuma árvore
Uma árvore de regressão divide o eixo de input em intervalos e dá a todos os pontos de um intervalo a mesma predição.

Agora vamos mudar a maneira como pensamos sobre o problema.

Em vez de perguntar como construir uma árvore de regressão que prediga yy, suponha que decidamos de antemão treinar vários modelos sequencialmente. Cada novo modelo se concentrará apenas em corrigir o que o modelo anterior ainda não capturou.

Antes de treinar qualquer árvore, precisamos de uma predição inicial.

Para regressão com erro quadrático, um ponto de partida natural é a média do target:

F0(x)=yˉF_0(x)=\bar y

Assim, cada input recebe exatamente a mesma predição no início. Graficamente, o modelo é apenas uma linha horizontal.

Para cada observação, podemos agora medir o quanto o verdadeiro target está distante desse baseline:

ri=yiF0(xi)r_i = y_i - F_0(x_i)
O baseline da média deixa um erro diferente em cada regiãoCada observação começa com a mesma predição, zero vírgula treze. Segmentos verticais em âmbar mostram a distância com sinal desse baseline até cada target.-101-303input xtarget yF₀ = média = 0,13
O baseline constante é alto demais em algumas regiões e baixo demais em outras. Cada segmento vertical é um resíduo.

Os segmentos verticais representam exatamente essas diferenças. Se um ponto está acima do baseline, seu resíduo é positivo; se está abaixo, seu resíduo é negativo.

Nesse momento, esses resíduos se tornam o novo problema de predição.

Em vez de manter os valores originais de yy como nosso target, nós os substituímos temporariamente pelo quanto o modelo atual precisa se mover em cada observação de treino.

Como este problema de exemplo tem apenas uma feature, podemos visualizar esses resíduos como outro dataset.

Os resíduos do baseline ainda têm um padrão ao longo do eixo de inputA coordenada horizontal permanece fixa enquanto cada target se move para o valor de seu resíduo. Resíduos negativos se agrupam à esquerda, e resíduos positivos se agrupam ao longo da elevação central.-101-303input xresidualresíduo zero
Depois que o baseline é subtraído, os erros continuam organizados por x, em vez de se espalharem aleatoriamente em torno de zero.

Esse gráfico de resíduos deve parecer quase idêntico ao gráfico original do target. Subtrair a mesma constante, yˉ\bar y, desloca todos os pontos verticalmente sem mudar sua coordenada de input nem o formato do dataset. Os valores deslocados agora têm média zero, mas seu padrão ao longo de xx permanece.

A observação importante é que os resíduos não são necessariamente aleatórios.

Se o baseline subestima sistematicamente uma região da curva e superestima outra, os próprios resíduos contêm estrutura. Uma árvore de decisão pode aprender parte dessa estrutura.

Então treinamos uma árvore de regressão h1(x)h_1(x), mas agora seu target é o resíduo:

h1(x)yF0(x)h_1(x) \approx y-F_0(x)
Uma árvore rasa aprende uma aproximação regional dos resíduosUma árvore de profundidade dois ajusta quatro níveis constantes ao padrão dos resíduos. Sua linha em degraus é negativa à esquerda, fortemente positiva na elevação central e levemente positiva à direita.-101-303input xresidualh₁(x)
A árvore não consegue reproduzir todos os resíduos. Ela transforma o padrão regional compartilhado em uma função de correção.

A semelhança com a primeira árvore que desenhamos também é esperada. Subtrair uma única constante de todos os targets não muda quais limites de split mais reduzem o erro quadrático. Com as mesmas configurações, uma árvore treinada em yyˉy-\bar y aprende, portanto, as mesmas regiões que uma árvore treinada diretamente em yy; somente os valores de suas folhas são deslocados. Essa equivalência especial pertence à primeira rodada. Depois que F1(x)F_1(x) passa a variar pelo espaço de input, os resíduos seguintes deixam de ser um deslocamento constante dos targets originais.

Quando essa árvore aprende uma aproximação útil da correção, nós a adicionamos ao baseline:

F1(x)=F0(x)+h1(x)F_1(x)=F_0(x)+h_1(x)

Uma predição, portanto, já não vem de uma única árvore. Ela é a soma de um valor inicial e uma correção aprendida.

Adicionar a primeira correção transforma uma constante em um modelo regionalO baseline horizontal tracejado continua visível por trás do modelo atualizado em forma de degraus F um. Os targets observados permanecem fixos.-101-303input xtarget yF₀F₁
Os targets não se movem. O modelo sai do baseline tracejado e chega à predição atualizada sólida F₁ = F₀ + h₁.

Mesmo esse único passo já contém a maior parte da intuição por trás do boosting. O primeiro modelo não precisa resolver o problema inteiro. Ele apenas nos dá um ponto de partida. O modelo seguinte estuda o que ainda está errado e aprende uma função que move as predições em uma direção melhor.

Nada é tão simples assim

Há um problema em aplicar imediatamente a correção inteira.

Uma árvore de regressão é, ela própria, uma aproximação. Ela não conhece a verdadeira função de correção; apenas a estima a partir de um conjunto de treino finito. Se confiarmos completamente em cada árvore e adicionarmos suas predições em magnitude total, o ensemble poderá reagir agressivamente demais a padrões que existem apenas nos dados de treino.

Considere pontos de um conjunto de teste que nunca foram usados para treinar a árvore. Ela pode estimar bem as correções em algumas regiões e produzir correções desnecessariamente grandes em outras.

Uma maneira simples de tornar o processo mais conservador é reduzir cada correção antes de adicioná-la.

Em vez de

F1(x)=F0(x)+h1(x),F_1(x)=F_0(x)+h_1(x),

usamos

F1(x)=F0(x)+ηh1(x),F_1(x)=F_0(x)+\eta h_1(x),

em que η\eta é a learning rate, normalmente escolhida em algum ponto entre 0 e 1.

Se η=0,1\eta=0{,}1, por exemplo, uma árvore que propõe uma correção de +4+4 move a predição atual apenas em +0,4+0{,}4.

Isso significa que cada árvore individual tem menos influência, mas também que as árvores posteriores terão a oportunidade de continuar corrigindo o erro restante.

Mesmo antes de adicionarmos mais árvores, a learning rate determina quanto dessa primeira correção chega ao modelo. Um valor grande move as quatro predições regionais para mais longe do baseline. Um valor pequeno preserva as mesmas regiões, mas mantém cada passo mais próximo de F0F_0.

A interação abaixo mantém tanto F0F_0 quanto a árvore já ajustada h1h_1 fixos. Ela muda apenas o multiplicador em F1(x)=F0+ηh1(x)F_1(x)=F_0+\eta h_1(x). Antes de mover o slider, preveja que parte da linha em degraus pode mudar: os locais dos splits, suas alturas ou ambos.

Escale a primeira correçãoF₁(x) = F₀ + ηh₁(x) · η 1,00
Baseline mais uma árvoreRMSE 0,247
A primeira correção na learning rate selecionadaOs círculos vazados são os targets de validação. A linha horizontal tracejada é o baseline fixo. A linha em degraus com quatro níveis é esse baseline mais a primeira árvore de resíduos fixa, escalada pela learning rate. Os segmentos finos em âmbar são os resíduos de validação resultantes.-101-303input xF₀F₁(x)
Erros de validação
Distribuição dos resíduos de validaçãoA escala horizontal fixa vai de menos zero vírgula nove a mais zero vírgula nove. Resíduos mais próximos de zero formam barras perto da linha central.−0,900,9resíduo de validação

O baseline e a árvore permanecem fixos. η muda apenas a altura das quatro correções regionais da árvore.

Learning rate 1,00. Raiz do erro quadrático médio de validação 0,247.

Nesta amostra específica de validação, um valor um pouco abaixo de 11 tem desempenho ligeiramente melhor do que usar a primeira correção inteira. Isso basta para mostrar que reduzir uma correção aprendida pode ajudar, mas não torna esse valor universalmente ideal. Em ensembles completos, valores em torno de 0,10{,}1 são pontos de partida comuns porque as árvores posteriores continuam trabalhando no que resta. A learning rate apropriada depende do dataset, da complexidade das árvores, do número de iterações de boosting, da regularização e do comportamento de validação.

Mais árvores

Depois de treinar a primeira árvore, temos um modelo melhor:

F1(x)=F0(x)+ηh1(x)F_1(x)=F_0(x)+\eta h_1(x)

mas, em geral, não um modelo perfeito.

Então repetimos o mesmo procedimento.

Calculamos um novo resíduo para cada observação de treino:

ri(2)=yiF1(xi)r_i^{(2)} = y_i-F_1(x_i)

Esses resíduos descrevem o que o ensemble ainda precisa corrigir depois que a primeira árvore já contribuiu.

A primeira árvore deixa um novo target residual para a segunda árvoreO modelo atual F um e seus erros verticais restantes aparecem à esquerda. Os mesmos erros com sinal aparecem em torno de zero à direita, ainda organizados pelo input x.Modelo atual F₁-101-303input xO que F₁ ainda não captura-101-303input xF₁(x)zero
Depois que F₁ muda por região, os erros restantes formam um target genuinamente novo para a segunda árvore.

Agora podemos treinar outra árvore,

h2(x)r(2),h_2(x)\approx r^{(2)},

e atualizar o modelo novamente:

F2(x)=F1(x)+ηh2(x)=F0(x)+ηh1(x)+ηh2(x)F_2(x) = F_1(x)+\eta h_2(x) = F_0(x)+\eta h_1(x)+\eta h_2(x)

Para tornar essa atualização concreta, a figura seguinte isola três observações do mesmo conjunto de treino. Ela não mostra a curva ajustada inteira. Cada exemplo começa no baseline compartilhado F0F_0, acompanha a correção âmbar da primeira árvore até F1F_1 e depois acompanha a correção verde da segunda árvore até F2F_2. O círculo preto é o target observado, que nunca se move.

A segunda árvore responde aos erros deixados pela primeiraTrês observações dos dados de treino são mostradas. Cada target observado permanece fixo. Uma seta âmbar move a predição do baseline F zero para F um, e uma seta verde move F um para F dois. A segunda árvore continua descendo para a observação à esquerda, desfaz parte de um overshoot na observação central e continua subindo para a observação à direita.-101-303input xtarget ycontinua descendovoltacontinua subindoF₀primeira correçãosegunda correçãotarget observadoη 0.75
Três observações do mesmo conjunto de treino. A segunda árvore continua movendo a predição em direção ao target onde ainda há erro e volta onde a primeira árvore passou do ponto.

Nos exemplos à esquerda e à direita, ainda há erro na mesma direção após a primeira atualização, por isso a segunda árvore continua movendo a predição em direção ao target. No exemplo central, a primeira árvore passou do ponto, então a segunda correção aponta de volta. Aqui, os segundos passos são menores porque foram ajustados ao que restou depois da primeira árvore, e não porque a segunda árvore seja inerentemente mais fraca.

Esses são três recortes locais de um único modelo ajustado, não três modelos separados. O ensemble não está construindo uma decomposição fixa do target; cada novo learner responde às predições produzidas por todos os learners anteriores.

É por isso que a sequência importa.

A árvore h2h_2 resolve um problema diferente de h1h_1, porque h1h_1 já mudou as predições. A árvore h3h_3 resolverá outro problema mais uma vez.

Depois de MM iterações:

FM(x)=F0(x)+ηm=1Mhm(x)F_M(x) = F_0(x) + \eta\sum_{m=1}^{M}h_m(x)

A animação seguinte expande esse processo iterativo em suas três ações recorrentes. Os eixos e as observações permanecem fixos. Apenas o target residual atual, a árvore ajustada a ele e o modelo acumulado mudam. Use as rodadas numeradas para inspecionar diretamente qualquer estado ou reproduza a sequência completa.

Uma rodada de boosting muda o problema seguinteη 0,60 · quatro árvores de profundidade dois

Comece com uma predição constante.

Predição atual0 árvores
Predição atual do ensembleOs targets observados permanecem fixos enquanto o ensemble constante por partes muda conforme as árvores são adicionadas.-101-303input xF(x)
Próximo targetresidual
Resíduos restantesCada ponto mantém sua coordenada de input e se move para a diferença com sinal entre seu target e a predição atual.-101-303input xzero
baseline0,13
rodada atual

Comece com uma predição constante.

Há outra maneira útil de observar o mesmo processo.

Em vez de nos concentrarmos nas próprias árvores, podemos monitorar a distribuição dos erros restantes. No início do treino, os resíduos podem estar amplamente dispersos. Conforme correções úteis são adicionadas, esperamos que essa distribuição se concentre mais em torno de zero, pelo menos nos dados em que o modelo realmente está melhorando.

O histograma de resíduos e o traço do erro abaixo usam exatamente as mesmas quatro atualizações. Observe a distribuição se estreitar em torno de zero enquanto a raiz do erro quadrático médio diminui. Isso é evidência para esta execução de treino, não uma garantia de que o erro de validação sempre diminuirá.

Correções úteis puxam os erros restantes em direção a zero0 árvores · RMSE de treino 0,719
Predição atual
Predição atual do ensembleOs targets observados permanecem fixos enquanto o ensemble constante por partes muda conforme as árvores são adicionadas.-101-303input xF(x)
Erros restantes
Distribuição dos resíduos restantes−1.401.4
Erro por árvores
Erro ao longo das rodadas de boosting0.20.40.601234
árvores concluídas

Após 0 árvores, a raiz do erro quadrático médio de treino é 0,719.

A interação entre a learning rate e o número de árvores se torna particularmente importante aqui.

Com uma learning rate muito pequena e poucas árvores, o ensemble pode quase não se afastar de seu baseline. Com uma learning rate grande, as primeiras árvores podem passar bastante do ponto, forçando árvores posteriores a aprender correções na direção oposta. Entre esses extremos existe um regime em que cada árvore contribui o bastante para ser útil sem dominar o ensemble inteiro.

Agora varie as duas quantidades. Mantenha o número de árvores pequeno o bastante para que cada contribuição continue inspecionável. Uma learning rate muito pequena deve deixar estrutura visível nos resíduos depois de quatro rodadas. Uma taxa agressiva pode fazer uma árvore posterior apontar na direção oposta. Passe o cursor sobre o gráfico de predições, ou focalize-o e use as setas, para decompor uma predição em seu baseline e nas contribuições das árvores.

Equilibre o tamanho do passo e o número de árvores2 árvores · η 0,60 · RMSE 0,220
Predição compostapasse o cursor ou focalize para inspecionar x
Predição atual do ensembleOs targets observados permanecem fixos enquanto o ensemble constante por partes muda conforme as árvores são adicionadas.-101-303input xF(x)
O que restaapós F2
Resíduos restantesCada ponto mantém sua coordenada de input e se move para a diferença com sinal entre seu target e a predição atual.-101-303input xzero
baseline0,13
h1η × árvore 1
h2η × árvore 2
=prediçãoF2

Faça uma previsão primeiro: com apenas algumas árvores, um η pequeno vai parar antes do target, ou um η grande vai forçar as árvores posteriores a corrigirem de volta?

Número de árvores

2 árvores com learning rate 0,60. Raiz do erro quadrático médio de treino 0,220.

A learning rate desempenha dois papéis ao longo de várias rodadas. Ela escala diretamente cada contribuição e, ao mudar a predição atual, também muda o target residual usado para ajustar todas as árvores posteriores. É por isso que as próprias árvores podem mudar quando você move esse slider; diferentemente do playground anterior com uma única árvore, isso já não é uma árvore fixa vista em diferentes escalas.

Aumentando a complexidade

Nosso primeiro sinal unidimensional era intencionalmente esparso. Quatro árvores rasas bastavam para tornar cada contribuição inspecionável, mas não para mostrar o que um grande modelo aditivo pode construir.

No próximo experimento, preservaremos a visualização unidimensional, mas tornaremos o target muito mais rico. O novo sinal combina uma tendência global, ondas amplas, uma ondulação fina, duas características localizadas, duas mudanças de nível e ruído aleatório. Uma única árvore pequena não consegue expressar todas essas escalas ao mesmo tempo.

Antes de mexer nos controles, preveja o que um ensemble limitado aprenderá primeiro. Ele gastará suas primeiras árvores com a forma ampla ou com a elevação e a queda estreitas?

Construa detalhes com muitas árvores rasas50 árvores · η 0,10 · treino 0,108 · validação 0,152
Sinal em camadastendência · ondas amplas · ondulação fina · elevação e queda locais · mudanças de nível
Predição compostapontos de treino
Muitas árvores rasas aproximam o sinal em camadasSetenta e duas observações de treino contêm curvas amplas, uma ondulação fina, duas características localizadas, duas mudanças de nível e ruído. A linha tracejada é um ensemble anterior, e a linha verde é o orçamento de árvores selecionado.-101-303input xF50(x)
O que restapontos de validação
Resíduos de validação com o orçamento de árvores selecionadoCento e vinte observações de validação mantêm sua coordenada de input e se movem para o erro com sinal que ainda resta. Círculos vazados em âmbar as distinguem dos pontos de treino.-101-303input xzero
baseline0,10
+h1
+h2
+h3
h50
=ensembleF50

50 correções de profundidade dois

Faça uma previsão antes de mover o orçamento: qual estrutura aparece primeiro — a forma ampla ou os detalhes locais estreitos?

50 árvores com learning rate 0,10. Raiz do erro quadrático médio de treino 0,108. Raiz do erro quadrático médio de validação 0,152.

A estrutura ampla aparece com relativamente poucas árvores porque responde por erros grandes e repetidos. Detalhes locais menores precisam de um orçamento maior: só passam a valer a pena depois que o ensemble remove estrutura suficiente do padrão dominante.

O erro de validação também impõe um limite à intuição de que mais árvores são sempre melhores. O erro de treino continua caindo conforme o ensemble ganha capacidade. O erro de validação pode estabilizar ou eventualmente subir porque as árvores posteriores são cada vez mais capazes de modelar peculiaridades das observações de treino. Portanto, o número de árvores é uma escolha de regularização, e não apenas um pedido por mais acurácia.

Modelos reais de gradient boosting podem conter centenas ou milhares de learners. Cada novo learner observa a correção exigida pelo modelo em seu estágio atual e tenta generalizá-la.

Com muitas features de input, a árvore decide quais são úteis por meio de seus splits. Um ramo pode particionar os dados segundo a idade, outro segundo o saldo em conta e outro segundo a interação entre várias decisões anteriores. Não precisamos especificar manualmente qual feature deve responder por cada correção.

Essa é uma razão pela qual as árvores são especialmente atraentes como base learners para dados tabulares. Elas representam naturalmente limiares, não linearidades e interações entre features sem exigir que toda relação seja expressa como uma transformação suave em um espaço de representações contínuas.

As árvores individuais usadas em boosting costumam ser mantidas relativamente pequenas.

Se cada learner fosse uma árvore extremamente profunda, capaz de ajustar quase perfeitamente os resíduos atuais, então cada passo de boosting poderia memorizar grande parte do conjunto de treino. Árvores rasas fornecem, em vez disso, uma classe de funções restrita: cada atualização pode capturar apenas parte da estrutura restante.

Isso cria uma interação importante entre a complexidade das árvores, a learning rate e o número de rodadas de boosting. Centenas de árvores com uma learning rate suficientemente pequena podem construir gradualmente uma função útil, enquanto centenas de árvores altamente expressivas combinadas com atualizações agressivas podem eventualmente causar overfitting.

Também não há nada na definição matemática do gradient boosting que diga que os learners precisam ser árvores.

Em princípio, poderíamos usar modelos lineares, splines, pequenas redes neurais ou outras classes de funções. As árvores de decisão se tornaram a escolha dominante porque combinam uma capacidade de aproximação útil com um viés indutivo que funciona muito bem para muitos datasets estruturados.

O que fazemos quando queremos classificar?

Até aqui, nosso exemplo teve uma propriedade especialmente conveniente: a predição pode ser qualquer número real.

Se o target é contínuo, não há problema em predizer

4.2,0.7,38.1-4.2,\quad 0.7,\quad 38.1

ou qualquer outro valor em

(,).(-\infty,\infty).

Com erro quadrático, também podemos calcular uma correção particularmente intuitiva:

yy^y-\hat y

e adicionar um modelo que a prediga.

A classificação binária é diferente.

Agora, a quantidade final que queremos é uma probabilidade:

p(y=1x)[0,1].p(y=1\mid x)\in[0,1].

Adicionar correções arbitrárias diretamente às probabilidades seria problemático. Uma probabilidade de 0,90{,}9, por exemplo, não pode simplesmente receber uma correção de +0,4+0{,}4, porque 1,31{,}3 não é uma probabilidade válida.

Uma solução conveniente é realizar o boosting em outro espaço numérico.

Em vez de construir o modelo aditivo diretamente no espaço de probabilidade, transformamos probabilidades de (0,1)(0,1) em valores que podem ir de -\infty a ++\infty. As árvores operam nesse espaço sem restrições e, quando precisamos de uma probabilidade, transformamos a saída do modelo de volta para (0,1)(0,1).

A regressão prediz diretamente, enquanto a classificação faz boosting no espaço logitA regressão adiciona duas correções de árvores diretamente em uma reta numérica de predições reais. A classificação binária começa no espaço de probabilidade, em que os targets são zero ou um e as predições ficam entre eles. Logit mapeia a predição para uma reta numérica sem restrições, duas correções de árvores são adicionadas ali, e sigmoid mapeia o resultado de volta para uma probabilidade.Regressãoadicione diretamente no espaço de prediçãopredição com valor real−∞+∞F₀+ ηh₁+ ηh₂F₂Classificação bináriasaia do espaço de probabilidade apenas ao ajustar correçõesespaço de probabilidade01p₀ 0,40logitespaço logit−∞+∞F₀+ ηh₁+ ηh₂F₂sigmoidespaço de probabilidade01p₂ 0,53targets ficam em 0 ou 1 · predições retornam ao intervalo entre elesA regressão prediz diretamente, enquanto a classificação faz boosting no espaço logitA regressão adiciona duas correções de árvores diretamente em uma reta numérica de predições reais. A classificação binária começa no espaço de probabilidade, usa logit para entrar em uma reta numérica sem restrições, adiciona duas correções de árvores e usa sigmoid para retornar ao espaço de probabilidade, onde os targets são zero ou um.Regressãoadicione diretamente no espaço de predição−∞+∞F₀+ ηh₁+ ηh₂F₂Classificação bináriamude de espaço só para ajustar correçõesespaço de probabilidade01p₀ 0,40logitespaço logit−∞+∞F₀+ ηh₁+ ηh₂F₂sigmoidespaço de probabilidade01p₂ 0,53targets: 0 ou 1 · predições: entre eles
A regressão adiciona na reta de predição. A classificação usa o espaço logit para as adições; depois, a sigmoid transforma o score de volta em probabilidade.

Sigmoid e logits

As duas funções que conectam esses espaços são a sigmoid e o logit.

A sigmoid recebe qualquer número real zz e o mapeia para um valor entre zero e um:

σ(z)=11+ez.\sigma(z) = \frac{1}{1+e^{-z}}.

Quando zz\rightarrow-\infty, a sigmoid se aproxima de zero. Quando z+z\rightarrow+\infty, ela se aproxima de um.

Sua inversa é o logit:

logit(p)=log(p1p).\operatorname{logit}(p) = \log\left(\frac{p}{1-p}\right).

O logit recebe uma probabilidade p(0,1)p\in(0,1) e a mapeia para toda a reta real.

Sigmoid: logit → probabilidade

00.51-404z = −0,405 → p = 0,40logit zprobabilidade p

Logit: probabilidade → logit

-8-4048-1012p = 0,40 → z = −0,405probabilidade plogit z−∞ quando p → 0+∞ quando p → 1
As funções desfazem uma à outra: trocar as coordenadas horizontal e vertical transforma um gráfico no outro. O baseline compartilhado aparece nas duas visualizações: a probabilidade 0,40 é o logit −0,405.

Portanto, essas funções formam uma ponte de duas direções:

plogitzsigmoidp.p \overset{\text{logit}}{\longrightarrow} z \overset{\text{sigmoid}}{\longrightarrow} p.

Uma probabilidade de 0,50{,}5 corresponde a um logit de 00. Probabilidades acima de 0,50{,}5 têm logits positivos, enquanto probabilidades abaixo de 0,50{,}5 têm logits negativos.

O gradient boosting pode construir um modelo aditivo nesse espaço logit:

FM(x)=F0(x)+ηh1(x)++ηhM(x),F_M(x) = F_0(x) + \eta h_1(x) +\cdots+ \eta h_M(x),

e a probabilidade final é

p(x)=σ(FM(x)).p(x)=\sigma(F_M(x)).

Juntando as peças

Considere um dataset de classificação unidimensional com quarenta observações. Ele mantém o mesmo intervalo de input do problema de regressão, mas agora cada target é a classe 00 ou a classe 11. Dezesseis observações pertencem à classe 11, e vinte e quatro pertencem à classe 00.

As tabelas abaixo destacam cinco observações desse dataset. Manteremos o problema completo com quarenta linhas fixo em todas as tabelas, curvas, árvores e animações desta seção.

Antes de treinar a primeira árvore, precisamos novamente de um baseline.

A probabilidade empírica da classe 11 é

p0=1640=0.4.p_0=\frac{16}{40}=0.4.

Como nosso modelo aditivo opera no espaço logit, o valor inicial do modelo é

F0=logit(0.4)=log(0.40.6)0.405.F_0 = \operatorname{logit}(0.4) = \log\left(\frac{0.4}{0.6}\right) \approx -0.405.

Cada observação recebe inicialmente esse mesmo logit, que corresponde, por meio da sigmoid, a uma probabilidade de 0,40{,}4.

Agora precisamos decidir o que a próxima árvore deve aprender.

Com entropia cruzada binária, a quantidade relevante é

ri=yipi.r_i=y_i-p_i.

Se yi=1y_i=1 enquanto o modelo atual prediz pi=0,4p_i=0{,}4, então

ri=10.4=0.6.r_i=1-0.4=0.6.

O modelo precisa se mover em uma direção que aumente o logit e, portanto, aumente a probabilidade.

Se yi=0y_i=0,

ri=00.4=0.4,r_i=0-0.4=-0.4,

então a correção aponta na direção oposta.

Esses valores costumam ser chamados de pseudo-resíduos porque desempenham o mesmo papel que os resíduos comuns desempenharam na regressão com erro quadrático, embora surjam do gradiente de uma loss diferente.

Vamos derivar isso formalmente mais adiante. Por enquanto, a ideia importante é que a loss nos fornece um sinal de correção para cada observação de treino.

A loss fornece a cada observação um sinal de correção com sinalregional-classes-v1 · linhas destacadas
A loss fornece a cada observação um sinal de correção com sinal
linhainput xclasse ybaseline p₀baseline F₀sinal y − p₀
C07−1,9700,40−0,405−0,40
C16−0,6510,40−0,4050,60
C19−0,2200,40−0,405−0,40
C260,8010,40−0,4050,60
C352,1200,40−0,405−0,40
No baseline, as linhas da classe 1 pedem +0,60, e as linhas da classe 0 pedem −0,40 na direção do gradiente de primeira ordem.

Na construção de primeira ordem usada pelos playgrounds deste artigo, uma nova árvore modela esse sinal de correção pelo espaço de features. Algumas implementações de produção refinam depois os valores das folhas usando a curvatura da loss. Isso muda o tamanho da atualização, e não o próprio loop de correção.

Para a observação C16, a primeira árvore ajustada e uma learning rate de 0,80{,}8 contribuem com aproximadamente +0,292+0{,}292 no espaço logit. Partindo de

F0=0.405,F_0=-0.405,

o score atualizado se torna

F10.405+0.2920.114.F_1\approx-0.405+0.292\approx-0.114.

Para convertê-lo de volta em probabilidade:

p1=σ(0.114)=11+e0.1140.472.p_1 = \sigma(-0.114) = \frac{1}{1+e^{0.114}} \approx 0.472.

Assim, a probabilidade passa de 0,40{,}4 para cerca de 0,4720{,}472.

Se essa observação pertence à classe 11, essa é uma correção útil. Para observações da classe 00, atualizações úteis devem, em geral, mover seus logits para baixo e, consequentemente, reduzir suas probabilidades.

Uma árvore move diferentes regiões do input em direções diferentesregional-classes-v1 · linhas destacadas
Uma árvore move diferentes regiões do input em direções diferentes
linhainput xclasse ybaseline p₀baseline F₀sinal y − p₀ηh₁(x)novo F₁novo p₁
C07−1,9700,40−0,405−0,40−0,32−0,7250,33
C16−0,6510,40−0,4050,600,29−0,1140,47
C19−0,2200,40−0,405−0,400,29−0,1140,47
C260,8010,40−0,4050,600,29−0,1140,47
C352,1200,40−0,405−0,40−0,02−0,4250,40
A árvore prediz o padrão dos pseudo-resíduos por região. Sua saída escalada é adicionada ao logit; depois, a sigmoid converte o resultado de volta em probabilidade.

Observe que a árvore não corrige cada observação de forma independente. Ela aprende um único padrão regional. Uma observação ruidosa da classe 00 pode, portanto, se mover para cima junto de observações próximas da classe 11, mesmo enquanto a entropia cruzada total diminui. O boosting melhora o modelo compartilhado, não necessariamente cada linha em cada rodada.

Depois da atualização, o modelo deve atribuir probabilidades menores a pelo menos alguns exemplos da classe 00 e probabilidades maiores a pelo menos alguns exemplos da classe 11. Podemos então calcular uma nova probabilidade para cada observação, obter um novo conjunto de pseudo-resíduos, treinar outra árvore e repetir o processo.

A arquitetura geral é, portanto, quase a mesma da regressão.

O que muda é a loss e, como a loss muda, também muda o sinal de correção produzido em cada iteração.

Um exemplo mais concreto

As cinco linhas destacadas expõem a aritmética, mas o dataset completo torna visível o padrão regional de decisão.

As mesmas quarenta observações agora aparecem sobre duas linhas de classe. Em vez de aprender um target contínuo de regressão, o modelo precisa aprender como a probabilidade da classe 11 muda pelo espaço de input.

Antes de pressionar Reproduzir, preveja o que permanecerá igual à regressão e o que precisará mudar. Depois, acompanhe os rótulos de classe, o sinal de correção ypy-p e as contribuições aditivas no espaço logit ao longo de quatro árvores rasas.

O loop de correção sobrevive a uma nova loss0 árvores · η 0,80 · log loss 0,673

Comece pela taxa da classe um: p₀ = 0,40 e F₀ = −0,405.

Probabilidade da classe 1os rótulos permanecem fixos
Probabilidade atual da classe umAs observações binárias permanecem fixas em zero e um. Uma curva verde por partes mostra a probabilidade obtida ao aplicar a sigmoid ao modelo logit acumulado.00.51-303input xp0(x)classe 1classe 0
Sinal de correção y − ppróxima árvore h1
Sinal atual de correção dos pseudo-resíduosCada observação mantém sua coordenada de input e se move para y menos a probabilidade atual da classe um. A linha em degraus âmbar é a próxima árvore rasa ajustada a esse sinal.-101-303input xzeroh1(x)
baseline logit−0,405
=logit F0score
sigmoidp0

passe o cursor ou focalize um ponto

árvores concluídas

Após 0 árvores, a log loss de treino é 0,673. A curva de probabilidade é a sigmoid do modelo logit aditivo.

A diferença importante é o que a curva representa.

Na regressão, o ensemble aproximava diretamente o target numérico. Na classificação binária, o ensemble aditivo constrói um score no espaço logit, enquanto a sigmoid transforma esse score na curva de probabilidade que realmente interpretamos.

Uma árvore que produz uma correção positiva em algum intervalo aumenta ali o log-odds da classe 11. Uma correção negativa o reduz. Repetir esses ajustes locais pode, com o tempo, formar uma fronteira de classificação altamente não linear, embora cada árvore individual continue pequena.

Antes de adicionar mais notação, comprima toda a jornada em um único loop. O modelo atual produz predições. A loss escolhida transforma essas predições em um sinal de correção. Uma árvore pequena aprende a parte desse sinal que pode ser explicada pelos inputs. Reduzimos e adicionamos a árvore, obtemos um novo modelo e consultamos a loss novamente.

Regressão e classificação diferem no espaço de predição e no sinal de correção, mas não nessa sequência.

Matemática

Regressão

A explicação baseada em resíduos acima é exata para um caso particularmente importante: regressão com erro quadrático.

Suponha que nosso conjunto de treino seja

{(xi,yi)}i=1n,\{(x_i,y_i)\}_{i=1}^{n},

e que nosso modelo atual seja F(x)F(x).

Queremos minimizar uma loss empírica

L(F)=i=1nL(yi,F(xi)).\mathcal{L}(F) = \sum_{i=1}^{n} L(y_i,F(x_i)).

Para o erro quadrático, podemos escrever

L(yi,F(xi))=12(yiF(xi))2.L(y_i,F(x_i)) = \frac{1}{2} \left(y_i-F(x_i)\right)^2.

A derivada em relação à predição F(xi)F(x_i) é

LF(xi)=F(xi)yi.\frac{\partial L}{\partial F(x_i)} = F(x_i)-y_i.

Portanto, a derivada negativa é

LF(xi)=yiF(xi),-\frac{\partial L}{\partial F(x_i)} = y_i-F(x_i),

que é exatamente o resíduo.

Isso nos dá uma interpretação mais geral do que fazíamos antes.

Na iteração de boosting mm, calculamos

rim=[L(yi,F(xi))F(xi)]F=Fm1.r_{im} = - \left[ \frac{\partial L(y_i,F(x_i))} {\partial F(x_i)} \right]_{F=F_{m-1}}.

Esses são os gradientes negativos da loss em relação às predições atuais.

Então ajustamos um learner hm(x)h_m(x) de modo que

hm(xi)rim.h_m(x_i)\approx r_{im}.

Por fim, atualizamos a função preditiva:

Fm(x)=Fm1(x)+ηhm(x).F_m(x) = F_{m-1}(x) + \eta h_m(x).

Para o erro quadrático, isso se reduz ao procedimento intuitivo com resíduos que já vimos, porque o gradiente negativo é justamente yy^y-\hat y.

Para outra loss diferenciável, o gradiente negativo geralmente será outra coisa.

É nesse ponto que a palavra gradient em gradient boosting se torna precisa.

O gradiente não é calculado em relação aos limiares de split de uma árvore de decisão, e não estamos diferenciando através da árvore. Em vez disso, em cada observação de treino, perguntamos como a loss mudaria se a predição atual se movesse um pouco.

Se o modelo atual produz o vetor

F=[F(x1)F(x2)F(xn)],\mathbf F = \begin{bmatrix} F(x_1)\\ F(x_2)\\ \vdots\\ F(x_n) \end{bmatrix},

então a loss define um vetor gradiente

FL=[LF(x1)LF(x2)LF(xn)].\nabla_{\mathbf F}\mathcal L = \begin{bmatrix} \frac{\partial \mathcal L}{\partial F(x_1)}\\ \frac{\partial \mathcal L}{\partial F(x_2)}\\ \vdots\\ \frac{\partial \mathcal L}{\partial F(x_n)} \end{bmatrix}.

O gradient descent comum gostaria de mover as predições na direção

FL.-\nabla_{\mathbf F}\mathcal L.

Mas simplesmente armazenar uma correção independente para cada ponto de treino não nos daria um modelo capaz de produzir predições para inputs nunca vistos.

Por isso, o gradient boosting introduz uma aproximação crucial: ele treina um learner hm(x)h_m(x) para generalizar a direção desejada do gradiente como função das features.

Essa é a ponte central entre otimização e aprendizado supervisionado.

O gradiente nos diz como as predições deveriam mudar no conjunto de treino. O weak learner procura estrutura nessas mudanças e as transforma em uma função que também pode ser avaliada em novos valores de xx.

Essa perspectiva costuma ser descrita como otimização no espaço de funções.

No gradient descent comum, poderíamos ter

f(x;θ)f(x;\theta)

e atualizar um vetor de parâmetros com dimensão finita:

θm=θm1ηθL.\theta_m = \theta_{m-1} - \eta\nabla_\theta\mathcal L.

No gradient boosting, construímos a função preditiva de forma aditiva:

Fm=Fm1+ηhm.F_m = F_{m-1} + \eta h_m.

A direção de busca é, portanto, representada por uma nova função, e não por uma perturbação direta de um vetor de parâmetros existente.

Uma versão mais completa da atualização também pode incluir um tamanho de passo γm\gamma_m:

Fm(x)=Fm1(x)+ηγmhm(x),F_m(x) = F_{m-1}(x) + \eta\gamma_m h_m(x),

em que

γm=argminγi=1nL(yi,Fm1(xi)+γhm(xi)).\gamma_m = \arg\min_\gamma \sum_{i=1}^{n} L\left( y_i, F_{m-1}(x_i)+\gamma h_m(x_i) \right).

Diferentes implementações aproximam ou otimizam essas atualizações de formas diferentes, mas a estrutura fundamental permanece a mesma: obter uma direção a partir da loss, aproximar essa direção com um learner e adicionar o learner à função atual.

Mude a loss, e o alvo da correção muda. O mecanismo de ajustar e adicionar permanece o mesmo.

Quando formulamos o boosting dessa maneira, a regressão com erro quadrático deixa de ser um algoritmo especial e se torna uma instância de um framework geral.

Mude a loss, e o gradiente muda com ela. O mesmo procedimento aditivo pode, portanto, ser adaptado a objetivos semelhantes ao erro absoluto, regressão de Poisson, classificação binária, classificação multiclasse e muitas outras tarefas.

Classificação

Vamos agora formalizar o procedimento de classificação binária.

Para um target binário

yi{0,1},y_i\in\{0,1\},

deixamos o ensemble produzir um score bruto

F(xi)R.F(x_i)\in\mathbb R.

Esse score representa um logit. A probabilidade correspondente é

pi=σ(F(xi))=11+eF(xi).p_i = \sigma(F(x_i)) = \frac{1}{1+e^{-F(x_i)}}.

Podemos otimizar a entropia cruzada binária:

L(yi,F(xi))=[yilogpi+(1yi)log(1pi)].L(y_i,F(x_i)) = - \left[ y_i\log p_i + (1-y_i)\log(1-p_i) \right].

Embora a loss seja escrita em termos de pip_i, essa probabilidade depende do score bruto do modelo por meio de

pi=σ(F(xi)).p_i=\sigma(F(x_i)).

Calcular a derivada em relação ao score bruto resulta em

LF(xi)=piyi.\frac{\partial L}{\partial F(x_i)} = p_i-y_i.

Portanto, o gradiente negativo é

LF(xi)=yipi.-\frac{\partial L}{\partial F(x_i)} = y_i-p_i.

Esse é precisamente o pseudo-resíduo apresentado antes.

Na iteração mm,

pim=σ(Fm1(xi)),p_{im} = \sigma(F_{m-1}(x_i)),

e calculamos

rim=yipim.r_{im} = y_i-p_{im}.

Uma árvore é então ajustada usando esses sinais de gradiente como targets.

Conceitualmente:

hm(xi)yipim.h_m(x_i)\approx y_i-p_{im}.

O ensemble é atualizado em seguida no espaço de score bruto,

Fm(x)=Fm1(x)+ηcorrectionm(x),F_m(x) = F_{m-1}(x) + \eta\,\text{correction}_m(x),

e a nova probabilidade é

pm(x)=σ(Fm(x)).p_m(x) = \sigma(F_m(x)).

Isso torna muito mais clara a semelhança com a regressão.

Para regressão com erro quadrático:

ri=yiF(xi).r_i=y_i-F(x_i).

Para classificação logística:

ri=yiσ(F(xi)).r_i=y_i-\sigma(F(x_i)).

Nos dois casos, essas quantidades são gradientes negativos da loss escolhida em relação à representação atual da predição.

Nota opcional de implementação: usando a curvatura para escolher os valores das folhas

Dizer que uma árvore de classificação prediz ypy-p é a descrição de primeira ordem usada pelos playgrounds deste artigo. Muitos algoritmos práticos de gradient boosting não calculam simplesmente a média desses pseudo-resíduos dentro de uma folha para adicionar diretamente esse valor. Depois que uma árvore define suas regiões, o valor atribuído a cada folha pode ser escolhido para minimizar a loss. Isso pode usar informações de curvatura da segunda derivada.

Para a loss logística, considere

gi=LF(xi)=piyi,g_i = \frac{\partial L}{\partial F(x_i)} = p_i-y_i,

enquanto

Hi=2LF(xi)2=pi(1pi).H_i = \frac{\partial^2L}{\partial F(x_i)^2} = p_i(1-p_i).

Uma aproximação de segunda ordem da loss em torno da predição atual tem a forma

L(F+Δ)L(F)+gΔ+12HΔ2.L(F+\Delta) \approx L(F) + g\Delta + \frac{1}{2}H\Delta^2.

Minimizar essa aproximação quadrática local produz uma correção semelhante à de Newton

ΔgH.\Delta \approx -\frac{g}{H}.

Quando várias observações caem em uma folha RjR_j da árvore, um passo de Newton agregado correspondente tem a forma geral

wjiRjgiiRjHi,w_j \approx - \frac{\sum_{i\in R_j}g_i} {\sum_{i\in R_j}H_i},

antes de considerar termos adicionais de regularização que uma implementação específica pode introduzir.

Como

igi=i(yipi),-\sum_i g_i = \sum_i(y_i-p_i),

as explicações de primeira e de segunda ordem não competem entre si. O pseudo-resíduo fornece a direção em que a loss quer mover cada predição. A curvatura pode ajudar a escolher o tamanho da atualização. Essa é a ideia por trás de métodos de boosting de segunda ordem, como o XGBoost, embora cada implementação acrescente sua própria regularização, seus critérios de split e sua estrutura computacional.

A predição inicial da classificação também decorre diretamente da loss.

Se o conjunto de treino contém uma fração

yˉ=1ni=1nyi\bar y = \frac{1}{n}\sum_{i=1}^{n}y_i

de exemplos positivos, então a probabilidade constante que minimiza a entropia cruzada binária é

p0=yˉ.p_0=\bar y.

Como o ensemble opera no espaço logit, o score bruto inicial correspondente é

F0=log(yˉ1yˉ).F_0 = \log\left( \frac{\bar y}{1-\bar y} \right).

A partir daí, o boosting calcula repetidamente probabilidades, deriva gradientes da loss, ajusta árvores a padrões úteis de correção e atualiza o score aditivo.

O mesmo princípio geral se estende para além da classificação binária. Problemas multiclasse exigem vários scores de classe e uma transformação softmax, enquanto outros objetivos estatísticos produzem seus próprios gradientes e Hessianas. A mecânica se torna mais elaborada, mas o procedimento central permanece o mesmo.

Conclusão e ressalvas

O gradient boosting se torna consideravelmente mais fácil de entender quando deixamos de pensar nele como uma sequência misteriosa de árvores.

O ensemble começa com uma função simples:

F0(x).F_0(x).

A loss nos diz como as predições atuais deveriam mudar. Um weak learner observa essas correções desejadas pelo conjunto de treino e tenta generalizá-las a partir das features de input. Reduzimos sua contribuição, adicionamos ao modelo atual, calculamos o que ainda está errado e repetimos.

Para regressão com erro quadrático, essas correções são os resíduos conhecidos

yy^.y-\hat y.

De forma mais geral, são gradientes negativos

LF(x).-\frac{\partial L}{\partial F(x)}.

É isso que permite ao mesmo framework passar da regressão para a classificação e para muitos outros objetivos apenas pela mudança da loss.

Árvores de decisão são especialmente eficazes como learners dentro desse processo porque conseguem capturar limiares, interações e estruturas não lineares que aparecem com frequência em dados tabulares. Ao mesmo tempo, manter as árvores individuais fracas força o ensemble a construir a função final gradualmente, em vez de permitir que um learner domine o ajuste.

Essa construção gradual introduz vários trade-offs. A learning rate controla a magnitude de cada atualização. A profundidade da árvore controla a complexidade disponível em uma única atualização. O número de rodadas de boosting controla quantas oportunidades o ensemble recebe para se corrigir. Aumentar qualquer um deles indiscriminadamente pode, com o tempo, fazer o modelo ajustar estruturas específicas do treino em vez de padrões generalizáveis, razão pela qual o desempenho de validação e o early stopping são importantes na prática.

A interpretação pela otimização também tem uma limitação importante. Uma árvore não reproduz de forma independente o vetor exato do gradiente negativo para cada observação. Ela aproxima esse vetor usando uma classe de funções restrita. Pontos atribuídos à mesma folha compartilham uma correção, e a qualidade de cada passo de boosting depende, portanto, de a árvore conseguir encontrar estrutura significativa nos gradientes.

Essa restrição também é parte do que torna o método útil. Em vez de memorizar uma atualização arbitrária para cada observação de treino, o gradient boosting procura repetidamente correções que possam ser expressas como regras reutilizáveis sobre o espaço de features.

Depois de iterações suficientes, o modelo final pode conter centenas de árvores, mas cada uma resolve um problema relativamente modesto:

Dado o que o ensemble prediz agora, qual correc¸a˜o sistemaˊtica deve vir em seguida?\text{Dado o que o ensemble prediz agora, qual correção sistemática deve vir em seguida?}

Gradient Boosted Decision Trees transformam essa sequência de pequenas perguntas em uma poderosa função preditiva.