Capítulo 4 Floresta Aleatória

Random Forest, ou Floresta Aleatória, método desenvolvido por (Breiman 2001), utiliza um conjunto de Árvores de Decisão para realizar tarefas de classificação ou regressão. Os métodos, como a Floresta Aleatória, que dá-se pela combinação de outros métodos são denominados como ensemble. O conceito fundamental das Florestas Aleatórias é a sabedoria das multidões: um número grande de modelos não correlacionados, no caso as árvores, operando em conjunto irão performar melhor do que cada modelo individual.

Antes de apresentar o método veja um experimento feito com 50 pessoas, para ilustrar a ideia da sabedoria das multidões. Cada pessoa viu uma foto de uma garrafa de 300ml, transparente, com grãos de feijão nela. Mais ou menos até a metade da garrafa. Em seguida cada participante deu um palpite sobre o número grãos de feijão na garrafa.

A quantidade exata de grãos de feijão na garrafa era 524, valor marcado com a linha em preto no gráfico apresentado na 4.1. As linhas pontilhadas em preto representam um intervalo de raio 100, ou seja, estão nos números 424 e 624. Cada palpite de um participante é um ponto vermelho. Veja que a maioria dos palpites estão fora do intervalo pontilhado, que mostra que a maioria dos participantes não deram um bom palpite. O normal é errar mesmo. Mas quando calculamos o valor médio dos palpites, linha pontilhada em vermelho, temos um palpite muito melhor do que os palpites individuais.

Resultado do Experimento sobre a Sabedoria das Multidões

Figura 4.1: Resultado do Experimento sobre a Sabedoria das Multidões

A ideia da Floresta Aleatória é essa: em vez de construir uma única árvore para realizar previsões serão construídas muitas árvores, diferentes entre si. A previsão final será a média da previsão de todas as árvores.

Floresta Aleatória

Figura 4.2: Floresta Aleatória

Seguem algumas vantagens da Floresta Aleatória em relação à uma única árovre de decisão:

  • Alta precisão: A Random Forest geralmente produz resultados mais precisos em comparação com um único modelo de árvore de decisão, especialmente quando o conjunto de dados é grande e complexo.

  • Resistência ao overfitting: Ao combinar previsões de várias árvores, a Foresta Aleatória reduz o risco de overfitting, ou seja, de criar um modelo excessivamente ajustado aos dados de treinamento e com baixa capacidade de generalização para novos dados.

  • Melhor desempenho com bases contendo outliers: uma vez que cada árvore da floresta é gerada por uma amostra bootstrap das observações (linhas), a observações com outliers nem sempre serão selecionadas, e com isso estes valores atípicos não geram uma grande influência no resultado final.

  • Melhor absorção da informação contida em cada covariável: como as partições das árvores da floresta consideram um seleção das covariáveis (colunas), algumas partições não levam em consideração a covariável mais importante e com isso outras variáveis conseguem exercer influência no resultado final.

4.1 Bagging

A Floresta Aleatória é um modelo com bagging. Um modelo com bagging é uma abordagem de aprendizado de máquina ensemble que combina múltiplos modelos individuais em um único modelo mais robusto e preciso. O termo “bagging” é uma abreviação de “bootstrap aggregating”, que se refere às duas principais etapas do processo.

O processo começa gerando várias amostras de treinamento com reposição a partir do conjunto de dados original. Isso significa que cada amostra é obtida aleatoriamente, permitindo que uma mesma amostra apareça múltiplas vezes e outras possam não ser selecionadas. O objetivo é criar várias versões do conjunto de treinamento, cada uma com pequenas variações nos dados de entrada.

Ilustração do Bagging

Figura 4.3: Ilustração do Bagging

Em seguida, um modelo individual é treinado em cada uma das amostras de treinamento geradas no passo anterior. No caso da Floresta Aleatória, este modelo individual é a Árvore de Decisão.

