Você está na página 1de 36

PARTE I

Métodos de Ensemble Learning

Neste guia, explicaremos os algoritmos de gradient boosting, que são o


state of the art em Machine Learning quando se pensa em dados tabulares,
pois o resultado da operação apresenta um bom equilíbrio entre tempo de
processamento e performance.

Na primeira parte, falaremos sobre o que são métodos de ensemble e um


pouco da história de desenvolvimento de alguns modelos de boosting. A
segunda parte, será dedicada exclusivamente ao XGB oost, que é,
provavelmente, o mais conhecido desses modelos. Na última etapa, será feita
uma comparação deste com LightGB M e o CatB oost, de modo a fornecer
um guia de quando usar cada um destes algoritmos.

Métodos de Ensemble Learning

https://www.kdnuggets.com/wp-content/uploads/ensemble-framework-packt.jpg

02
PARTE I - Métodos de Ensemble Learning

Introdução ao Ensemble Learning

Vamos começar com uma introdução intuitiva sobre métodos de ensemble.


Quando você está construindo um modelo, você quer escolher aquele com a
melhor performance de acordo com alguma métrica. Considere este exemplo:

Aqui treinamos uma Árvore de Decisão, uma Regressão Logística e um KNN.


Se a acurácia fosse nossa métrica escolhida, então a Árvore de Decisão seria
nossa melhor escolha, certo? O problema de fazer isso é que estamos
descartando os outros modelos, que foram capazes de aprender diferentes
padrões e podem ter propriedades úteis. O que podemos fazer sobre isso?

Considere outro exemplo.

Quando você conduz uma pesquisa de opinião, você não aceita apenas uma
“melhor” resposta. Você considera uma resposta combinada de todos os
participantes e usa estatísticas como a moda ou a média para representar as
respostas. As respostas combinadas provavelmente vão levar a uma decisão
melhor do que confiar em apenas uma resposta. É o princípio da wisdom of the
crown (sabedoria das multidões) entrando em prática.

O mesmo princípio se aplica aos métodos de ensemble, onde podemos formar


um novo modelo combinando os existentes.

03
PARTE I - Métodos de Ensemble Learning

Esse agrupamento objetiva, ao juntar múltiplos modelos mais fracos, diminuir a


suscetibilidade geral deles ao viés e a variância, tornando-os mais robustos.
Portanto, os métodos de ensemble devem levar em conta a maneira com a qual
eles agrupam os modelos, associando os algoritmos de forma a minimizar suas
desvantagens individuais no modelo final.

Isto é ensemble learning, uma das técnicas mais efetivas em Machine


Learning. Existem variados métodos de ensemble, mas neste texto focaremos
principalmente em Bagging, Boosting e Stacking, os tipos mais utilizados em
Data Science.

Bagging
Antes de entendermos Bagging, precisamos primeiro entender o que é
Bootstrapping. Essa técnica consiste em subdividir nosso dataset, tomando
elementos de forma aleatória e com reposição.

Assumindo que a amostra é representativa da população (ambas têm


aproximadamente a mesma distribuição), podemos “reconstruir” a população
criando várias (infinitas) cópias da amostra. Como a população deve ser parecida
com a amostra, esperamos que essa “reconstrução” se aproxime da população
inteira.

Em estatística, a partir dessa população reconstruída, podemos criar novas


amostras e, dessa forma, estudar as propriedades das amostras em relação à
população. Isso nos permite, por exemplo, entender melhor o comportamento
da média e do desvio padrão dos dados que estão além do dataset.

O bagging treina modelos individuais usando uma amostra aleatória para cada.
Depois dos modelos individuais serem treinados com suas respectivas amostras,
eles são agregados usando uma média nos problemas de regressão ou uma
votação nos problemas de classificação.

Essa é a técnica usada no Random


Forest, por exemplo, que usa diversas
árvores de decisão como modelos
individuais, além de fazer uma seleção
aleatória de variáveis também.

Fonte: https://www.datacamp.com 04
PARTE I - Métodos de Ensemble Learning

Mas por que usar o bagging é útil?


Primeiro, ajuda a reduzir a variância, já que a amostragem é aleatória. O viés
também pode ser reduzido, já que usamos uma média ou votação para
combinar os modelos. Por causa do alto número de estimadores usados, o
bagging fornece estabilidade e robustez.

Por outro lado, realizar o bagging tem um custo computacional alto, em termos
de espaço e tempo, pois a cada nova iteração é criada uma amostra diferente.
Além disso, essa técnica só funciona se o modelo base tiver uma boa
performance. Usar o bagging em um modelo base ruim pode fazer com que o
modelo final fique ainda pior. Por último, por se tratar de um preditor
homogêneo, ou seja, os modelos individuais usam o mesmo algoritmo, o
bagging pode não reconhecer alguns padrões de decisão da base.

Boosting
Os métodos de boosting formam uma outra categoria de Ensemble Learning,
com foco principalmente em diminuir o viés dos modelos iniciais. Esse tipo de
aprendizado se tornou muito conhecido no meio de Data Science nos últimos
anos, por obter ótimos resultados em competições de Machine Learning, devido
a sua grande adaptabilidade.

Mas qual a teoria por trás desse algoritmo?


Assim como bagging, os métodos de boosting têm como base treinar vários
padrões mais simples com a finalidade de produzir um modelo final mais
robusto. No entanto, nos algoritmos de Boosting, os modelos não são mais
treinados de forma independente entre si, mas de maneira sequencial, a partir
de um ajuste dos protótipos treinados previamente.

