KNN #3 — Codando nosso classificador de câncer de mama
Show me the code!
Para começarmos a brincadeira nós precisamos de dados, vamos então baixar o dataset Breast Cancer Wisconsin que vimos no artigo passado.
Você pode ver como baixar o arquivo com os dados seguindo o artigo anterior
Algumas observações antes de começarmos, após eu ter feito o dowlaond desse dataset, fiz algumas modificações bem simples nele que foram:
- Remoção da coluna do ID que não servira como dado de tributo nesse nosso exemplo
- Mudança da coluna de saída(classificação) para a última coluna
Após feito o dowload você tem duas opções:
1 — Baixar um dataset modificado por mim para facilitar o desenvolvimento do algoritmo KNN através desse link;
2 — Seguir o passo a passo e ir adaptando o código ao dataset;
Bem vamos começar! Antes de qualquer coisa, o código completo desse tutorial encontra-se nesse link.
Depois de ter seu dataset criado vamos criar dentro da pasta do nosso projeto criar uma pasta chamada “datas” e colocar todos os nossos datsets lá.
E fora dessa pasta “datas” vamos criar o nosso arquivo chamado main.go
Estou usando o editor VS Code para o desenvolvimento desse algoritmo, porém você pode usar qualquer um outro que não terá impacto nenhum para seguir o conteúdo da serie.
Vamos então definir o nome do pacote e criar a função main que será por onde nosso código irá começar
Obs: os comentários estarão em inglês pois vou fazer uma versão em inglês desse artigo também rs
Para começar a brincadeira nós vamos precisar trazer nosso dataset para a memória, então vamos criar um método que leia csv e traga isso em formato de matriz para dentro do código.
Agora toda o nosso dataset está dentro da variável “recodords”
Se imprimirmos o valor dessa variavel no terminal, teremos o seguinte valor
fmt.Println(records)…[7.76 24.54 47.92 181 0.05263 0.04362 0 0 0.1587 0.05884 0.3857 1.428 2.548 19.15 0.007189 0.00466 0 0 0.02676 0.002783 9.456 30.37 59.16 268.6 0.08996 0.06444 0 0 0.2871 B]]
Temos então nosso dataset ao qual nós vamos fazer varias iterações sobre ele e aplicar toda aquela teoria que vimos no artigo #1.
O próximo passo depois de obter o dataset, será dividi-lo em 2 partes, uma de treino e outra de teste.
Dados de treino: será os dados já classificados ao qual usaremos para treinar o nosso algoritmo;
Dados de teste: será os dados já classificados ao qual usaremos para validar a acurácia do nosso algoritmo;
Vamos dividir nosso dateset da seguinte forma, 70% dos dados de cada classe para teste e o restante(30%) de cada classe para teste.
Pra começar vamos extrair as classes do nosso dataset de forma unica, para isso vamos usar a seguinte lógica;
-> Extrair do nosso dataset(records) a coluna onde há os valores das classes;
-> Dar um distinct para limpar os valores repetidos e assim obter as nossas classes únicas;
[getCollum(…)]
No motodo getCollum nós recebemos uma matriz no parâmetro elements, vamos no índice de uma determinada coluna com o parâmetro columIndex e para cada linha dentro dessa coluna, nós adicionamos a um array novo que vamos retornar para o solicitante.
[distinct(…)]
Com o retorno do método getcolum nós vamos passar esse valor para o método distict que recebe um array e pra cada elemento desse array, ele:
-> Verifica-se se esse mesmo elemento encontra-se no map(dicionario) “encontred”
-> Caso não exista, ele irá adicionar o elemento ao map “encontred”
-> Caso exista, não adicione nada ao map “encontred”
No final vamos retornar nosso map encontred onde não terá classes repetidas.
Obs: optei por fazer tudo na mão para evitar o mal entendimento de quem não está acostumado com os pacotes do go.
Ao imprimir o valor de “classes” fmt.Println(classes) teremos um array com dois valores [M B]
Vamos então iterar sobre essas classes para obter os 70% de dados de cada classe para treino e 30% dos dados para teste.
Vamos criar nossas matrizes train e test antes das nossas iterações, pois nelas vamos atribuir os valores dos 70% e 30% dos dados.
No nosso método getValuesByClass() vamos receber uma matriz e uma classe, nela vamos filtrar nossa matriz para trabalharmos com dados apenas de uma classe em especifico.
Nossa variável “values” na primeira iteração, terá a matriz com valores correspondente a uma unica classe, exemplo: M.
Na segunda iteração sobre as nossas classes, a variável “values” terá então, dados correspondente a classe: B.
Depois de termos filtrado apenas os dados correspondente a uma determinada classe, precisamos dividir esses dados entre treino e teste, faremos isso da seguinte maneira:
Depois de termos obtido nossos dados de teste e de treino dentro do escopo da nossa iteração, vamos então alimentar a nossa matriz que está fora do escopo desse loop.
Eu sei, usar um loop para concatenar um array/slice não é a melhor forma, mas lembre-se que estou codificando da maneira mais didática que consegui, então por favor, sinta-se a vontade para melhorar o código.
Depois de separar os dados, vamos fazer as classificações e os testes!
Vamos classificar cada linha do nosso dataset de teste e vamos contabilizar quantos nós acertamos e quantos nós erramos.
Por fim podemos imprimir algumas coisinhas:
fmt.Println(“Total de dados: “, len(records))
fmt.Println(“Total de treinamento: “, len(train))
fmt.Println(“Total de testes: “, len(test))
fmt.Println(“Total de acertos: “, hits)
fmt.Println(“Porcentagem de acertos: “, (100 * hits / len(test)), “%”)
No final, ao rodar “go run main.go” no terminal, teremos este resultado:
Total de dados: 569
Total de treinamento: 513
Total de testes: 513
Total de acertos: 484
Porcentagem de acertos: 94 %
E caso você queira ver quais foram os acertos e os erros, nós podemos imprimir a classificação que foi feita para o dado de teste descomentando a linha 22 do gist acima:
//fmt.Println(“tumor: “, test[i][columnIndex], “ classificado como:
E teremos a seguinte saída:
tumor: M classificado como: B
tumor: M classificado como: M
tumor: M classificado como: M
tumor: M classificado como: M
tumor: M classificado como: M
tumor: M classificado como: M
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
tumor: B classificado como: B
Total de dados: 569
Total de treinamento: 513
Total de testes: 513
Total de acertos: 479
Porcentagem de acertos: 93 %
Obrigado por ter lido todo o conteúdo, espero que lhe seja muito útil.
[Momento jabá]
Não deixe de se tornar membro da nossa comunidade (AI BRASIL) que está ganhando o brasil, já estamos em São Paulo em no Rio de Janeiro (por enquanto!), fazemos meetups todos os meses, e em todos os meetups temos hands-ons, falando de assuntos como o desse artigo, só que de uma forma mais aprofundada e com “tira duvidas” !