Ao fazer uma previsão usando o modelo com bagging, as previsões de cada modelo individual são combinadas para obter uma única previsão final. O bagging ajuda a reduzir o overfitting, pois as variações introduzidas nas amostras de treinamento aumentam a diversidade dos modelos individuais.

Segundo (James et al. 2013), o bagging é particularmente útil para árvores de decisão. Para aplicar o bagging no Modelo de Árvores de Decisão simplesmente contrói-se B árvores de decisão usando os B conjuntos de treinamento gerados pelo bootstrap. Essas árvores são cultivadas profundamente, ou seja, deixamos elas crescere o quanto quiserem. Portanto, cada árvore individual tem alta variância, mas baixo viés.

4.2 Partições

Neste momento já ficou claro porque a Floresta se chama Aleatória. Mas o bagging não é a única parte aleatória da floresta. Na costrução de uma árvore da Floresta Aleatória, cada vez que uma divisão em um nó da árvore será realizado, um sorteio de m covariáveis, entre todas as p covariáveis da base, é realizado. As covariáveis selecionadas serão as únicas candidatas à realizar a partição no nó.Uma nova amostra de m covariáveis é selecionada em cada divisão da árvore e, tipicamente, escolhe-se mp.

A decisão de não usar todas as covariáveis como candidatas para uma partição em um nó reduz a correlação entre as árvores da floresta. Como a saída de uma Floresta aleatória é feita, em geral, pela média das saídas de cada árvore, a redução da correlação entre as árvores reduz a variância da saída do método, tornando mais confiável.

Uma outra vantagem neste processo é que ao considerar apenas um subconjunto das covariáveis, em muitos nós a partição é realizada sem que a covariáveis mais importante seja uma candidata. Isto permite que outras covariáveis tenham mais chances de serem escolhidas.

4.3 Regressão x Classificação

Até o momento só foi falado sobre árvores de decisão, de forma geral, sem diferenciar o caso de regressão do de classificação. A única diferença entre os dois casos é que para regressão a Floresta Aleatória é uma floresta de árvores de regressão, enquanto que para classificação, é uma floresta de árvores de classificação.

A previsão também é semelhante, a resposta que a Floresta Aleatória retorna é a média simples das respostas de todas as árvores. Ou seja, a nova observação, para a qual queremos fazer uma previsão, é colocada como dado de entrada em todas as árvores da floresta e cada árvore retorna um valor de previsão. A previsão da floresta aleatória será a média das previsões das árvores.

4.4 Algoritmo

Considere uma base de dados supervisionada, onde Y é a variável resposta (qualitativa ou quantitativa) e Xj, j=1,2,,p são as p covariáveis. Para cada observação i, i=1,2,,n, isto é, para cada linha i da base, temos Yi o valor da variável resposta para a observação i e Xi,j o valor ca covariável j para a observação i. Posto isso, segue o algorítimo para o Método de Floresta Aleatória.

Escolhe-se o valor do hiperparâmtro B, que é o número de árvores na floresta.

  1. Faça b=1 .

  2. Selecione uma amostra de tamanho n do banco de treino a partir do método bootstrap, com reposição (bagging).

  3. A amostra selecionada será a base de dados de entrada de uma nova árvore, vamos chamá-la de X.

  4. Faça um sorteio aleatório simples, sem reposição, de p covariáveis entre as p covariáveis de X. Vamos chamar de J o conjunto dos índices das covariáveis sorteadas.

  5. Defina a covariável jJ e o valor sR tais que minimizam a soma dos índices Gini, para o caso de um problema de classificação, ou o RSS, para o caso de um problema de regressão, nas regiões R1={X|Xj<s} e R2={X|Xjs}.

  6. Verifique se em R1 um dos critérios de parada foi atingido. Se sim, este nó é uma folha e vá para o passo 8. Se não, faça X=R1 e volte para o passo 4.

  7. Verifique se em R2 um dos critérios de parada foi atingido. Se sim, este nó é uma folha e vá para o passo 8. Se não, faça X=R2 e volte para o passo 4.

  8. Faça b=b+1. Se bB, volte para o passo 2. Caso contrário, FIM.

