Skip to content

Exploração de Dados

Descrição da base de dados e código de exploração

O câncer de mama é o tipo de câncer mais comum entre mulheres em todo o mundo, responsável por aproximadamente 25% de todos os casos e afetando milhões de pessoas todos os anos. Ele se desenvolve quando células da mama começam a crescer de forma descontrolada, formando tumores que podem ser identificados por exames de imagem (raios-X) ou detectados como nódulos.

O principal desafio no diagnóstico é diferenciar corretamente os tumores malignos (cancerosos) dos benignos (não cancerosos). O objetivo deste projeto é desenvolver um modelo de classificação supervisionada capaz de prever, com base em atributos numéricos das células, se um tumor é maligno ou benigno.

Sobre o Dataset

Total de registros: 569 amostras

Variável alvo: diagnosis (M = maligno, B = benigno)

Número de variáveis preditoras: 30 atributos numéricos relacionados ao tamanho, textura, formato e concavidade das células

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
from tabulate import tabulate  


#carregamento da base
df = pd.read_csv('https://raw.githubusercontent.com/MariaLuizazz/MACHINE-LEARNING-PESSOAL/refs/heads/main/dados/breast-cancer.csv')
print(df.sample(n=10, random_state=42).to_markdown(index=False))
id diagnosis radius_mean texture_mean perimeter_mean area_mean smoothness_mean compactness_mean concavity_mean concave points_mean symmetry_mean fractal_dimension_mean radius_se texture_se perimeter_se area_se smoothness_se compactness_se concavity_se concave points_se symmetry_se fractal_dimension_se radius_worst texture_worst perimeter_worst area_worst smoothness_worst compactness_worst concavity_worst concave points_worst symmetry_worst fractal_dimension_worst
87930 B 12.47 18.6 81.09 481.9 0.09965 0.1058 0.08005 0.03821 0.1925 0.06373 0.3961 1.044 2.497 30.29 0.006953 0.01911 0.02701 0.01037 0.01782 0.003586 14.97 24.64 96.05 677.9 0.1426 0.2378 0.2671 0.1015 0.3014 0.0875
859575 M 18.94 21.31 123.6 1130 0.09009 0.1029 0.108 0.07951 0.1582 0.05461 0.7888 0.7975 5.486 96.05 0.004444 0.01652 0.02269 0.0137 0.01386 0.001698 24.86 26.58 165.9 1866 0.1193 0.2336 0.2687 0.1789 0.2551 0.06589
8670 M 15.46 19.48 101.7 748.9 0.1092 0.1223 0.1466 0.08087 0.1931 0.05796 0.4743 0.7859 3.094 48.31 0.00624 0.01484 0.02813 0.01093 0.01397 0.002461 19.26 26 124.9 1156 0.1546 0.2394 0.3791 0.1514 0.2837 0.08019
907915 B 12.4 17.68 81.47 467.8 0.1054 0.1316 0.07741 0.02799 0.1811 0.07102 0.1767 1.46 2.204 15.43 0.01 0.03295 0.04861 0.01167 0.02187 0.006005 12.88 22.91 89.61 515.8 0.145 0.2629 0.2403 0.0737 0.2556 0.09359
921385 B 11.54 14.44 74.65 402.9 0.09984 0.112 0.06737 0.02594 0.1818 0.06782 0.2784 1.768 1.628 20.86 0.01215 0.04112 0.05553 0.01494 0.0184 0.005512 12.26 19.68 78.78 457.8 0.1345 0.2118 0.1797 0.06918 0.2329 0.08134
927241 M 20.6 29.33 140.1 1265 0.1178 0.277 0.3514 0.152 0.2397 0.07016 0.726 1.595 5.772 86.22 0.006522 0.06158 0.07117 0.01664 0.02324 0.006185 25.74 39.42 184.6 1821 0.165 0.8681 0.9387 0.265 0.4087 0.124
9012000 M 22.01 21.9 147.2 1482 0.1063 0.1954 0.2448 0.1501 0.1824 0.0614 1.008 0.6999 7.561 130.2 0.003978 0.02821 0.03576 0.01471 0.01518 0.003796 27.66 25.8 195 2227 0.1294 0.3885 0.4756 0.2432 0.2741 0.08574
853201 M 17.57 15.05 115 955.1 0.09847 0.1157 0.09875 0.07953 0.1739 0.06149 0.6003 0.8225 4.655 61.1 0.005627 0.03033 0.03407 0.01354 0.01925 0.003742 20.01 19.52 134.9 1227 0.1255 0.2812 0.2489 0.1456 0.2756 0.07919
8611161 B 13.34 15.86 86.49 520 0.1078 0.1535 0.1169 0.06987 0.1942 0.06902 0.286 1.016 1.535 12.96 0.006794 0.03575 0.0398 0.01383 0.02134 0.004603 15.53 23.19 96.66 614.9 0.1536 0.4791 0.4858 0.1708 0.3527 0.1016
911673 B 13.9 16.62 88.97 599.4 0.06828 0.05319 0.02224 0.01339 0.1813 0.05536 0.1555 0.5762 1.392 14.03 0.003308 0.01315 0.009904 0.004832 0.01316 0.002095 15.14 21.8 101.2 718.9 0.09384 0.2006 0.1384 0.06222 0.2679 0.07698

