Skip to content

2. Decision Tree

As árvores de decisão são uma técnica popular de aprendizado de máquina supervisionado usada para classificação e regressão. Elas representam decisões e suas possíveis consequências em uma estrutura hierárquica, facilitando a interpretação dos resultados.

graph TD;
    T1((Teste 1)) -->|Sim| T2((Teste 2))
    T1 -->|Não| T3((Teste 3))
    T2 -->|Sim| R1[Resultado 1]
    T2 -->|Não| R2[Resultado 2]
    T3 -->|Sim| R3[Resultado 3]
    T3 -->|Não| R4[Resultado 4]
Exemplo: ir para praia ou não?

Após dias de anotações sobre o comportamento de uma pessoa, foi possível criar uma tabela com os seguintes registros:

Dia Sol? Vento? Praia?
1 Sim Sim Não
2 Sim Sim Não
3 Sim Não Sim
4 Não Não Não
5 Não Sim Não
6 Não Não Não

A partir desses dados, podemos construir uma árvore de decisão para prever se a pessoa irá à praia com base nas condições climáticas.

graph TD;
    A((Sol?)) -->|Sim| B((Vento?))
    A -->|Não| C[Não ir à praia]
    B -->|Sim| D[Não ir à praia]
    B -->|Não| E[Ir à praia]

Árvore de decisão simples para prever se a pessoa irá à praia com base nas condições climáticas. A partir da pergunta "Sol?", a árvore se divide em dois caminhos: se há sol, verifica-se se há vento. Se não há sol, a decisão é não ir à praia. Se não há vento, a decisão é ir à praia. Fonte: Didatica Tech - Árvores de Decisão.

Considerações

Vantagens

  • Interpretação fácil: A estrutura em árvore facilita a visualização e compreensão das decisões tomadas pelo modelo.
  • Não requer normalização: Árvores de decisão não são sensíveis à escala dos dados, o que significa que não é necessário normalizar ou padronizar as variáveis.
  • Capacidade de lidar com dados categóricos e numéricos: Elas podem trabalhar com ambos os tipos de dados sem necessidade de transformação prévia.

Desvantagens

  • Tendência ao overfitting: Árvores de decisão podem se ajustar demais aos dados de treinamento, capturando ruídos e padrões irrelevantes.
  • Instabilidade: Pequenas variações nos dados podem resultar em árvores completamente diferentes, tornando o modelo menos robusto.

Nomenclatura

As árvores de decisão são compostas por nós (representando testes em atributos) e folhas (representando resultados ou classes finais). O processo de construção da árvore envolve a seleção do atributo mais informativo para dividir os dados em subconjuntos, minimizando a impureza (e.g., usando medidas como entropia ou índice Gini)1.

Estrutura de uma Árvore de Decisão

Estrutura de uma Árvore de Decisão: os nós representam testes em atributos, enquanto as folhas representam os resultados finais. Fonte: Aulas - Árvores.

O objetivo de uma árvore de decisão é criar uma estrutura que minimize a impureza dos nós, resultando em folhas que contenham exemplos da mesma classe ou com valores semelhantes. Isso é feito através de um processo iterativo de divisão dos dados, onde em cada nó é escolhido o atributo que melhor separa os dados em termos de classe ou valor.

Existem algumas métricas comuns usadas para medir a qualidade de uma divisão, incluindo:

  • Índice Gini: Mede a impureza dos dados, onde um valor de 0 indica pureza total (todos os exemplos pertencem à mesma classe).
  • Entropia: Mede a incerteza ou aleatoriedade dos dados, onde uma entropia de 0 indica que todos os exemplos pertencem à mesma classe.
  • Ganho de Informação: Mede a redução da entropia após a divisão dos dados.
  • Redução da Variância: Usada em árvores de decisão para regressão, mede a redução da variância dos valores após a divisão dos dados.
  • Chi-quadrado: Usado para medir a independência entre variáveis categóricas, ajudando a identificar interações significativas entre atributos.

Para o cálculo do coeficiente de Gini (mais usado em árvores de decisão):

\[ g_i = 1 - \sum_{i=1}^{n} p_i^2 \]

onde \( p_i \) é a proporção de cada classe \( i \) no conjunto de dados.

Mais baixo a impureza, mais puro o nó.

Construção

Neste exemplo, temos um conjunto de dados sobre transações financeiras, onde cada transação é classificada como "Fraude" ou "Normal". A árvore de decisão pode ser usada para prever se uma nova transação é fraudulenta ou não, com base em características como o valor da transação e o período.

Fraude

Valor Periodo Classe
2500 Diurno Normal
1500 Diurno Normal
700 Diurno Normal
3700 Diurno Normal
5600 Diurno Normal
8000 Diurno Normal
3200 Noturno Normal
2900 Noturno Normal
5950 Diurno Normal
630 Noturno Fraude
1800 Diurno Normal
2700 Diurno Normal
3300 Diurno Normal
4200 Noturno Normal
7000 Diurno Normal
500 Diurno Normal
850 Noturno Normal
900 Diurno Normal
4700 Diurno Fraude
5650 Diurno Fraude
2025-10-14T13:23:46.605407 image/svg+xml Matplotlib v3.10.7, https://matplotlib.org/