4.5 Como realizar previsões

Uma vez a floresta construída, ela pode ser usada para prever a variável resposta de novas observações. Para isso a nova observação passa a ser dado de entrada para todas as árvores da floresta. Cada uma das B árvores fornece uma previsão para a nova observação, vamos chamar de ˆyb a previsão feita pela árvore b para a entrada y. A previsão da floresta será:

ˆy=Bb=1ˆybB

4.6 Vamos praticar

Vamos repetir a prática dos dois últimos capítulos, mas agora com a Floresta Aleatória.

# Carregar pacotes e base de treino
library(tidyverse)
library(rpart)
base_treino = readRDS(file="arquivos-de-trabalho/base_treino_final.rds")

Para criar modelos de Floresta Aleatória será usado o pacote randomForest (Liaw and Wiener 2002).

#install.packages("randomForest")
library(randomForest)

Como o processo de criação das árvores trabalha com sorteios, é importante fixar a semente para garantir a reprodutibilidade do código.

set.seed(123456789)

Regressão

Vejamos os resultados das regressões já feitas para a árvore de regressão agora com o método da Floresta Aleatória.

Nota de Redação

Primeiro será ajustado um modelo para prever a nota em redação das escolas. A função a ser usada é a randomForest, do pacote de mesmo nome. No primeiro argumento desta função, x, deve ser colocadas as covariáveis. No argumento y é informado a variável alvo.

Ajuste do Modelo

Não é preciso informar se o modelo é de classificação ou regressão. A função identifica o tipo da variável y e automaticamente escolhe regressão se ela for numérica ou classificação se ela for fator.

rf_RD <- randomForest(x =  base_treino |>
                        select(-c(NU_TAXA_PARTICIPACAO, 
                                  NU_MEDIA_CN, 
                                  NU_MEDIA_CH, 
                                  NU_MEDIA_LP, 
                                  NU_MEDIA_MT, 
                                  NU_MEDIA_RED, 
                                  CO_ESCOLA_EDUCACENSO,
                                  NO_ESCOLA_EDUCACENSO,
                                  NU_PARTICIPANTES)), 
                      y = base_treino$NU_MEDIA_RED, ntree=500)
saveRDS(rf_RD,file = "arquivos-de-trabalho/rf_RD.rds")

As variáveis importantes para esse modelo são guardadas no próprio objeto gerado pela função randomForest.

Variáveis Importantes
importancia = rf_RD$importance
sort(importancia[,1],decreasing = TRUE)
## TP_DEPENDENCIA_ADM_ESCOLA                      INSE          NU_TAXA_ABANDONO 
##                18768178.1                13259812.2                 7931482.5 
##              SG_UF_ESCOLA       PC_FORMACAO_DOCENTE        NU_TAXA_REPROVACAO 
##                 7729902.0                 4909349.5                 4040871.1 
##             NU_MATRICULAS       NU_TAXA_PERMANENCIA              PORTE_ESCOLA 
##                 3936378.0                 3771669.2                 1083390.0 
##  NU_PARTICIPANTES_NEC_ESP     TP_LOCALIZACAO_ESCOLA 
##                  815759.7                  350065.4
Previsão para novas observações

Aqui na nova observação as variáveis categóricas são informadas como fator e, o que é importante, é preciso que os fatores tenham os mesmos levels. Por isso o código da base de dados para previsão será montada diferente da do último capítulo.

SG_UF_ESCOLA = 
  factor(x = c("RJ","SP","MG","AM","RS"),
         levels = levels(base_treino$SG_UF_ESCOLA))

TP_DEPENDENCIA_ADM_ESCOLA = 
  factor( x = c("Estadual","Privada","Estadual","Municipal","Federal"),
          levels = levels(base_treino$TP_DEPENDENCIA_ADM_ESCOLA))