Para maximizar o desempenho do preditor final, o boosting treina


iterativamente novos modelos com um enfoque nas observações de que os
anteriores erraram mais, tornando a predição mais resistente ao viés. Em
seguida, atualiza-se o padrão para priorizar as predições com maior erro nas
observações da base de teste. O modo como ocorre esse treinamento e essa
atualização é onde diferem os diferentes algoritmos de boosting.

Como o principal foco dos métodos de Boosting é de reduzir o viés dos “weak
learners (modelos simples)”, é ideal escolher como base para a agregação um
tipo simples com alto viés e baixa variância. Decorrente disso, geralmente
escolhemos árvores de decisão de baixa profundidade para compor o preditor
final.

05
PARTE I - Métodos de Ensemble Learning

AdaBoost
Adaptive Boosting é um algoritmo que consiste em combinar de forma
sequencial vários modelos mais fracos. Sendo assim, o weak learner
subsequente leva em consideração as predições do anterior, para formar um
preditor mais conciso. O diferencial desse algoritmo é que as predições mais
difíceis (aquelas em que o weak learner da iteração atual mal previu) recebem
um peso maior no preditor seguinte, buscando assim uma maior otimização do
algoritmo final.

Noutros termos, cada modelo é inicializado com um peso padrão, que define seu
poder de decisão no protótipo final. A partir disso, conforme vamos treinando
esses modelos mais simples, cada weak learner ganha um peso maior para as
observações em que ele previu corretamente, e um peso menor para as
observações em que ele possui um alto índice de erro.

Repare aqui que existem dois pesos. O primeiro é o peso para cada observação
que representa o grau de foco que a iteração em questão deve dar para aquela
observação. A cada novo modelo treinado, esses pesos das amostras são
atualizados. Já o segundo é um peso para cada modelo que representa seu
poder de decisão quando são combinados. Eles atribuem apenas uma vez para
cada estimador.

Dessa forma, os weak learners com maior precisão terão maior poder de
decisão no modelo final.

Fonte: https://towardsdatascience.com/understanding-adaboost-2f94f22d5bfe
06
PARTE I - Métodos de Ensemble Learning

Gradient Boosting
O gradient boosting é um outro tipo de algoritmo de boosting, que difere do
adaboost quanto à maneira com a qual os modelos são treinados com relação
aos anteriores.

Ao invés de estabelecer pesos para os weak learners, o gradient boosting treina


novos padrões diretamente no erro dos anteriores. Ou seja, os novos tipos tentam
prever o erro dos anteriores em vez de prever independentemente o target.
Dessa forma, obtemos a predição final somando a predição de todos os weak
learners.

O algoritmo do gradient boosting funciona assim: o primeiro modelo faz uma


aproximação bem simples da predição, e obtemos os nossos erros residuais
(observado menos o previsto); depois, treinamos mais modelos nesses erros
residuais, para tentar predizer o erro do primeiro modelo. Dessa forma, quando
somamos as predições de cada um para obter a predição final, obtemos uma
versão mais corrigida da primeira:

Fonte:: https://medium.com/mlreview/gradient-boosting-from-scratch-1e317ae4587d
07
PARTE I - Métodos de Ensemble Learning

Repetimos esse processo por várias iterações, obtendo erros residuais cada vez
menores.

Fonte: https://medium.com/mlreview/gradient-boosting-from-scratch-1e317ae4587d

Stacking
Para explicar como o stacking funciona, vamos usar uma analogia
esportiva.

Considere uma corrida em grupo, onde os corredores correm até passar o bastão
para o próximo no caminho. Este é um bom exemplo de trabalho em equipe.
Enquanto todos os membros do time devem ser competidores fortes, cada
indivíduo tem um papel especial baseado em suas habilidades. Por exemplo, o
âncora é o último membro a receber o bastão e aquele que completa a corrida.
Em algum nível, ele é como o líder do time.

08
PARTE I - Métodos de Ensemble Learning

Para ser efetivo nessas corridas, o âncora deve: saber as forças e fraquezas de
cada membro do time, definir responsabilidades para cada membro e, por fim,
participar da corrida.

Métodos de stacking levam esta ideia das corridas em grupo. Ao invés de passar
um bastão, modelos individuais passam suas predições para o próximo modelo.
Abaixo, temos um diagrama ilustrando a arquitetura de ensembles de stacking.

Fonte: https://www.datacamp.com

Cada modelo individual usa o mesmo dataset e input features. Esses são os
estimadores da primeira camada. Então, os estimadores passam suas predições
como features adicionais para a segunda camada.

Até agora, vimos métodos de ensemble que usam simples operações aritméticas
como, por exemplo, a média ou a moda para combinar os seus tipos. No entanto,
no stacking, o combinador é por si só um modelo passível de ser treinado. Além
disso, a espécie combinadora não tem apenas as predições como features, mas
também o dataset original. Isto permite determinar qual estimador é mais
acurado dependendo das features de input.

O modelo agregador desempenha um papel similar ao âncora na corrida. É


também o último membro da equipe, e aquele que fornece a predição final. Para
ser efetivo, o protótipo deve dispor das mesmas características que o âncora:
deve aprender a identificar as forças e fraquezas dos estimadores individuais,
escolher qual modelo fornece a melhor predição (dependendo das features de
input), e, por fim, ser um modelo útil para aprender padrões com o objetivo de
prever o target.

09
PARTE II
XGBoost

