Outubro Rosa — Prevendo Câncer de Mama com ML

Roger Luiz
6 min readOct 23, 2023

--

No mês dedicado à conscientização sobre o câncer de mama, escolhi abordar esse tema vital, destacando não apenas a relevância do autocuidado, mas também explorando o poder dos dados e das ferramentas de Aprendizado de Máquina na previsão da ocorrência desse câncer.

https://blog.superdental.com.br/cancer-de-mama-vamos-falar-sobre-isso/

Introdução

O câncer é uma das doenças mais devastadoras em todo o mundo. Prever a ocorrência de câncer é um desafio crítico na área da medicina. A detecção precoce é fundamental para aumentar as taxas de sobrevivência e melhorar a qualidade de vida dos pacientes. Neste artigo, exploraremos como é possível prever a ocorrência de câncer de mama com a ajuda da aprendizagem de máquina e análise de dados. Utilizaremos dados obtidos a partir do Conjunto de Dados de Câncer de Mama de Wisconsin, disponível em: http://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+%28Diagnostic%29

Etapa 1: Explorando os Dados

Informações sobre os Dados

Os dados de câncer de mama incluem 569 observações de biópsias de câncer, cada uma com 32 características (variáveis). Uma característica é um número de identificação (ID), outro é o diagnóstico de câncer, e 30 são medidas laboratoriais numéricas. O diagnóstico é codificado como “M” para indicar maligno ou “B” para indicar benigno.

O arquivo baixado, já estava no meu diretório no R, então só fiz carrega-lo:

dados <-read.csv(“bc_data.csv”)
head(dados)

Decidi demover a coluna Id, já que para esse caso, ele não me serviria.

dados<-dados[,-1]
str(dados)

Verifiquei se há dados faltantes:

any(is.na(dados))

Agora para uma melhor visualização futura, decidi alterar a coluna diagnosis, alterando “B” e “M” para “Benigno” e “Maligno”. E aproveitei e transformei a coluna para fator.

dados$diagnosis <- factor(dados$diagnosis, levels = c(“B”, “M”), labels = c(“Benigno”, “Maligno”))

Verificando a quantidade:

Normalização dos Dados

Além disso, percebeu-se que os dados apresentavam problemas de escala, o que é crítico para algoritmos de aprendizado de máquina, como o k-Nearest Neighbors (k-NN). Para resolver esse problema, os dados foram normalizados usando a função de normalização.

normalizar <- function(x) { return ((x — min(x)) / (max(x) — min(x))) }

dados_norm <- as.data.frame(lapply(dados[2:31], normalizar))

Etapa 2: Treinando o Modelo

Com os dados devidamente preparados, o próximo passo é treinar o modelo. O k-NN foi escolhido como algoritmo de classificação. Os dados foram divididos em conjuntos de treinamento e teste, e o modelo foi treinado com base nos dados de treinamento. O objetivo é prever se um tumor é maligno ou benigno com base nas características das biópsias.

# Carregando o pacote library
install.packages(“class”)
library(class)

# Criando dados de treino e dados de teste
dados_treino <- dados_norm[1:469, ]
dados_teste <- dados_norm[470:569, ]

# Criando os labels para os dados de treino e de teste
dados_treino_labels <- dados[1:469, 1]
dados_teste_labels <- dados[470:569, 1]

# Criando o modelo
modelo <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 21)

Etapa 3: Avaliando e Interpretando o Modelo

Após o treinamento do modelo, é essencial avaliar sua performance. Isso foi feito utilizando uma matriz de confusão, que revelou a taxa de verdadeiros positivos, verdadeiros negativos, falsos positivos e falsos negativos. Esses valores são cruciais para entender a eficácia do modelo na previsão do câncer de mama.

# Carregando o gmodels
install.packages(“gmodels”)
library(gmodels)

# Criando uma tabela cruzada dos dados previstos x dados atuais
CrossTable(x = dados_teste_labels, y = modelo, prop.chisq = FALSE)

A interpretação dos resultados também é importante. Um verdadeiro positivo significa que o modelo previu corretamente um tumor maligno, enquanto um verdadeiro negativo indica que o modelo previu corretamente um tumor benigno. Falsos positivos e falsos negativos representam erros de previsão.

No nosso caso, o modelo encontrou apenas 2 falsos negativos (Observar linha 2, coluna 2). Na prática, isso quer dizer que o nosso modelo previu que a pessoa NÃO tinha a doença e os dados mostraram que SIM, a pessoa tinha a doença.

Pela lógica, temos 98% de taxa de acerto do modelo. Mas, pare e pense: e essas duas pessoas que receberam a notícia de que não tinham a doença, mas na verdade elas tinham!
Vamos tentar melhorar ainda mais esse nosso modelo.

Etapa 4: Otimizando a Performance do Modelo

Para melhorar a performance do modelo, algumas otimizações foram realizadas.

Uma forma de otimização, é a padronização dos dados via z-score. Para isso, o R tem uma função chamada scale. Observe abaixo:

dados_z <- as.data.frame(scale(dados[-1]))

Agora eu recrio os novos datasets de treino e teste:

dados_treino <- dados_z[1:469, ]
dados_teste <- dados_z[470:569, ]

dados_treino_labels <- dados[ 1: 469, 1]
dados_teste_labels <- dados[ 470: 569, 1]

Agora recrio o modelo:

modelo_v2 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 21)

#Ao aplicarmos a matrix de confusão, encontramos o seguinte resultado:

CrossTable(x = dados_teste_labels, y = modelo_v2, prop.chisq = FALSE)

Observe que temos 5 falsos negativos, mostrando que essa versão do modelo é inferior a primeira. Nesse caso, continuamos…

Agora, vamos alterar o valor do para o hiperparâmetro k.

Variando o valor de k, é possível encontrar o melhor equilíbrio entre viés e variância do modelo. A escolha de k é crítica no k-NN, pois afeta a suavidade da superfície de decisão.

Crio novamente os dados de treino e de teste:

# Criando dados de treino e dados de teste
dados_treino <- dados_norm[1:469, ]
dados_teste <- dados_norm[470:569, ]

# Criando os labels para os dados de treino e de teste
dados_treino_labels <- dados[1:469, 1]
dados_teste_labels <- dados[470:569, 1]

Crio novamente os modelos, variando o hiperparâmetros:

# Valores diferentes para k
modelo_v3 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 1)

modelo_v4 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 5)

modelo_v5 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 11)

modelo_v6 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 15)

modelo_v7 <- knn(train = dados_treino,
test = dados_teste,
cl = dados_treino_labels,
k = 21)

Bom, poderíamos continuar tentando melhorar esse modelo alterando ainda mais o valor do k, tentando fazer outras transformações ou então, poderíamos aumentar o tamanho da nossa amostra.
De qualquer forma, o melhor modelo que encontramos foi o modelo com k=21. O mesmo que fizemos no início, com 98% de acertividade.

Bom, agora poderíamos calcular a taxa de erro do nosso modelo e plota-lo em um gráfico pra ficar bem interessante. Mas o artigo já está bem denso. Vamos deixar essa parte para uma postagem futura.

Obrigado, e lembre-se de se cuidar. Câncer de Mama mata!

Até a próxima!

--

--

Roger Luiz
Roger Luiz

Written by Roger Luiz

Baiano, professor e engenheiro. Ah, e amante da ciência de dados também!