Pré-Processamento

Explicação dos processos realizados no pré-processamento

Antes do treinamento do modelo, foi realizado um pré-processamento para garantir a qualidade e consistência dos dados:

Remoção de colunas irrelevantes – A coluna id foi descartada, pois não contribui para o aprendizado do modelo.

Tratamento de valores ausentes – Foram encontrados valores faltantes em algumas variáveis (concavity_worst e concave points_worst). Esses valores foram preenchidos utilizando a mediana, por ser uma técnica robusta contra outliers.

Codificação de variáveis categóricas – A variável alvo diagnosis foi transformada em valores numéricos por meio de Label Encoding (M = 1, B = 0), permitindo sua utilização pelo algoritmo de aprendizado.

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


#carregamento da base
df = pd.read_csv('https://raw.githubusercontent.com/MariaLuizazz/MACHINE-LEARNING-PESSOAL/refs/heads/main/dados/breast-cancer.csv')


#pré processamento
#remoção da coluna id pois é irrelevante para o modelo
df = df.drop(columns=['id'])

#conversão de letra para número
label_encoder = LabelEncoder()  
df['diagnosis'] = label_encoder.fit_transform(df['diagnosis'])

#features escolhidas, todas menos diagnosis e id
x = df.drop(columns=['diagnosis'])
y = df['diagnosis']

#imputação com mediana de valores ausentes nas features concavity_worts e concavity points_worst
df['concavity_mean'].fillna(df['concavity_mean'].median(), inplace=True)
df['concave points_mean'].fillna(df['concave points_mean'].median(), inplace=True)