Fonte: https://www.discoverbits.in/post/wp-content/uploads/2018/08/xgboost.png

Para explicar o processo de construção de árvores, vamos usar um exemplo de


como o XGBoost funciona para a regressão. Após a explicação, veremos as
diferenças no caso de problemas de classificação.

Construção de árvores para regressão


Vamos começar aprendendo sobre como o XGBoost constrói as árvores de
decisão. Para isso, vamos usar um exemplo de um problema de regressão, com
dados extremamente simples, como podemos observar na figura abaixo:

Fonte: StatsQuest

No eixo x, temos diferentes dosagens de um remédio, enquanto no eixo y,


medimos a efetividade do medicamento. Existem duas observações com alta
efetividade, o que significa que o remédio foi útil. Já as duas observações com
baixa efetividade representam exemplos de onde o medicamento foi mais
prejudicial do que benéfico.

O primeiro passo no processo de treinamento do XGBoost é fazer uma predição


inicial. Esta predição pode ser qualquer coisa, mas por padrão ela é 0.5, tanto para
os problemas de regressão quanto para os de classificação. Vale dizer aqui que o
parâmetro “base_score” controla essa predição inicial, então editando esse valor,
podemos mudar essa predição de 0.5.

10
PARTE II - XGBoost

Fonte: StatsQuest

A predição 0.5, corresponde a esta linha preta contínua na imagem acima. Para
cada amostra, temos um resíduo, isto é, a diferença entre o valor observado e o
predito, que nos mostra o quão boa a inicial é. Na imagem eles estão
representados pelas linhas pretas pontilhadas. Agora, assim como o gradient
boosting, o XGBoost treina uma árvore de decisão para os resíduos.

Então vamos falar sobre como construir uma árvore para regressão. Note que
existem várias maneiras de construir essas árvores. Nesta parte, falaremos da
maneira mais comum de construí-las para regressão.

Cada árvore começa com uma única folha, e todos os resíduos vão para essa
folha:

Fonte: StatsQuest

Agora, calculamos um score de qualidade ou de similaridade para os resíduos:

OBS: λ (lambda) é um parâmetro de regularização, e falaremos


sobre ele mais a frente. Por enquanto, vamos dizer que λ=0.

Então colocamos todos os resíduos no numerador, e como há 4 resíduos na folha,


colocamos 4 no denominador.

11
PARTE II - XGBoost

Então, o score de similaridade para os resíduos nesta folha é 4.

Observe que como não elevamos ao quadrado os resíduos antes da soma no


numerador, 7.5 e -7.5 serão cancelados. Em outras palavras, quando colocamos
uma amostra acima da linha de predição com uma amostra abaixo da linha de
predição juntas na mesma folha, o resultado dos seus resíduos tendem a se
cancelar.

A questão é: conseguimos uma maneira melhor de agrupar resíduos


similares se dividirmos em dois grupos?

Fonte: StatsQuest

Para responder isso, primeiro focamos nas duas observações com as dosagens
mais baixas:

Fonte: StatsQuest

Digamos que a média entre elas é 15 - representada acima pela linha vermelha.
Então, dividimos as observações em dois grupos, baseado em quando uma
amostra tem “dosagem < 15” ou não.

12
PARTE II - XGBoost

A observação mais a esquerda é a única com dosagem menor do que 15, então
seu resíduo vai na folha da esquerda e todos os outros vão para a folha da direita.
Agora calculamos os scores de similaridade para as duas folhas, seguindo o
mesmo procedimento mostrado antes, obtendo 110.25 para a folha da esquerda
e 14.08 para a folha da direita.

Fonte: StatsQuest

Observe que quando os residuais em um nó são muito diferentes, eles se


cancelam, fazendo o score de similaridade ser mais baixo. Em contraste,
quando os resíduos são similares, ou há apenas um deles no nó, não há
cancelamento e o score de similaridade se torna mais alto.

Agora, precisamos quantificar o quão melhor é termos essa divisão de folhas


comparadas a quando todas estavam na raiz. Fazemos isso calculando o ganho
em dividir os resíduos em dois grupos, que é dado por:

Nesse caso, temos um ganho de 120.33.

Agora que calculamos o ganho para o threshold “dosagem < 15”, o


comparamos com o ganho para os outros thresholds.

Então, deslocamos o threshold para que agora ele seja a média entre as próximas
duas observações e construímos uma árvore que divide as observações para o
novo threshold, que é “dosagem < 22.5”:

13
PARTE II - XGBoost

Fonte: StatsQuest

Calculamos os scores de similaridade para as folhas (8 para a esquerda e 0 para a


direita) e depois o ganho.

Nesse caso, o ganho é igual a 4. Como esse ganho para “dosagem < 22.5”
(ganho = 4) é menor que a “dosagem < 15” (ganho = 120.33), “dosagem < 15” é
melhor dividindo os resíduos em clusters com valores similares.

Então, novamente deslocamos o threshold para que seja a média das próximas
duas observações, e construímos uma árvore que divide as observações para o
novo threshold, que é “dosagem < 30”.

Fonte: StatsQuest

Calculamos os scores de similaridade para as folhas ( 4.08 para a esquerda e 56.25


para a direita) e depois o ganho.

14
PARTE II - XGBoost

