Outubro Rosa — Prevendo Câncer de Mama com ML
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.
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!