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: 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):
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 |
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
- Definir o nó com os dados daquele ramo.
- Calcular a impureza de cada atributo.
- Escolher o atributo que melhor separa os dados.
- Dividir os dados com base no atributo escolhido.
- 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:
Normalizando os valores, temos:
Normalizando os valores, temos:
Á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
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 |
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
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
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 |