Nesse caso, o ganho é igual a 56.33. Novamente, como o ganho para “dosagem
< 30” (ganho = 56.33) é menor que o da “dosagem < 15” (ganho = 120.33), “dosagem
< 15” é melhor em dividir as observações. Como não podemos deslocar mais o
threshold para a direita, já comparamos todos os thresholds diferentes possíveis
e usaremos, desta maneira, o threshold que nos dá o maior ganho, “dosagem
< 15”, para o primeiro ramo na árvore.

Fonte: StatsQuest

Como temos apenas um resíduo na folha da esquerda, não podemos dividi-la


mais. No entanto, podemos dividir os três resíduos na direita. Repetindo o
processo de escolha de thresholds descrito anteriormente, veremos que o
melhor threshold nesse caso será “dosagem < 30”, fornecendo um ganho de
140.17.

Fonte: StatsQuest

Para manter o exemplo simples, vamos limitar a profundidade da árvore em dois


níveis, o que significa que não iremos mais dividir as folhas , deixando a árvore
completa. Vale ter em mente aqui que o parâmetro padrão são as árvores que
apresentam até 6 níveis de profundidade.

Note que todos esses parâmetros comentados até aqui são customizáveis.
Normalmente, controlamos a profundidade das árvores, os parâmetros de
regularização, o número de estimadores, etc. Além disso, usamos algum critério
de otimização de hiperparâmetros como o grid search ou o random search, por
exemplo, de modo a maximizar a escolher os parâmetros que levam a um
modelo com a maior performance possível no final.

15
PARTE II - XGBoost

Precisamos falar sobre o processo de pruning, ou em português, podagem.


Como sabemos, métodos de ensemble podem facilmente levar ao problema de
overfitting, visto a complexidade dos modelos. O pruning é um processo que
visa evitar o overfitting, diminuindo o tamanho das árvores e,
consequentemente, acaba reduzindo a sua complexidade.

Nós podamos uma árvore do XGBoost nos baseando em seus ganhos. Iniciamos
tomando um valor, digamos, por exemplo, 130. Este será mais um parâmetro de
regularização, e o XGBoost chama este número de γ (gamma). Calculamos,
assim, a diferença entre o ganho associado ao ramo mais baixo na árvore e o valor
γ. Se a diferença entre o ganho e o γ for negativa, removemos o ramo. Se for
positiva, não o removemos.

Fonte: StatsQuest

A diferença entre o ganho (140.17) e gamma (130) é positiva, então não


removemos esse ramo, e nenhum dos outros acima deste. Ademais, como essa
árvore tem apenas duas divisões, iremos terminar o processo de podagem.

Fonte: StatsQuest

Note que o ganho para o primeiro ramo, 120.33, é menor que 130, o valor de
gamma, então a diferença será negativa. Mas como não removemos o primeiro
ramo, não removeremos a raíz. Caso configurarmos γ= 150, removeremos os dois
ramos e tudo o que teríamos é a predição original - o que é um caso extremo de
podagem.

16
PARTE II - XGBoost

Agora vamos voltar aos resíduos iniciais, mas desta vez, quando calcularmos os
scores de similaridade, vamos configurar λ=1. Lembre-se que o lambda é um
parâmetro de regularização, o que significa que a intenção dele é reduzir a
sensitividade das predições a observações individuais. O score de similaridade
para a raíz é então:

Ou seja, obtemos um score de 3.2, o que é 80% do que tínhamos quando λ=0.

Quando calculamos os scores de similaridade para as folhas, obtemos 55.12 para


a da esquerda (metade do que tínhamos antes) e 10.56 para a da direita (¾ do
que tínhamos antes).

Fonte: StatsQuest

Notamos então que quando λ>0, os scores de similaridade são menores, e a


quantidade de decréscimo é inversamente proporcional ao número de resíduos
no nó. Em outras palavras, a folha na esquerda tinha apenas um resíduo e obteve
o maior decréscimo no score de similaridade (50%). Em contraste, a raiz tinha
todos os quatro resíduos e teve o menor decréscimo (20%).

Quando nós calculamos o ganho, obtemos 62.48, o que é bem menor do que o
ganho de 120.33 de quando λ=0. Similarmente, o ganho do próximo ramo
“dosagem < 30” também é menor do que antes.

Para efeitos de comparação, esses são os valores dos ganhos quando λ=0.

Fonte: StatsQuest

17
PARTE II - XGBoost

Quando falamos sobre podas, configuramos primeiro γ=130, e como para o ramo
mais profundo na primeira árvore, a diferença entre o ganho e a gamma era
positiva, não podamos a árvore em nenhum momento.

Fonte: StatsQuest

Com λ=1, os valores para o ganho dos dois ramos são menores que 130, o que nos
faria podar a árvore inteira.

Então, quando λ>0, é mais fácil podar as folhas porque os valores para o ganho
são menores.

Vamos assumir que esta é a árvore com a qual estamos trabalhando.

Fonte: StatsQuest

Vamos mostrar como calcular os valores de output para as folhas. O valor de


output de uma folha é dado por:

Note que o valor é como o score de similaridade, exceto que nós não elevamos ao
quadrado a soma dos resíduos.

18
PARTE II - XGBoost

Tomando como exemplo a folha com o resíduo -10.5, se λ=0, o output será igual a
-10.5, mas se λ=1. Em outras palavras, quando obtivermos λ>0, irá reduzir a
quantidade que uma folha individual adiciona na predição total. Então, λ (o
parâmetro de regularização) vai reduzir a sensitividade da predição a observação
individual. Por agora, vamos manter as coisas simples e deixar λ=0, porque esse é
o valor padrão. Calculando os valores de output para cada uma das folhas, temos:

Fonte: StatsQuest

Repare que quando λ=0, o output de uma folha é simplesmente a média de seus
resíduos.

Depois de calcular os outputs de cada folha, finalmente a primeira árvore está


completa.

Já que construímos nossa primeira árvore, podemos fazer novas predições.


E assim como o gradient boosting, XGBoost faz as novas predições com a inicial
mais o output da árvore vezes uma learning rate (taxa de aprendizado).

Fonte: StatsQuest

19
PARTE II - XGBoost

Se você não sabe porque usamos essa learning rate, aqui vai uma
explicação rápida:

Basicamente, todos os modelos de Machine Learning, no final, são treinados


para minimizar uma função de perda, que é uma penalidade por uma má
previsão, sendo uma medida de quão bom é um modelo de previsão em termos
de ser capaz de prever o resultado esperado. Com o objetivo de minimizar essa
função de perda, normalmente usamos o chamado método do gradiente. Para
encontrar um mínimo local de uma função usa-se um esquema iterativo, onde,
em cada passo, se toma a direção a qual a função mais decresce. A learning rate
é o que determina o tamanho do passo em cada iteração enquanto se move para
um mínimo dessa perda. É como tentar encontrar o ponto mais baixo de uma
montanha à noite. Para fazer isso, a cada momento você deve dar um pequeno
passo na direção onde tem o maior declive.

Ao definir uma taxa de aprendizado, há um trade-off entre a convergência e um


“overshooting”. Uma taxa de aprendizado muito alta fará com que o aprendizado
salte sobre os mínimos, enquanto uma taxa de muito baixa levará muito tempo
para convergir ou ficará presa em um mínimo local indesejável. Abaixo temos
uma figura que ilustra o que acabou de ser explicado:

O XGBoost chama a learning rate de ε(eta) e seu valor padrão é 0.3, então é esse
que iremos utilizar.

Para a observação mais à esquerda no eixo x, com dosagem = 10, a nova predição
será igual a inicial (0.5) mais a learning rate, ε(eta) 0.3, vezes o output da folha
(-10.5). Logo, 0.5 + (0.3 * -10.5) = -2.65.

20
PARTE II - XGBoost

Fonte: StatsQuest

Podemos observar que o novo resíduo é menor do que antes, então acabamos
de dar um pequeno passo na direção certa.

Similarmente, para as outras observações, teremos as seguintes novas predições:

Fonte: StatsQuest

Assim como a primeira, as novas predições para as observações restantes têm


resíduos menores do que antes, sugerindo que cada pequeno passo foi dado na
direção certa.

Construímos uma nova árvore baseada nos novos resíduos e fizemos novas
predições que nos deram resíduos menores:

21
PARTE II - XGBoost

Fonte: StatsQuest

Em seguida, continuamos construindo árvores até que os resíduos sejam


menores que um certo limite, ou até que tenhamos atingido o número máximo
de árvores.

É assim que o XGBoost constrói as árvores para um problema de regressão.

Construção de árvores para classificação


O modo como as árvores do XGBoost são construídas para os problemas de
classificação é bem similar ao modo como são feitas para a regressão.

Existem três principais diferenças:

1 O score de similaridade de uma folha agora é dado por:

Nesse caso, i representa cada resíduo de uma folha. Aqui vale lembrar que
em problemas de classificação, cada predição é a probabilidade daquela
observação pertencer à classe positiva. Então, quando construímos a
árvore, usamos a probabilidade da predição anterior daquela amostra.

22
PARTE II - XGBoost

2 O output de uma folha agora é dado por:

Novamente, o output da folha é quase igual ao score de similaridade, com a


diferença de que os resíduos não são elevados ao quadrado depois de somados.

3 Para atualizar as predições, precisamos converter a probabilidade


anterior para um valor da log (odds), atualizar o valor da log (odds) e,
só assim, converter o valor para uma probabilidade, isto é, um valor
entre 0 e 1.

Caso o leitor não esteja familiarizado, aqui vão algumas definições:

Se um dado evento A tem a probabilidade p de ocorrer, definimos a chance


(odds) do evento ocorrer como:

Tomando a probabilidade de um ponto x ter classe positiva como p = P(y = 1),


temos então:

Dessa forma, concluímos que a função logit está intimamente relacionada com a
chance de um evento ocorrer.

Temos um número real e podemos estimá-lo usando um regressor f qualquer.


Lembrando que para classificar um ponto queremos estimar o probabilidade de
y = 1, temos:

23
PARTE II - XGBoost

σ é a inversa de logit, também chamada de função sigmóide ou logística,


definida por:

Essa função é definida para todos os números reais, e sua imagem, isto é, os
valores que ela pode assumir, ficam entre 0 e 1.

Para atualizar a probabilidade de uma amostra conforme construímos as árvores,


fazemos o seguinte processo:

I) Calculamos a log (odds) anterior ou logit (p) da probabilidade anterior;

II) Atualizamos a log (odds) por meio da fórmula:

III) Calculamos a nova probabilidade aplicando a função logística em log


(odds):

Cabe ressaltar que existe uma justificativa matemática por trás de cada cálculo
de ganho e de score de similaridade.

24
PARTE III - XGBoost vs LightGBM vs CatBoost

Introdução
Abaixo temos uma linha cronológica de quando cada algoritmo foi lançado:

https://towardsdatascience.com/catboost-vs-light-gbm-vs-xgboost-5f93620723db