print(df.to_markdown(index=False))
diagnosis radius_mean texture_mean perimeter_mean area_mean smoothness_mean compactness_mean concavity_mean concave points_mean symmetry_mean fractal_dimension_mean radius_se texture_se perimeter_se area_se smoothness_se compactness_se concavity_se concave points_se symmetry_se fractal_dimension_se radius_worst texture_worst perimeter_worst area_worst smoothness_worst compactness_worst concavity_worst concave points_worst symmetry_worst fractal_dimension_worst
0 12.47 18.6 81.09 481.9 0.09965 0.1058 0.08005 0.03821 0.1925 0.06373 0.3961 1.044 2.497 30.29 0.006953 0.01911 0.02701 0.01037 0.01782 0.003586 14.97 24.64 96.05 677.9 0.1426 0.2378 0.2671 0.1015 0.3014 0.0875
1 18.94 21.31 123.6 1130 0.09009 0.1029 0.108 0.07951 0.1582 0.05461 0.7888 0.7975 5.486 96.05 0.004444 0.01652 0.02269 0.0137 0.01386 0.001698 24.86 26.58 165.9 1866 0.1193 0.2336 0.2687 0.1789 0.2551 0.06589
1 15.46 19.48 101.7 748.9 0.1092 0.1223 0.1466 0.08087 0.1931 0.05796 0.4743 0.7859 3.094 48.31 0.00624 0.01484 0.02813 0.01093 0.01397 0.002461 19.26 26 124.9 1156 0.1546 0.2394 0.3791 0.1514 0.2837 0.08019
0 12.4 17.68 81.47 467.8 0.1054 0.1316 0.07741 0.02799 0.1811 0.07102 0.1767 1.46 2.204 15.43 0.01 0.03295 0.04861 0.01167 0.02187 0.006005 12.88 22.91 89.61 515.8 0.145 0.2629 0.2403 0.0737 0.2556 0.09359
0 11.54 14.44 74.65 402.9 0.09984 0.112 0.06737 0.02594 0.1818 0.06782 0.2784 1.768 1.628 20.86 0.01215 0.04112 0.05553 0.01494 0.0184 0.005512 12.26 19.68 78.78 457.8 0.1345 0.2118 0.1797 0.06918 0.2329 0.08134
1 20.6 29.33 140.1 1265 0.1178 0.277 0.3514 0.152 0.2397 0.07016 0.726 1.595 5.772 86.22 0.006522 0.06158 0.07117 0.01664 0.02324 0.006185 25.74 39.42 184.6 1821 0.165 0.8681 0.9387 0.265 0.4087 0.124
1 22.01 21.9 147.2 1482 0.1063 0.1954 0.2448 0.1501 0.1824 0.0614 1.008 0.6999 7.561 130.2 0.003978 0.02821 0.03576 0.01471 0.01518 0.003796 27.66 25.8 195 2227 0.1294 0.3885 0.4756 0.2432 0.2741 0.08574
1 17.57 15.05 115 955.1 0.09847 0.1157 0.09875 0.07953 0.1739 0.06149 0.6003 0.8225 4.655 61.1 0.005627 0.03033 0.03407 0.01354 0.01925 0.003742 20.01 19.52 134.9 1227 0.1255 0.2812 0.2489 0.1456 0.2756 0.07919
0 13.34 15.86 86.49 520 0.1078 0.1535 0.1169 0.06987 0.1942 0.06902 0.286 1.016 1.535 12.96 0.006794 0.03575 0.0398 0.01383 0.02134 0.004603 15.53 23.19 96.66 614.9 0.1536 0.4791 0.4858 0.1708 0.3527 0.1016
0 13.9 16.62 88.97 599.4 0.06828 0.05319 0.02224 0.01339 0.1813 0.05536 0.1555 0.5762 1.392 14.03 0.003308 0.01315 0.009904 0.004832 0.01316 0.002095 15.14 21.8 101.2 718.9 0.09384 0.2006 0.1384 0.06222 0.2679 0.07698

Divisão de Dados

Separação em treino e teste

O dataset foi dividido em conjuntos de treino e teste para permitir a avaliação do modelo em dados não vistos durante o treinamento. Foram utilizadas duas proporções distintas:

Etapa I: 80% treino, 20% teste

Etapa II: 70% treino, 30% teste

Essa variação foi realizada para observar como a quantidade de dados de treino impacta o desempenho do modelo.

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
from tabulate import tabulate  


#carregamento da base
df = pd.read_csv('https://raw.githubusercontent.com/MariaLuizazz/MACHINE-LEARNING-PESSOAL/refs/heads/main/dados/breast-cancer.csv')


#pré processamento

#remoção da coluna id pois é irrelevante para o modelo
df = df.drop(columns=['id'])

#conversão de letra para número
label_encoder = LabelEncoder()  
df['diagnosis'] = label_encoder.fit_transform(df['diagnosis'])

#features escolhidas, todas menos diagnosis e id
x = df.drop(columns=['diagnosis'])
y = df['diagnosis']

#imputação com mediana de valores ausentes nas features concavity_worts e concavity points_worst
df['concavity_mean'].fillna(df['concavity_mean'].median(), inplace=True)
df['concave points_mean'].fillna(df['concave points_mean'].median(), inplace=True)

#divisão de treinamento e teste 
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42, stratify=y)

print(df.to_markdown(index=False))

Treinamento do modelo

Etapas do treinamento

Na etapa de treinamento, foi utilizado o algoritmo de Árvore de Decisão, por ser um método simples, interpretável e bastante utilizado em problemas de classificação inicial.

ETAPA I:

Divisão: 80% treino, 20% teste

Resultado: 93% de acurácia

ETAPA II:

Divisão: 70% treino, 30% teste

Resultado: 90% de acurácia

Os resultados mostram que pequenas variações na divisão dos dados afetam a acurácia final, embora o desempenho geral do modelo tenha se mantido satisfatório.

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
from tabulate import tabulate  