TP_LOCALIZACAO_ESCOLA = 
  factor(x = c("Urbana","Urbana","Urbana","Rural","Urbana"),
         levels = levels(base_treino$TP_LOCALIZACAO_ESCOLA))


INSE = factor(x = c("Grupo 3","Grupo 6","Grupo 4","Grupo 2","Grupo 4"),
              levels = levels(base_treino$INSE))

PORTE_ESCOLA = factor(x = c("De 61 a 90 alunos","Maior que 90 alunos","De 61 a 90 alunos","De 31 a 60 alunos","Maior que 90 alunos"),
                      levels = levels(base_treino$PORTE_ESCOLA))

NU_MATRICULAS = c(87,44,102,21,80)

NU_PARTICIPANTES_NEC_ESP = c(1,2,0,0,1)

PC_FORMACAO_DOCENTE = c(48.1 , 75.7 , 68.8 , 51.2 , 70.3)

NU_TAXA_PERMANENCIA = c(67,100,92,87,75)

NU_TAXA_REPROVACAO = c(6.1,3.3, 9.1, 8.7,5.6)

NU_TAXA_ABANDONO = c(0,0,1, 2, 3)

escola = tibble(SG_UF_ESCOLA ,  
                TP_DEPENDENCIA_ADM_ESCOLA, 
                TP_LOCALIZACAO_ESCOLA , 
                NU_MATRICULAS , 
                NU_PARTICIPANTES_NEC_ESP ,
                INSE ,
                PC_FORMACAO_DOCENTE , 
                NU_TAXA_PERMANENCIA , 
                NU_TAXA_REPROVACAO ,  
                NU_TAXA_ABANDONO ,  
                PORTE_ESCOLA)
predict(rf_RD, newdata = escola)
##        1        2        3        4        5 
## 496.5097 674.8462 552.3417 516.4380 592.1234

4.6.0.1 Nota de Matemática

Os mesmos passos serão repetidos para a nota de matemática.

Ajuste do Modelo
rf_MT <- randomForest(
  x =  base_treino |> 
    select(-c(NU_TAXA_PARTICIPACAO,
              NU_MEDIA_CN,
              NU_MEDIA_CH,
              NU_MEDIA_LP, 
              NU_MEDIA_MT,
              NU_MEDIA_RED,
              CO_ESCOLA_EDUCACENSO,
              NO_ESCOLA_EDUCACENSO,
              NU_PARTICIPANTES)),
  y = base_treino$NU_MEDIA_MT, 
  ntree=500)
saveRDS(rf_MT,file = "arquivos-de-trabalho/rf_MT.rds")
Variáveis Importantes
importancia = rf_MT$importance
sort(importancia[,1],decreasing = TRUE)
##                      INSE TP_DEPENDENCIA_ADM_ESCOLA              SG_UF_ESCOLA 
##                17100690.9                11849612.6                 5640099.9 
##          NU_TAXA_ABANDONO       PC_FORMACAO_DOCENTE       NU_TAXA_PERMANENCIA 
##                 5222819.8                 3203708.3                 2840186.6 
##             NU_MATRICULAS        NU_TAXA_REPROVACAO              PORTE_ESCOLA 
##                 2693996.3                 2586864.2                  779179.8 
##  NU_PARTICIPANTES_NEC_ESP     TP_LOCALIZACAO_ESCOLA 
##                  428176.8                  128173.5
Previsão para novas observações
predict(rf_MT, newdata = escola)
##        1        2        3        4        5 
## 457.7980 640.1608 488.2122 439.1422 529.1003

Classificação Binária

A principal difereça será que neste caso teremos que criar a variável alvo, que não está na base.

4.6.0.2 Nota de Redação