O XGBoost é o mais antigo deles, sendo, talvez por isso, o mais conhecido entre
eles. Começou como um projeto de pesquisa de Tianqi Chen e do brasileiro
Carlos Guestrin, que publicaram juntos um artigo descrevendo o algoritmo.
Caso queira conferir o artigo original, basta clicar aqui. Apesar disso, seu uso só
ficou popular em 2016, quando começou a ser muito usado nas competições de
Machine Learning, superando a performance de quase todos os outros
algoritmos facilmente.

Em 2017, as primeiras versões estáveis e abertas ao público do LightGBM e do


CatBoost foram lançadas. Apesar de similares com o XGBoost, cada um deles
veio com uma proposta bem clara sobre qual o aspecto seria superado pelo
XGBoost - falaremos sobre isso mais a frente.

Dada a disponibilidade de artigos internet afora sobre o assunto, hoje o foco será
no LightGBM e no CatBoost. Falaremos sobre: as diferenças estruturais destes
em relação ao XGBoost, o propósito de cada algoritmo, como eles lidam com
variáveis categóricas, a semelhança nos hiperparâmetros e mostraremos
algumas comparações de performance.

25
PARTE III - XGBoost vs LightGBM vs CatBoost

LightGBM
O principal objetivo do LightGBM é acelerar o treinamento, mantendo a
mesma performance do XGBoost. Para isso, ele tem três grandes
otimizações durante o processo de construção das árvores.

Em primeiro lugar, as variáveis contínuas são discretizadas em bins na fase de


encontrar o melhor threshold para dividir as amostras. Na parte anterior, vimos
que o XGBoost, em cada momento que dividia as amostras na construção da
árvore, ordenava as amostras para cada feature e escolhia a divisão que
maximizava o ganho. O LightGBM também faz o mesmo processo. Porém,
discretizando as variáveis contínuas, temos um número bem menor de
thresholds para testar, o que acelera a etapa de treinamento.

Além disso, o LightGBM usa uma técnica de amostragem chamada de


GOSS (Gradient-based One-Side Sampling), que consiste no seguinte: o
gradiente representa a inclinação da tangente da função de perda; portanto, se o
gradiente de uma determinada amostra é grande em algum sentido, essa
amostra apresenta maior erro, tornando esses pontos importantes para
encontrar o ponto de divisão ideal. Aqui podemos fazer uma analogia com o
AdaBoost, que a cada iteração, estabelece um peso para as amostras
proporcional ao erro em sua estimação, indicando quais amostras o modelo está
errando mais na predição. A ideia é a mesma: as amostras com maior valor do
gradiente são amostras com um erro maior.

Após o cálculo dos gradientes, a etapa da amostragem se apresenta. O GOSS


mantém todas as instâncias com gradientes altos e realiza uma amostragem
aleatória nas instâncias com pequenos gradientes. Por exemplo, digamos que eu
tenha um conjunto de dados com 500 mil linhas, sendo que em 10 mil, temos
erros mais altos. Portanto, o algoritmo escolherá 10 mil linhas de gradiente mais
alto + x% das 490 mil linhas restantes escolhidas aleatoriamente. Supondo que x
seja 10, o total de linhas selecionadas terá 59k (10k+49k) de 500K com base no
valor da divisão, se encontrado. Dessa maneira, na próxima iteração, teremos um
número bem menor de amostras para serem consideradas, o que também
acelera o treinamento.

A suposição básica tomada aqui é que as amostras com gradientes pequenos


apresentam um erro de treinamento menor e já estão bem treinadas. Para
manter a mesma distribuição de dados, ao calcular o ganho de informações, o
GOSS introduz um multiplicador constante para as instâncias de dados com
pequenos gradientes. Assim, o GOSS alcança um bom equilíbrio entre reduzir o
número de instâncias de dados e manter a precisão das árvores de decisão.

26
PARTE III - XGBoost vs LightGBM vs CatBoost

Por último, temos uma diferença no modo como as árvores de decisão crescem.
O XGBoost usa uma abordagem chamada de “level-wise tree growth”,
enquanto o LightGBM usa a abordagem denominada “leaf-wise tree growth”.
Abaixo temos duas imagens ilustrando como cada árvore fica mais profunda:

https://datascience.stackexchange.com/questions/26699/decision-trees-leaf-wise-best-first-and-level-wise-tree-traverse

Repare que na abordagem leaf-wise e em cada nível, apenas um dos lados da


árvore fica mais profundo. Isto significa que a cada nível, temos uma quantidade
menor de resíduos a se considerar de modo a encontrar o threshold que
maximize o ganho. Logo, temos outra aceleração no processo de treinamento
aqui.

CatBoost
O CatBoost, por sua vez, tem dois grandes objetivos: evitar o overfitting e
fornecer bons hiperparâmetros. Seu nome é uma abreviação de Categorical
Boosting, devido a sua maneira especial de lidar com variáveis categóricas.

27
PARTE III - XGBoost vs LightGBM vs CatBoost

A primeira diferença estrutural que podemos citar do CatBoost é o uso de uma


estrutura de dados chamada Oblivious Tree, onde cada nível da árvore tem o
mesmo split para todos os ramos. Para exemplificar:

https://medium.com/@hanishsidhu/whats-so-special-about-catboost-335d64d754ae

Esse tipo de estrutura leva a um tempo de predição muito baixo, visto que o
número de splits distintos cresce linearmente com a profundidade da árvore e
não exponencialmente como o XGBoost.

Para explicar como o CatBoost tenta evitar o overfitting, vamos comparar o