#carregamento da base
df = pd.read_csv('https://raw.githubusercontent.com/MariaLuizazz/MACHINE-LEARNING-PESSOAL/refs/heads/main/dados/breast-cancer.csv')

#pré processamento
#remoção da coluna id pois é irrelevante para o modelo
df = df.drop(columns=['id'])

#conversão de letra para número
label_encoder = LabelEncoder()  
df['diagnosis'] = label_encoder.fit_transform(df['diagnosis'])

#features escolhidas, todas menos diagnosis e id
x = df.drop(columns=['diagnosis'])
y = df['diagnosis']

#imputação com mediana de valores ausentes nas features concavity_worts e concavity points_worst
df['concavity_mean'].fillna(df['concavity_mean'].median(), inplace=True)
df['concave points_mean'].fillna(df['concave points_mean'].median(), inplace=True)

#divisão de treinamento e teste 
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42, stratify=y)

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

print(df.sample(n=10, random_state=42).to_markdown(index=False))

Avaliação do Modelo Final

Após os testes iniciais, foi feita a avaliação final do modelo. O foco desta etapa foi verificar o comportamento da árvore de decisão em termos de acurácia e complexidade. A árvore gerada inicialmente se apresentou pequena, sugerindo que o modelo poderia estar simplificando demais os padrões dos dados (underfitting). Após ajustes na proporção de dados de treino, a árvore tornou-se mais consistente, refletindo melhor as relações entre as variáveis. O modelo alcançou 90% de acurácia no conjunto de teste, isso significa que, a cada 100 diagnósticos, 90 foram corretos.

Embora existam modelos que possam alcançar valores um pouco maiores (como 95%+), a escolha dos 90% foi intencional:

Por que 90% foi considerado adequado?

  • Balanceamento entre desempenho e generalização
  • Acima de 90%, o modelo começava a apresentar sinais de overfitting.

Importância clínica

  • No contexto de câncer de mama, evitar falsos negativos (não detectar um tumor maligno) é prioridade.

Conclusão da Avaliação

O modelo final com 90% de acurácia foi escolhido por representar o melhor equilíbrio entre desempenho, generalização e relevância prática para o contexto médico.

Breast Cancer Dataset

Accuracy: 0.90 2025-09-02T19:34:46.040233 image/svg+xml Matplotlib v3.10.6, 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
from tabulate import tabulate  


#carregamento da base
df = pd.read_csv('https://raw.githubusercontent.com/MariaLuizazz/MACHINE-LEARNING-PESSOAL/refs/heads/main/dados/breast-cancer.csv')

#pré processamento
#remoção da coluna id pois é irrelevante para o modelo
df = df.drop(columns=['id'])

#conversão de letra para número
label_encoder = LabelEncoder()  
df['diagnosis'] = label_encoder.fit_transform(df['diagnosis'])

#features escolhidas, todas menos diagnosis e id
x = df.drop(columns=['diagnosis'])
y = df['diagnosis']

#imputação com mediana de valores ausentes nas features concavity_worts e concavity points_worst
df['concavity_mean'].fillna(df['concavity_mean'].median(), inplace=True)
df['concave points_mean'].fillna(df['concave points_mean'].median(), inplace=True)


#divisão de treinamento e teste 
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42, stratify=y)

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

# Plotar árvore
plt.figure(figsize=(12,10))

# Avaliação o modelo, medindo a acuracia
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())

Relatório Final

Resumo do Projeto

Este projeto teve como objetivo aplicar técnicas de Machine Learning para criar um modelo capaz de prever se um tumor de mama é benigno ou maligno, utilizando o dataset Breast Cancer (Diagnostic).

  • As etapas seguidas foram:

Exploração de dados - Pré-processamento - Divisão de dados – separação em treino e teste - Treinamento do modelo - Avaliação do modelo – análise do desempenho final com base na acurácia e na estrutura da árvore.

Resultados Obtidos

  • Acurácia variando entre 90% e 93%, dependendo da proporção de treino/teste utilizada.

Conclusão

Mesmo com limitações, o projeto cumpriu seu objetivo: desenvolver um modelo de classificação supervisionada e aplicar todo o fluxo de pré-processamento, treino e avaliação, consolidando o meu aprendizado sobre o processo de Machine Learning.