Random Forest: como funciona um dos algoritmos mais populares de ML

Cínthia Pessanha
cinthiabpessanha
Published in
6 min readNov 20, 2019

--

A área de machine learning, apesar de ser considerada relativamente nova, já conta com uma infinidade de algoritmos dos mais diversos tipos e aplicações. É fato que muitos destes algoritmos são oriundos da área de mineração de dados, como é o caso do K-means, Beyes, dentre outros. Neste artigo, será abordado o funcionamento do algoritmo Random Forest, que baseia-se justamente em um dos algoritmos mais básicos da área de mineração de dados: as árvores de decisão.

Árvores de decisão

Esquematização gráfica de uma árvore de decisão

As árvores de decisão representam uma das formas mais simplificadas de um sistema de suporte à decisão. É um método estatístico, de aprendizagem supervisionada, podendo ser utilizado em problemas de classificação e na realização de previsões.

A partir de um conjunto de dados existente, o método cria uma representação do conhecimento ali embutido, em formato de árvore. Os nós da árvore são criados a partir das características (features) do conjunto de dados. Obviamente existe uma série de cálculos matemáticos envolvidos na escolha de uma determinada feature como nó em uma determinada posição da árvore. Para entender melhor esses cálculos, sugiro a leitura deste artigo.

A biblioteca scikit-learn do Python já tem implementado um algoritmo para geração de arvores de decisão. E o mais legal é que dá para gerar um PDF com a representação gráfica da árvore gerada a partir do dataset fornecido utilizando a biblioteca export_graphviz.

Para mostrar a implementação deste exemplo, escolhi o dataset cujos dados são provenientes do naufrágio mais famoso da história e que deu origem a um dos meus filmes favoritos: TITANIC.

O dataset com os dados referentes aos passageiros do titanic foram obtidos do Kaggle. As características dos passageiros são:

Features disponíveis

Nesta primeira abordagem, foi feita a remoção das features Name, Ticket e Cabin. Ticket e Name foram removidos porque eram únicos por passageiro, o que a torna irrelevante para a geração do modelo (apesar da feature Name possuir pronome de tratamento). Já Cabin , apesar de ter sido removida, pode possuir alguma informação escondida, como por exemplo, a localização das acomodações que foram acometidas de água primeiro, ou suas localizações não propiciavam uma fuga rápida, etc. Além disso, não foram aplicados encoders e nenhum pré-processamento mais rebuscado nos dados, pois tudo isso será abordado em um outro momento, quando formos tratar de feature engineering em um artigo futuro 😊

Utilizando o DecisionTreeClassifier do scikit-learn, obtemos a seguinte árvore de decisão (considerando profundidade de 3 níveis — lembrando que a quantidade de níveis é um parâmetro que pode influenciar diretamente no desempenho e na acurácia das respostas do modelo):

from sklearn import tree
from graphviz import Source
from sklearn.tree import export_graphviz
decision_tree = tree.DecisionTreeClassifier(max_depth=3)
decision_tree = decision_tree.fit(x_train,y_train)
#exporting generated decision tree to PDF
dot_data = tree.export_graphviz(decision_tree, feature_names = list(X_train),class_names = ['Died', 'Survived'],out_file = None )
graph = Source(dot_data) graph.render("test") #test is the name of the file
Árvore de decisão extraída a partir do dataset de passageiros do TITANIC. O algoritmo permite que se escolha a profundidade da árvore gerada.

Ok, so far, so good. Mas vamos supor que para um outro problema, nosso dataset tenha uma quantidade muito maior de features. Concordam que a tendência é que essa árvore aumente de profundidade a medida que novas features são incluídas ao dataset? O problema disso é que uma árvore com grande profundidade tende a responder muito bem a dados conhecidos, porém perca poder de generalização e responda mal a dados desconhecidos (o famoso e temido overfitting).

E se, ao invés de criar uma única árvore de decisão com TODAS as features ao mesmo tempo (juntas e shallow now) criarmos pequenas árvores de decisão a partir de algumas features aleatórias? E no final, fazermos uma votação a partir dos valores retornados por cada árvore? Pois essa é exatamente a abordagem adotada no Random Forest!

Finalmente…Random Forest!

O nome Random Forest faz todo o sentido quando se pensa em seu funcionamento: random significa aleatório, e denota o comportamento do algoritmo ao selecionar subconjuntos de features e montar mini árvores de decisão. Forest significa floresta, já que são geradas várias árvores de decisão.

Várias árvores de decisão = RANDOM FOREST

Ou seja, basicamente, o algoritmo possui 4 passos:

  1. Seleção aleatória de algumas features

2. Seleção da feature mais adequada para a posição de nó raiz

3. Geração dos nós filhos

4. Repete os passos acima até que se atinja a quantidade de árvores desejada

Depois que o modelo é gerado, as previsões são feitas a partir de “votações”. Cada mini árvore toma uma decisão a partir dos dados apresentados. A decisão mais votada é a resposta do algoritmo.

Se olharmos atentamente, a forma de funcionamento do random forest é baseada em Bootstrapp Aggregation (Bagging), o que o torna um algoritmo ensambled, que nada mais é do que a combinação de previsões de múltiplos algoritmos de machine learning juntos, de forma a obter previsões mais acuradas do que qualquer modelo individual. Para mais detalhes sobre bagging, acesse este link.

Por que Random Forest é tão famoso e amplamente adotado?

  • Por ter suas origens na forma mais básica e inicial de um algoritmo de suporte a decisão (as árvores de decisão), fica muito fácil entender seu funcionamento
  • Random Forests resolvem problemas tanto de regressão (ex.: prever valor de uma casa) quanto de classificação (e-mail é spam ou não é spam)
  • Apresenta bons resultados em diversos tipos de problema
  • Tem bom desempenho
  • Possui implementações nas mais diversas bibliotecas de inteligência artificial disponíveis atualmente

É importante lembrar que tanto árvore de decisão quanto random forest estão disponíveis na biblioteca scikit-learn. Abaixo seguem alguns resultados obtidos com a aplicação de ambos os métodos utilizando o mesmo conjunto de dados de passageiros do titanic:

Comparativo de resultados entre árvore de decisão e Random Forest

Para ver o notebook completo, basta acessar minha página no github. Não entendeu esse cross_val_score e como interpretá-lo? Aqui eu explico um pouco sobre esse cálculo e recomendo um livro que pode ser ainda mais esclarecedor.

É importante deixar claro que tudo leva a crer que sempre uma Random Forest irá apresentar resultados melhores que uma árvore de decisão. Mas cada caso é um caso e SEMPRE é uma palavra muito forte. Então, o único SEMPRE aplicável é o que se refere a sempre avaliar os resultados de diversos algoritmos.

Portanto, apesar de suas limitações, as árvores de decisão continuam sendo uma excelente técnica para iniciar estudos na área de machine learning. E se você está iniciando um projeto de machine learning e deseja fazer um teste inicial de desempenho dentre diversos algoritmos, sem dúvida vale a pena incluir o Random Forest como alternativa de avaliação de modelos.

--

--