procedimento adotado por ele com os outros algoritmos de boosting.

De um modo geral, para o XGBoost e para o LightGBM, temos os seguintes


passos:

I) Considere todos (ou uma amostra ) dos dados para treinar um modelo com
alto bias;

II) Calcule os resíduos para cada ponto;

III) Treine outro modelo com os mesmos pontos e seus correspondentes


resíduos como variável resposta;

IV) Repita o passo 2 e 3 (por n iterações).

Esse procedimento é muito propenso ao overfitting, porque estamos calculando


os resíduos de cada ponto usando um modelo que já foi treinado no mesmo
conjunto de pontos.

28
PARTE III - XGBoost vs LightGBM vs CatBoost

Tendo em vista esse problema, o CatBoost faz o boosting de uma maneira muito
elegante. Vamos explicá-la usando um exemplo simples.

Digamos que temos 10 pontos em nosso conjunto e estão ordenados no tempo


como mostrado abaixo:

Se os dados não tem uma ordenação, a cada iteração o algoritmo seleciona uma
ordenação aleatória, como se criasse um tempo artificial para cada ponto.

Após isso, o CatBoost adota o seguinte procedimento:

I) Calcular os resíduos de cada ponto usando um modelo que foi treinado em


todos os outros pontos anteriores a ele. Por exemplo, para calcular o resíduo
do ponto x5, treinamos um modelo usando os pontos x1, x2, x3 e x4.
Portanto treinamos diferentes modelos para pontos diferentes. No final,
estamos calculando resíduos para pontos onde o modelo correspondente
nunca foi treinado;

II) Treinar o modelo usando os resíduos de cada ponto como variável resposta;

III) Repetir os passos 1 e 2 (por “n” iterações).

Para o conjunto de dados acima, devemos treinar 9 modelos diferentes para


obter resíduos( para 9 pontos). Isso pode ser computacionalmente caro. Portanto,
por padrão, em vez de treinar modelos diferentes para cada um dos pontos, isto
é, “n” modelos para n pontos, são treinados log (n) modelos, de modo que se um
modelo foi treinado em n pontos, esse modelo é usado para calcular resíduos
para os próximos n pontos.

29
PARTE III - XGBoost vs LightGBM vs CatBoost

Ou seja, um modelo que foi treinado no primeiro ponto é usado para calcular o
resíduo do segundo ponto. Outro modelo que foi treinado nos dois primeiros
pontos é usado para calcular resíduos do terceiro e quarto pontos, e assim por
diante.

Todo esse procedimento explicado até agora é conhecido como ordered


boosting (boosting ordenado).

A última característica que iremos mostrar do CatBoost é a forma com o qual ele
lida com features categóricas.

Por padrão, o CatBoost utiliza a abordagem One-hot Encoding somente se uma


feature categórica tiver apenas duas categorias diferentes. Se você deseja
implementar o One-hot enconding em uma feature categórica que possui “N”
categorias diferentes, é possível configurar o parâmetro “one_hot_max_size”
como igual a “N”.

O CatBoost possui uma representação muito boa de dados categóricos. Ele


utiliza conceitos do ordered boosting e aplica o mesmo a uma técnica chamada
response coding (ou target encoding). No response coding, representamos
cada feature categórica usando a média da coluna target de todos os pontos
com aquele mesmo valor para a variável categórica. No entanto, podemos acabar
representando o valor de uma variável usando seu rótulo. Isso leva a um
problema denominado target leakage, isto é, usamos informação da variável
que queremos prever para a construção das features. Já o CatBoost, para
codificar uma instância de uma variável categórica, considera apenas os pontos
anteriores a ela e calcula a média do target desses pontos com o mesmo valor
dessa variável categórica.

Abaixo temos um exemplo de como isso funciona na prática:

Digamos que temos o seguinte dataset (todos os pontos já ordenados no


tempo).

30
PARTE III - XGBoost vs LightGBM vs CatBoost

Nós temos a Feature 1, uma feature categórica com 3 diferentes categorias. Com
o response coding, nós representaremos nublado = (15 +14 +20+25) / 4 = 18.5. Isso
realmente leva ao data leakage, porque estamos construindo uma feature de
um ponto usando o target do mesmo ponto.

O CatBoost transforma todas as features categóricas sem qualquer data


leakage. Ao invés de considerar todos os pontos, ele considera apenas os
anteriores a um determinado ponto. Assim, transforma as categorias em
números usando a seguinte fórmula:

Aqui temos:

avg_target é o valor numérico da instância após a transformação;

countInClass é a soma do valor do target para instâncias com o valor atual da


feature categórica;

Prior é um valor preliminar para a feature;

TotalCount é a quantidade de vezes que uma instância apareceu com o atual


valor da feature categórica.

No caso do nosso dataset, se deixarmos prior = 0.05, temos como exemplo:

Na sexta-feira, nublado = (15 + 14 + 0.05) / 3 = 9.68;

No sábado, nublado = (15 + 14 + 20 + 0.05) / 3 = 12.26;

Na terça-feira, nublado = 0.05 / 2 = 0.025.

31
PARTE III - XGBoost vs LightGBM vs CatBoost

Hiperparâmetros
Todos esses três algoritmos têm muitos parâmetros para ajustar, mas
abordaremos apenas os importantes. Abaixo, temos uma tabela com esses
parâmetros de acordo com sua função e suas contrapartes nos diferentes
modelos. Cabe ressaltar que os parâmetros mais importantes são bem similares
nos três, com leves alterações no nome, por exemplo, mas com a mesma
funcionalidade.