base_treino_RED = base_treino |> 
  mutate(NOTA_RED = ifelse(base_treino$NU_MEDIA_RED>=600,"boa","regular")) |>
  select(-c(NU_TAXA_PARTICIPACAO,
            NU_MEDIA_CN,
            NU_MEDIA_CH,
            NU_MEDIA_LP, 
            NU_MEDIA_MT,
            NU_MEDIA_RED,
            CO_ESCOLA_EDUCACENSO,
            NO_ESCOLA_EDUCACENSO,
            NU_PARTICIPANTES
  ))
base_treino_RED$NOTA_RED = as.factor(base_treino_RED$NOTA_RED)
Ajuste do Modelo
rf_RED <- randomForest(x =  base_treino_RED |> select(-NOTA_RED),
                       y = base_treino_RED$NOTA_RED , 
                       ntree=500)
saveRDS(rf_RED,file = "arquivos-de-trabalho/rf_RED.rds")
Variáveis Importantes
importancia = rf_RED$importance
sort(importancia[,1],decreasing = TRUE)
## TP_DEPENDENCIA_ADM_ESCOLA                      INSE              SG_UF_ESCOLA 
##                1055.14719                 755.09395                 497.67042 
##       PC_FORMACAO_DOCENTE          NU_TAXA_ABANDONO       NU_TAXA_PERMANENCIA 
##                 446.43378                 445.93058                 394.84455 
##        NU_TAXA_REPROVACAO             NU_MATRICULAS              PORTE_ESCOLA 
##                 391.63084                 380.26797                  85.36660 
##  NU_PARTICIPANTES_NEC_ESP     TP_LOCALIZACAO_ESCOLA 
##                  68.38661                  15.03753
Previsão para novas observações
predict(rf_RED, newdata = escola, type="prob")
##     boa regular
## 1 0.024   0.976
## 2 0.756   0.244
## 3 0.074   0.926
## 4 0.072   0.928
## 5 0.354   0.646
## attr(,"class")
## [1] "matrix" "array"  "votes"

Nota de Matemática

base_treino_MAT = base_treino |> 
  mutate(NOTA_MAT = ifelse(base_treino$NU_MEDIA_MT>=600,"boa","regular")) |>
  select(-c(NU_TAXA_PARTICIPACAO,
            NU_MEDIA_CN,
            NU_MEDIA_CH,
            NU_MEDIA_LP, 
            NU_MEDIA_MT,
            NU_MEDIA_RED,
            CO_ESCOLA_EDUCACENSO,
            NO_ESCOLA_EDUCACENSO,
            NU_PARTICIPANTES
  ))
base_treino_MAT$NOTA_MAT = as.factor(base_treino_MAT$NOTA_MAT)
Ajuste do Modelo
rf_MAT <- randomForest(x = base_treino_MAT |> select(-NOTA_MAT),
                       y = base_treino_MAT$NOTA_MAT , 
                       ntree=500)
saveRDS(rf_MAT,file = "arquivos-de-trabalho/rf_RED.rds")
Variáveis Importantes
importancia = rf_MAT$importance
sort(importancia[,1],decreasing = TRUE)
## TP_DEPENDENCIA_ADM_ESCOLA                      INSE              SG_UF_ESCOLA 
##                1055.14719                 755.09395                 497.67042 
##       PC_FORMACAO_DOCENTE          NU_TAXA_ABANDONO       NU_TAXA_PERMANENCIA 
##                 446.43378                 445.93058                 394.84455 
##        NU_TAXA_REPROVACAO             NU_MATRICULAS              PORTE_ESCOLA 
##                 391.63084                 380.26797                  85.36660 
##  NU_PARTICIPANTES_NEC_ESP     TP_LOCALIZACAO_ESCOLA 
##                  68.38661                  15.03753
Previsão para novas observações
predict(rf_MAT, newdata = escola, type="prob")
##     boa regular
## 1 0.024   0.976
## 2 0.756   0.244
## 3 0.074   0.926
## 4 0.072   0.928
## 5 0.354   0.646
## attr(,"class")
## [1] "matrix" "array"  "votes"

