Como lidar com Classes Desbalanceadas em Machine Learning (Precision , Recall , Oversampling e Undersampling)

Luís Miguel Alves
8 min readApr 10, 2021
Classes desbalanceadas , como resolver?

Classes desbalanceadas (ou como eu gosto de falar , mais 0’s do que 1’s , ou vice-versa) são problemas do cotidiano de qualquer cientista de dados , eu diria até o mais comum , apesar de serem simples de serem contornado são extremamente importantes , por isso eu hoje decidi elaborar este artigo a fim de esclarecer tudo sobre esse conceito!

O que você vai ler neste artigo:

  • O que são classes desbalanceadas?;
  • Precision e Recall;
  • Identificando os problemas;
  • Oversampling;
  • Undersampling;

obs: Neste artigo me detive a não usar muitas linhas de códigos , mas saiba que elas estão sim disponíveis , clicando aqui você é redirecionado ao Notebook do Google Colab no qual foram retirados os resultados deste artigo , caso queira aplicar diretamente os algoritmos aqui ensinado , acesse-o

O que são classes desbalanceadas?

Para entendermos este conceito vamos a um exemplo:

Imagine que você é dono de um banco , e como todos os bancos você tem de lidar com fraudes , isso é , comprar feitas que não são reconhecidas pelo real dono do cartão. Não precisamos de muito para compreender que fraudes acontecem , mas obviamente não a todo momento. O fato é que a chance de ocorrer uma fraude nas compras de um cartão é pequenas quando comparadas ao todo.

Pensando nisso , você resolve criar um Modelo de Machine Learning que possa prever essas fraudes. Sabendo dessa diferença entre fraudes , você consegue um conjunto de dados que tenham aproximadamente 1.000 dados de fraude e 1.000.000 de dados não fraudes. Perceba que ao criar um modelo e treiná-lo você esta usando menos dados de fraude do que não fraudes.

Em que isso acarreta? Basicamente nosso modelo será capaz de detectar comprar reais com boa precisão , afinal , ele “estudou” 1 milhão de casos e sabe o que faz. Por outro lado , ao tentar detectar fraudes reais ele poderá não se sair tão bem , isso por que que apenas “estudou” 1 mil casos de fraudes , talvez ele não seja tão bom para fazer esse tipo de predição.

De forma resumida:

“A classe desbalanceada ocorre quando temos um dataset que possui muitos exemplos de uma classe e poucos exemplos da outra classe.

Precision e Recall

Mas afinal , como detectamos que realmente temos problemas com classes desbalanceadas?

Digamos que você não tenha visto a distribuição das classes previamente e decidiu treinar seu modelo e obteve uma acurácia média de 80% , pode parecer que foi bom o rendimento , mas não , não foi.

Enfim, que poderá de fato nos informar com exatidão nosso problema? Chamamos esses heróis de “Métricas de Avaliação” — Precision e Recall

Precision : Como o nome já diz , o Precision mede a precisão do modelo. Dados um número total de classificações como 0 , quantas dessas classificações meu modelo previu corretamente? Imagine que temos 100 dados que sejam classificados como 0 , se meu modelo acertar 83 deles , dizemos que temos um modelo com 83% de precisão.

precision Machine Learning
Precision

Recall : A tradução da palavra Recall quer dizer algo como “lembrar” ou “recordar” , podemos fazer essas analogia. Irei explicar de forma bem minuciosa pois este pode ser um pouco mais complexo de se entender. Imagine que naquele mesmo modelo , temos um total de 100 dados , nestes 50 se classificam como 0 e os outros 50 como 1. Para eles , nosso modelo classifica corretamente como 1 um total de 30 dados e para 0 ele classifica errado um total de 45. o Recall é basicamente a razão entre os classificados corretamente como 1 (ou 0 também , existe um valor de Recall para cada classificação) pela soma destes com os classificados errados de 0. Neste caso temos um Recall de 40% (30 divido por 45+30)

recall Machine Learning
Recall

Identificando os Problemas:

Usei um conjunto de dados com classes desbalanceadas e obtive o seguinte resultado:

Perceba que o Precision e o Recall para a classificação como 1 são extremamente baixo , mesmo assim ainda temos uma boa acurácia , ou seja , nem sempre a “acurácia” (ou accuracy) representa tudo em nosso modelo. Neste caso podemos afirmar que ele ficou muito bom em classificar os valores de 0 , mas não tão bom para classificar os valores de 1.

Caso queira checar o Notebook Completo direto no Google Colab com maiores explicações clique aqui

Perceba que mesmo sem ter verificado previamente a distribuição das classes , com simples métricas de avaliação podemos checar isso!

Mas afinal , como podemos contornar esse problema? Equiparar nossos dados, e existem duas principais forma de fazê-lo: Oversampling e Undersampling .

Oversampling:

Em uma tradução literal , Oversampling significa “sobreamostragem”.

Mas o que isso quer dizer? Basicamente vamos igualar nossos dados mediante a classe majoritária. Como assim? Imagine que temos duas classe , uma delas tem 1 mil dados e a outra apenas 100 , vamos aumentar esta última até que ela tenha 1 mil dados também!

Aqui vai um exemplo:

Oversampling
https://i0.wp.com/dataaspirant.com/wp-content/uploads/2020/08/10-oversampling.png?ssl=1

Em nossos exemplos , o que na imagem é chamado de “label” , aqui chamamos de classe.

Perceba que foi aumentado o número de dados na “label 0”. Mas como?

Simples: criando dados sintéticos.

Existem diversas formas de fazer isso , e claro há toda uma lógica para fazer isso, não entrarei em detalhes do funcionamento neste artigo.

A forma que usaremos será o chamado SMOTE (Synthetic Minority Over-sampling Technique , algo como Técnica de sobreamostragem de minoria sintética ) , este algoritmo automatiza todas as funções para o usuário!

Ao aplicarmos ele em nossos dados teremos os seguintes resultados:

Agora obtivemos não só uma maior acurácia , como também melhoramos muitos os parâmetros de precision e recall .

Aplicação do SMOTE em código:

# importando o SMOTE:
from imblearn.over_sampling import SMOTE
# instanciando o SMOTE:
smote = SMOTE()
# aplicando o SMOTE aos nossos dados ("treinando"):
valores_X , valores_y = smote.fit_sample(valores_X , valores_y)
# Agora basta usá-los em seu modelo de Machine Learning

Entretanto , nem tudo são flores, a criação de dados sintéticos pode nos trazer problemas!

Vamos aos fatos , eu utilizei a palavra Sintéticos , isso é , dados não reais , criados por um algoritmo que tenta replicar padrões que ele observa nos dados. Dependendo da quantidade de dados podemos ter um problema chamado de Overfitting

Overfitting : Como o próprio nome sugere , “treinamos demais”. Neste caso nosso modelo fica muito bom em prever APENAS os dados de treino! Ou seja , o modelo não consegue generalizar bem os dados.

Overfitting
https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Overfitting.svg/1200px-Overfitting.svg.png

Note que neste exemplo temos duas classes marcadas com pontos na cor azul e vermelha. A linha de cor preta representa um modelo que generaliza bem os dados , já a linha verde é um modelo Overfiting , no lugar de criar uma equação que possa prever qualquer entrada de dados , ele cria uma equação que imita os dados de treino. Isso pode acontecer quanto temos dados muitos parecidos , justamente o que o SMOTE faz , cria dados sintéticos parecidos.

Undersampling:

Por outro lado temos o Undersampling que basicamente faz o mesmo que o Oversampling , só que ao contrário.

No undersampling ao invés de aumentarmos os dados , vamos diminuí-lo , ou seja vamos pegar a classe majoritária e diminuir os dados dela a fim de que tenha a mesma quantidade daqueles da classe minoritária.

Este caso não há a criação , apenas uma seleção de dados. Veja no seguinte exemplo

Undersampling
https://i1.wp.com/dataaspirant.com/wp-content/uploads/2020/08/17-undersampling.png?ssl=1

Neste caso diminuímos a “label 1” (ou classe 1) a fim de que tenha a mesma quantidade da label 0.

Apesar de ser simples de ser feito , isto é , basicamente selecionamos dados , há um algoritmo que nos ajuda , chamamos ele de NearMiss. Ao aplicarmos eles ao nosso conjunto de dados obtivemos o seguinte resultado:

Aqui tivemos uma acurácia menor , mas o problema do precision e do recall foi solucionado.

Aplicação do NearMiss em código:

# importando o NearMiss
from imblearn.under_sampling import NearMiss
# instanciando o NearMiss
nm = NearMiss()
# Aplicando o Near Miss aos nossos dados:
valores_X , valores_y = nm.fit_sample(valores_X , valores_y)
# Agora basta usá-los no seu modelo de Machine Learning

Assim como no Oversampling temos o problema de Overfitting , no Undersampling temos o problema de Underfitting.

Underfitting : Como o próprio nome sugere , o Underfitting “treina de menos”. Ora , se dessa vez no lugar de aumentarmos os dados fizemos foi diminuí-lo nosso modelo agora “estuda” de menos , ou algo do tipo. Quanto menos dados , menos complexa é a equação de prevê qualquer classificação.

Underfitting

Note que neste novo caso temos uma reta (equação) genérica . Como temos poucos dados sendo usado para treino , teremos menos informação na hora da construção do nosso modelo de Machine Learning .

Conclusões:

Problemas de classes desbalanceadas serão problemas comuns na sua vida de Cientista de Dados , seja em projetos pessoas , seja em resolução de problemas na empresa onde trabalha.

Veja que o que fiz aqui foi mostrar uma panorama geral da situação . Não afirmo que o SMOTE seja melhor que o NearMiss , na verdade para este caso o SMOTE se saiu melhor nas análises , cada caso é um caso , .Talvez você tenha caído neste artigo por acaso tentando resolver um problema, pois saiba que você deverá testar com qual deles seu modelo se sai melhor.

Caso queira acessar todo o código e análises mais profundas , por favor , considere acessar o Notebook no Google Colab deste artigo aqui.

Links:

LinkedIn ;

Github;

--

--

Luís Miguel Alves

Connoisseur of Data Science and lover of historical books, I am a young data scientist aspiring to a great career