https://towardsdatascience.com/catboost-vs-light-gbm-vs-xgboost-5f93620723db

Benchmarks
Em seguida, mostraremos os resultados de alguns testes feitos para comparar a
performance e o tempo de cada um dos algoritmos. Aqui vale ressaltar que os
dois últimos exemplos foram executados em bases de dados que utilizamos na
prática aqui na Datarisk.

Os testes foram executados em uma instância r5.8xlarge do Amazon EC2, com


256GB de RAM. A técnica utilizada para a otimização de hiperparâmetros em
todos os casos foi um Random Search com 50 iterações cada.

32
PARTE III - XGBoost vs LightGBM vs CatBoost

Exemplo 1

Temos um problema de regressão, onde a métrica de comparação é o R2.


Basicamente, este coeficiente indica quanto o modelo foi capaz de explicar os
dados coletados. O melhor score possível é 1.0 e ele pode ser negativo (porque o
modelo pode ser arbitrariamente ruim). Um modelo constante que sempre
prediz a média de y, não importando as features de input, terá um score R2 de
0.0.

A base continha 20.640 linhas e 8 features ao todo, sendo usada a divisão


treino/teste com 20% indo para o conjunto de testes.

Eis os resultados:

Exemplo 2

Temos um problema de classificação, onde a métrica de comparação é o AUC.

A base continha 83.602 linhas e 80 features ao todo, sendo usada a divisão


treino/teste com 20% indo para o conjunto de testes.

Apresentamos as variáveis categóricas na base e, com o intuito de comparar a


heurística de tratamento de categóricas do CatBoost, fizemos dois testes:
um passando os índices das features categóricas e outro tratando-as
previamente com o Rank Count Vectorizer. Para o XGBoost e o LightGBM,
também utilizamos o Rank Count Vectorizer.

33
PARTE III - XGBoost vs LightGBM vs CatBoost

Eis os resultados:

Exemplo 3

Temos outro problema de classificação, onde novamente usamos o AUC como


métrica de performance.

A base continha 83.623 linhas e 42 features ao todo, sendo usada a divisão


treino/teste com 20% indo para o conjunto de testes.

Assim como no último exemplo, faremos a mesma comparação da abordagem


do CatBoost em relação às categóricas, comparando-o com o Rank Count
Vectorizer.

Eis aqui os resultados:

34
PARTE III - XGBoost vs LightGBM vs CatBoost

Comparando os resultados dos três testes, podemos fazer algumas observações.

1) O LightGBM e o CatBoost normalmente têm sempre cerca de 4 ou 5 pontos


de score a mais com os hiperparâmetros padrão comparado ao XGBoost;

2) O tempo de treinamento do LightGBM é significativamente menor do que os


outros dois (especialmente na otimização de hiperparâmetros);

3) O XGBoost apresentou melhor performance após a otimização de


hiperparâmetros (o que pode também ser causado pela grade de parâmetros
testados para os três frameworks);

4) A heurística de tratamento de variáveis categóricas do CatBoost não mostrou


diferença significativa no desempenho final.

Por fim, devo dizer que essas observações são verdadeiras para esses conjuntos
de dados específicos, e podem ou não permanecer válidas para outros
conjuntos. No entanto, uma coisa é verdade: em geral, o XGBoost é mais lento
que os outros dois algoritmos e o LightGBM é o mais rápido entre eles.

Deixamos aqui algumas dicas de como usufruir da melhor forma dos três
modelos:

I) Sem otimização de hiperparâmetros, o CatBoost normalmente é uma boa


escolha, pois um dos objetivos de seu desenvolvimento é justamente esse
(pelos nossos testes, o LightGBM também apresentou boa performance com os
parâmetros padrão, então pelo seu tempo de treinamento baixo, pode ser uma
boa escolha para essa situação também);

II) Para fazer feature selection, feature engineering e otimização de


hiperparâmetros, use o LightGBM;

III) Ao final de tudo, use o pré-processamento e os hiperparâmetros que


levaram a melhor performance e teste os três. Normalmente a performance é
muito parecida, e qualquer leve ganho de score será bem-vindo;

35
PARTE III - XGBoost vs LightGBM vs CatBoost

Nos exemplos anteriores, fizemos testes executando o Random Search no


LightGBM e depois usando os melhores hiperparâmetros obtidos, treinamos um
XGBoost. No exemplo 1, obtivemos um R2 de 0,85038 (acima do que tínhamos
para o LightGBM, mas abaixo do score obtido pelo XGBoost otimizado). No
exemplo 2, obtivemos um AUC de 0,77612 (resultado pior do que qualquer um
dos modelos otimizados). Por fim, no exemplo 3, obtivemos um AUC de 0,81891
(novamente acima do que tínhamos para o LightGBM, mas abaixo do score
obtido pelo XGBoost otimizado). Isso é um bom indicativo de que após a
otimização de hiperparâmetros em um modelo, ainda é válido testar os
resultados nos outros, selecionando aquele com melhor performance.

Saímos de uma explicação introdutória sobre métodos de ensemble learning,


passando por todo o processo de construção de árvores no XGBoost (e nos outros
modelos de boosting baseado em árvores no geral) e chegamos na comparação
entre os três principais algoritmos de boosting no momento.

Quer conhecer um pouco mais sobre a Datarisk?


Clique aqui e encontre oportunidades por meio das nossas soluções!

36

Você também pode gostar