Classificação Multiclasses

4.6.0.3 Nota da redação

base_treino_RED_3 = base_treino |>
  mutate(NOTA_RED = 
           ifelse(
             base_treino$NU_MEDIA_RED>600,"boa",
             ifelse(base_treino$NU_MEDIA_RED<500,"ruim",
                    "regular"))) |>
  select(-c(NU_TAXA_PARTICIPACAO,
            NU_MEDIA_CN,
            NU_MEDIA_CH,
            NU_MEDIA_LP, 
            NU_MEDIA_MT,
            NU_MEDIA_RED,
            CO_ESCOLA_EDUCACENSO,
            NO_ESCOLA_EDUCACENSO,
            NU_PARTICIPANTES
  ))
base_treino_RED_3$NOTA_RED = as.factor(base_treino_RED_3$NOTA_RED)
summary(base_treino_RED_3$NOTA_RED)
##     boa regular    ruim 
##    3278    6126    2296
Ajuste do Modelo
rf_RED_3 <- randomForest(x =  base_treino_RED_3 |> select(-NOTA_RED),
                         y = base_treino_RED_3$NOTA_RED , 
                         ntree=500)
saveRDS(rf_RED_3,file = "arquivos-de-trabalho/rf_RED_3.rds")
Variáveis Importantes
importancia = rf_RED_3$importance
sort(importancia[,1],decreasing = TRUE)
##              SG_UF_ESCOLA       PC_FORMACAO_DOCENTE                      INSE 
##                 899.02614                 867.82477                 856.75535 
## TP_DEPENDENCIA_ADM_ESCOLA       NU_TAXA_PERMANENCIA        NU_TAXA_REPROVACAO 
##                 822.59051                 770.76462                 756.52912 
##             NU_MATRICULAS          NU_TAXA_ABANDONO  NU_PARTICIPANTES_NEC_ESP 
##                 745.30381                 728.47047                 168.25453 
##              PORTE_ESCOLA     TP_LOCALIZACAO_ESCOLA 
##                 166.06530                  41.00323
Previsão para novas observações
predict(rf_RED_3, newdata = escola, type = "prob")
##     boa regular  ruim
## 1 0.030   0.246 0.724
## 2 0.766   0.234 0.000
## 3 0.080   0.788 0.132
## 4 0.046   0.474 0.480
## 5 0.440   0.550 0.010
## attr(,"class")
## [1] "matrix" "array"  "votes"

4.7 Atividade

Trabalhar novamente com a base Bike Sharing Dataset.

  1. Ajuste um modelo de Floresta Aleatória para prever a quantidade de bicicletas alugadas (regressão).
  1. Identifique as variáveis importantes para o modelo.
  2. Faça uma previsão com valores hipotéticos.
  1. Ajuste um modelo de Floresta Aleatória para prever se a quantidade de bicicletas alugadas será ou não menor que abaixo de 4.000 (classificação binária).
  1. Identifique as variáveis importantes para o modelo.
  2. Faça uma previsão com valores hipotéticos.
  1. Ajuste um modelo de Floresta Aleatória para prever se a quantidade de bicicletas ficará em qual das três faixas: [0,4.000), [4.000,6.000) ou [6.000,) (multiclasses).
  1. Identifique as variáveis importantes para o modelo.
  2. Faça uma previsão com valores hipotéticos.

4.8 Referências

References

Breiman, Leo. 2001. “Random Forests.” Machine Learning 45: 5–32.
James, Gareth, Daniela Witten, Trevor Hastie, and Robert Tibshirani. 2013. An Introduction to Statistical Learning. Vol. 112. Springer.
Liaw, Andy, and Matthew Wiener. 2002. “Classification and Regression by randomForest.” R News 2 (3): 18–22. https://CRAN.R-project.org/doc/Rnews/.