Para construir a árvore de decisão, os dados são divididos em nós com base nas características mais informativas, minimizando a impureza dos nós. Para construir a árvore, o algoritmo avalia cada atributo e escolhe aquele que melhor separa as classes, utilizando métricas como o índice Gini ou entropia.

Passo a passo

  1. Definir o nó com os dados daquele ramo.
  2. Calcular a impureza de cada atributo.
  3. Escolher o atributo que melhor separa os dados.
  4. Dividir os dados com base no atributo escolhido.
  5. Repetir o processo para cada subconjunto até que um critério de parada seja atendido (e.g., todos os exemplos em um nó pertencem à mesma classe ou um número mínimo de exemplos é atingido).

Para definir o nó raiz, o algoritmo avalia todos os atributos e calcula a impureza de cada um. O atributo com a menor impureza é escolhido como o nó raiz. Em seguida, os dados são divididos com base nesse atributo, criando ramos na árvore. O processo é repetido recursivamente para cada ramo até que todos os nós sejam folhas (ou seja, não possam ser divididos mais).

Feature Sim Não
Valor >= 3000 18 20
Fraude 5 1
Normal 13 19
Periodo = Noturno 14 24
Fraude 4 2
Normal 10 22

Cálculo do índice de Gini para cada critério sobre atributos:

\[ \text{Gini}(\text{Critério}) = 1 - \left(\frac{fraude}{fraude + normal}\right)^2 - \left(\frac{normal}{fraude + normal}\right)^2 \]
\[ \text{Gini}(\text{Valor}\geq 3000) = 1 - \left(\frac{5}{18}\right)^2 - \left(\frac{13}{18}\right)^2 = 0.4012 \]
\[ \text{Gini}(\text{Valor} < 3000) = 1 - \left(\frac{1}{20}\right)^2 - \left(\frac{19}{20}\right)^2 = 0.0950 \]

Normalizando os valores, temos:

\[ \text{Pureza do nó} = \frac{\text{18}}{38} \cdot 0.4012 + \frac{20}{38} \cdot 0.0950 = 0.2401 \]
\[ \text{Gini}(\text{Periodo} = \text{Noturno}) = 1 - \left(\frac{4}{14}\right)^2 - \left(\frac{10}{14}\right)^2 = 0.4082 \]
\[ \text{Gini}(\text{Periodo} \neq \text{Noturno}) = 1 - \left(\frac{2}{24}\right)^2 - \left(\frac{22}{24}\right)^2 = 0.1528 \]

Normalizando os valores, temos:

\[ \text{Pureza do nó} = \frac{\text{14}}{38} \cdot 0.4082 + \frac{24}{38} \cdot 0.1528 = 0.2469 \]

Árvore de decisão resultante pode ser representada da seguinte forma:

graph TD;
    A{Valor >= 3000?} -->|Sim| B{Periodo = Noturno?}
    A -->|Não| C[Normal]
    B -->|Sim| D[Fraude]
    B -->|Não| E[Normal]

Accuracy: 0.62 2025-10-14T13:23:46.883754 image/svg+xml Matplotlib v3.10.7, https://matplotlib.org/

import matplotlib.pyplot as plt
import pandas as pd

from io import StringIO
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score

plt.figure(figsize=(12, 10))

df = pd.read_csv('https://raw.githubusercontent.com/hsandmann/ml/refs/heads/main/data/fraude.csv')

label_encoder = LabelEncoder()

# Carregar o conjunto de dados
x = df[['Valor', 'Periodo']]
x['Periodo'] = label_encoder.fit_transform(x['Periodo'])
y = df['Classe']

# Dividir os dados em conjuntos de treinamento e teste
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

# Criar e treinar o modelo de árvore de decisão
classifier = tree.DecisionTreeClassifier()
classifier.fit(x_train, y_train)

# Avaliar o modelo
accuracy = classifier.score(x_test, y_test)
print(f"Accuracy: {accuracy:.2f}")
tree.plot_tree(classifier)

# Para imprimir na página HTML
buffer = StringIO()
plt.savefig(buffer, format="svg")
print(buffer.getvalue())

Implementação com Bibliotecas

As árvores de decisão podem ser implementadas usando bibliotecas populares como scikit-learn em Python, que oferece uma interface simples para criar e treinar modelos de árvores de decisão. A seguir é um exemplo básico de como criar uma árvore de decisão para classificação:

Iris Dataset

Validation Accuracy: 1.0000
Feature Importances:

Feature Importance
3 petal width (cm) 0.893313
2 petal length (cm) 0.087577
1 sepal width (cm) 0.019110
0 sepal length (cm) 0.000000
2025-10-14T13:23:47.096787 image/svg+xml Matplotlib v3.10.7, https://matplotlib.org/
sepal_l sepal_w petal_l petal_w class
4.8 3.4 1.9 0.2 setosa
4.6 3.2 1.4 0.2 setosa
6.9 3.1 5.1 2.3 virginica
6.4 3.2 4.5 1.5 versicolor
7.6 3 6.6 2.1 virginica
6.3 2.5 4.9 1.5 versicolor
6.4 2.9 4.3 1.3 versicolor
6.3 2.8 5.1 1.5 virginica
6.9 3.2 5.7 2.3 virginica
6.8 3.2 5.9 2.3 virginica
6.4 2.8 5.6 2.2 virginica
4.9 2.5 4.5 1.7 virginica
6.1 2.8 4 1.3 versicolor
5.5 2.4 3.7 1 versicolor
6 2.7 5.1 1.6 versicolor
import matplotlib.pyplot as plt
import pandas as pd

from io import StringIO
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

plt.figure(figsize=(12, 10))

# Carregar o conjunto de dados Iris
iris = load_iris()
x = iris.data
y = iris.target

# Dividir os dados em conjuntos de treinamento e teste
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)

# Criar e treinar o modelo de árvore de decisão
classifier = tree.DecisionTreeClassifier()
classifier.fit(x_train, y_train)

# Evaluate the model
y_pred = classifier.predict(x_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Validation Accuracy: {accuracy:.4f}")

# Optional: Print feature importances
feature_importance = pd.DataFrame({
    'Feature': iris.feature_names,
    'Importance': classifier.feature_importances_
})
print("<br>Feature Importances:")
print(feature_importance.sort_values(by='Importance', ascending=False).to_html())

tree.plot_tree(classifier)

# Display the plot
buffer = StringIO()
plt.savefig(buffer, format="svg", transparent=True)
print(buffer.getvalue())

Titanic Dataset

Accuracy: 0.79 2025-10-14T13:23:47.827123 image/svg+xml Matplotlib v3.10.7, https://matplotlib.org/

PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 nan S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female 38 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 nan S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 nan S
import matplotlib.pyplot as plt
import pandas as pd

from io import StringIO
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score

# Preprocess the data
def preprocess(df):
    # Fill missing values
    df['Age'].fillna(df['Age'].median(), inplace=True)
    df['Embarked'].fillna(df['Embarked'].mode()[0], inplace=True)
    df['Fare'].fillna(df['Fare'].median(), inplace=True)

    # Convert categorical variables
    label_encoder = LabelEncoder()
    df['Sex'] = label_encoder.fit_transform(df['Sex'])
    df['Embarked'] = label_encoder.fit_transform(df['Embarked'])

    # Select features
    features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
    return df[features]

plt.figure(figsize=(12, 10))

df = pd.read_csv('https://raw.githubusercontent.com/hsandmann/ml/refs/heads/main/data/kaggle/titanic-dataset.csv')

# Carregar o conjunto de dados
x = preprocess(df)
y = df['Survived']

# Dividir os dados em conjuntos de treinamento e teste
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

# Criar e treinar o modelo de árvore de decisão
classifier = tree.DecisionTreeClassifier()
classifier.fit(x_train, y_train)

# Avaliar o modelo
accuracy = classifier.score(x_test, y_test)
print(f"Accuracy: {accuracy:.2f}")
tree.plot_tree(classifier)

# Para imprimir na página HTML
buffer = StringIO()
plt.savefig(buffer, format="svg")
print(buffer.getvalue())

Exercício

Entrega

📆 29.ago 🕒 9:00

Individual

Entrega do link via Canvas.

Dentre os datasets disponíveis, escolha um cujo objetivo seja prever uma variável categórica (classificação). Utilize o algoritmo de árvore de decisão para treinar um modelo e avaliar seu desempenho.

Utilize as bibliotecas pandas, numpy, matplotlib e scikit-learn para auxiliar no desenvolvimento do projeto.

A entrega deve ser feita através do Canvas - Exercício Árvore de Decisão. Só serão aceitos links para repositórios públicos do GitHub contendo a documentação (relatório) e o código do projeto. Conforme exemplo do template-projeto-integrador. ESTE EXERCÍCIO É INDIVIDUAL.

A entrega deve incluir as seguintes etapas:

Etapa Critério Descrição Pontos
1 Exploração dos Dados Análise inicial do conjunto de dados - com explicação sobre a natureza dos dados -, incluindo visualizações e estatísticas descritivas. 20
2 Pré-processamento Limpeza dos dados, tratamento de valores ausentes e normalização. 10
3 Divisão dos Dados Separação do conjunto de dados em treino e teste. 20
4 Treinamento do Modelo Implementação do modelo Decision Tree. 10
5 Avaliação do Modelo Avaliação do desempenho do modelo utilizando métricas apropriadas. 20
6 Relatório Final Documentação do processo, resultados obtidos e possíveis melhorias. Obrigatório: uso do template-projeto-integrador, individual. 20

Adicional