Blog

Postado em em 31 de outubro de 2022

Datasets Desbalanceados – O que São e Como Trabalhar com Eles?

Você sabe o que é são datasets desbalanceados? Sabe como você pode trabalhar com eles para não ignorar informações importantes?

Aulas Disponíveis:

Caso prefira esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!

Para receber por e-mail o(s) arquivo(s) utilizados na aula, preencha:

Trabalhando com Datasets Desbalanceados

Você sabe o que são datasets desbalanceados? Sabe como trabalhar com eles da forma correta?

Nessa aula eu vou te mostrar o que são as bases de dados desbalanceadas e como trabalhar com um dataset desbalanceado para que consiga fazer suas análises sem problemas!

Como trabalhar com Datasets Desbalanceados

O que é um dataset desbalanceado? Imagine que dentro da sua base de dados, você tenha uma quantidade muito grande de informações de uma classe, só que na outra classe você tem uma quantidade muito pequena.

Ainda não entendeu? Imagine que você tenha uma base de fraudes. Você vai concordar comigo que a quantidade de transações que são normais é muito maior do que quantidade de transações que de fato são fraudes não é mesmo?

Isso vale para uma base de saúde, onde a maioria dos pacientes não vai ter uma determinada doença, só uma quantidade muito pequena vai ter essa doença.

Só que nesses casos o nosso foco está justamente nessas poucas informações, que apesar de poucas são muito importantes.

Quando estamos trabalhando com esse tipo de dado temos que tomar MUITO CUIDADO, pois se estivermos avaliando apenas o percentual de acerto do modelo isso pode ser um problema.

Imagine que o seu modelo classifique todas as transações de um banco como não fraude. Esse modelo vai ter um percentual de acerto muito grande, só que o nosso foco principal é justamente verificar essas fraudes.

Então o que é fraude, foi classificado como uma transação comum e não conseguimos identificar isso de forma correta.

Nesse caso o nosso modelo pode acertar muito, mas não cumpre seu objetivo, que é exatamente verificar quais são as transações fraudulentas.

Vou deixar como sugestão uma aula de Avaliação de Modelo de Classificação caso você tenha alguma dúvida em relação as métricas que utilizamos e os termos!

Vamos então dar início ao nosso aprendizado de máquinas em dataset desbalanceado. Aqui vamos utilizar o dataset disponível no Kaggle no link abaixo:

https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud

Importando e visualizando a base de dados
Importando e visualizando a base de dados

Nesses primeiros blocos de código vamos importar o pandas, que vamos utilizar para nossas análises, vamos ler a nossa base de dados e vamos visualizá-la dentro do Jupyter.

Você deve ter notado que as colunas estão nomeadas como V1, V2… Isso é para garantir que as informações fiquem anônimas.

Mas no final da base você vai notar que temos a coluna Amount, que significa o valor da transação e a coluna Class que vai indicar se temos uma fraude (1) ou uma transação comum (0).

Então mesmo com as informações anônimas, nós temos essas duas informações que vão ser úteis para fazer a nossa classificação.

No gráfico de pizza você deve ter percebido que 99,83% das transações são comuns, ou seja, apenas 0,17% são fraudes.

Por isso temos que tomar cuidado com o nosso modelo, pois como a quantidade de fraude é quase nula o nosso modelo pode acabar ignorando essas informações. E não é isso que queremos!

Contagem dos dados
Contagem dos dados

Para ver melhor esses números fizemos a contagem dos valores, onde o 0 representa uma transação comum e o número 1 representa uma fraude.

Então temos 284.315 transações comuns para apenas 492 fraudes dentro dessa base de dados, mas você vai concordar que não vai querer deixar passar nenhuma delas dentro do seu modelo, não é mesmo?

Vamos começar! Devemos inicialmente separar os dados em treino e teste usando o train test split.

Separando a base de dados em treino e teste e verificando as proporções
Separando a base de dados em treino e teste e verificando as proporções

Aqui fizemos a separação dos dados para que possamos utilizar uma base para o treino e outra base para o teste do nosso modelo.

Além disso, verificamos a proporção dos dados nas duas bases e você pode notar que temos a mesma quantidade para que o teste seja feito da forma correta.

OBS: Para manter essa proporção tanto na base de treino quanto na base de teste é possível utilizar o parâmetro straitfy. Essa informação também está no link do train test split!

Agora vamos partir para a criação de um modelo utilizando Regressão Logística.

Utilizando a regressão logística
Utilizando a regressão logística

E então vamos avaliar o modelo.

Avaliando o modelo
Avaliando o modelo

Vamos começar com a acurácia do modelo. Só que você vai notar que a acurácia em datasets desbalanceados, geralmente é muito alta.

Mas isso não representa a qualidade do nosso modelo nesse caso, pois o nosso foco é justamente nas informações com menos registros.

Então para resolver essa questão utilizamos a matriz de confusão e o recall score.

OBS: Além da página do scikit learn, nós temos uma publicação que fala mais detalhadamente sobre a matriz de confusão para que você entenda melhor como as análises são feitas. Para isso basta clicar aqui.

Geralmente nós testamos mais de um algoritmo para verificar qual deles funciona melhor. Nesse caso não será diferente, vamos testar também a árvore de decisão.

Datasets Desbalanceados
Utilizando a árvore de classificação

Pelo recall nós conseguimos verificar que o segundo modelo consegue encontrar 74% das fraudes, que já é bem maior do que os 58% do primeiro modelo.

Então é importante que você saiba o que são cada uma dessas análises para não informar que o seu modelo com 0,99 de acurácia encontra as fraudes em 99% dos casos.

Agora que já sabemos como trabalhar com esses dados e já entendemos isso tudo, vamos para a parte importante, que é o balanceamento do dataset.

Datasets Desbalanceados
Balanceando o dataset

Nós podemos fazer o balanceamento de duas formas, ou diminuindo a classe majoritária ou aumentando a classe minoritária.

Eu vou mostrar apenas um dos casos nessa aula para não fica muito grande, mas o outro você pode visualizar no arquivo que está disponível para download.

Não se preocupe, pois a análise é a mesma, a única diferente é que um nós vamos fazer o undersampling e na outra o oversampling!

Então vamos ao exemplo reduzindo os registros da classe majoritária, mas vamos fazer isso excluindo os registros de forma aleatória com o RandomUnderSampler.

OBS: Lembrando que para esse passo vamos instalar a biblioteca imbalanced-Learn.

Datasets Desbalanceados
Balanceando os dados pelo RandomUnderSampler

Aqui vamos importar a biblioteca e definir o RandomUnderSampler. Em seguida vamos aplicar para x e y e por fim vamos visualizar os dados.

Aqui você já nota que agora temos a mesma quantidade de informações, ou seja, a mesma quantidade de transações normais e transações fraudulentas.

Datasets Desbalanceados
Analisando e comparando os resultados

Feito isso podemos utilizar novamente a regressão logística e a árvore de decisão para verificar se tivemos uma melhora.

Para a regressão logística usando o undersample passamos de um recall de 58% para 88%, então já tivemos uma melhora significativa.

Já no uso da árvore de decisão passamos de um recall de 74% para 90%. Também uma melhora significativa.

Datasets Desbalanceadas em Projetos de Ciência de Dados

Você sabe como tratar Datasets desbalanceados em projetos de Ciências de dados? Aprenda hoje mais de 6 formas de ajustar seus dados!

Caso prefira esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!

Para receber por e-mail o(s) arquivo(s) utilizados na aula, preencha:

Fala Impressionadores! Na aula de hoje eu quero te dar algumas dicas de como trabalhar com datasets desbalanceados em Ciência de Dados.

A ideia é que você saiba o que fazer quando tiver datasets desbalanceados, ou seja, quando tem 90% da sua base de dados com um valor e 10% com outro por exemplo.

O objetivo será deixar sua base na proporção 50/50 para que fique mais fácil tratar esses dados e que você consiga fazer isso de forma eficiente.

Nessa aula vou te mostrar o UnderSampling (RandomUnderSampler), o OverSampling (RandomOverSampler), algoritmo de clusterização e o KNN.

Para isso vamos utilizar a biblioteca Imbalanced-learn que é muito utilizada nesses casos de bases de dados desbalanceadas!

Trabalhando com datasets desbalanceados – Vamos usar uma base simples para entender os conceitos:

base de dados
base de dados

Para trabalhar com datasets desbalanceados, vamos usar a biblioteca imbalanced-learn:

https://imbalanced-learn.org/stable/index.html

Nosso objetivo é verificar a situação do cliente para saber se ele será um cliente devedor ou não:

Primeiros Passos

Para fazer a importação você precisa fazer o download da base e colocar na mesma pasta deste arquivo.

# Importando a base

import pandas as pd

base = pd.read_excel('BaseInadimplencia.xlsx')

# Visualizando essa base

base.head(3)
visualizando a base
visualizando a base
# Contando a quantidade de valores

base.Situacao.value_counts()
quantidade de valores
quantidade de valores

Aqui podemos perceber que 150 clientes pagaram e que tivemos problemas com 15 clientes. Os clientes inadimplentes receberam a classificação de rótulo 1, portanto se este mesmo cliente pedir um novo empréstimo já sabemos pela classificação que ele não é um bom pagador.

# Visualizando os dados graficamente

base.Situacao.value_counts().plot.pie(autopct='%.2f');
gráfico
gráfico

Visualizando o gráfico podemos ver que temos um dataset desbalanceado, outra forma de visualizar é obtendo a distribuição dos dados:

# Visualizando a distribuição dos dados

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

plt.show()
gráfico de dispersão
gráfico de dispersão

Como podemos balancear o gráfico?

Antes, vamos entender sobre as classes, temos 2 classes:

  • Classe majoritária: a que possui mais registros
  • Classe minoritária: a que possui menos registros

Por que as classes majoritárias e minoritárias são importantes?

Verificando as classes podemos decidir aumentar ou diminuir os registros de uma das classes visando equilibrá-las

métodos
métodos

Para isso, vamos fazer o undersampling (reduzir a classe majoritária) ou o oversampling (aumentar a classe minoritária).

Certo Lucas! Mas qual é o melhor método?

Na verdade, o mais importante é que você entenda os conceitos e entenda o problema, se temos apenas quinze registros da classe minoritária não faz sentido diminuir a classe majoritária, porque no final restariam apenas 30 registros e isso é pouco para fins de análise.

Se por outro lado a classe minoritária tivesse 2 milhões de registros o a majoritária 1 milhão, faz mais sentido reduzir a minoritária para trabalhar com uma base de dados menos pesada, então é mais uma questão de entender o problema.

Para fazer cada um desses balanceamentos existem técnicas diferentes, essas técnicas estão disponíveis na biblioteca imbalanced-learn.

# Instalando a biblioteca

# !pip install -U imbalanced-learn

Reduzindo os registros da classe majoritária (undersampling)

Vamos retirar dados da classe que possui mais registros. Agora, precisamos ter cuidado para que essa retirada não acabe causando perda de informação (retirando informações que são muito importantes).Também é necessário verificar o tamanho da base restante.

Podemos fazer isso excluindo os registros de forma aleatória com a documentação RandomUnderSampler

Documentação

documentação
documentação

Vamos apenas seguir os passos da documentação:

# Separando x e y

X = base.drop('Situacao',axis=1)

y = base.Situacao

Para separar x e y temos que retirar do x a única coluna que corresponde ao y, neste caso a coluna Situção.

# Definindo o RandomUnderSampler

from imblearn.under_sampling import RandomUnderSampler

rus = RandomUnderSampler(random_state=42)

# Definindo a nova amostra

X_res, y_res = rus.fit_resample(X, y)

A nova amostra será definida pela classe com menor número, já que estamos reduzindo a maior.

# Contando os valores

y_res.value_counts()
quantidades
quantidades

Observe que igualamos as quantidades de registros para as duas classes

# E visualizando graficamente

y_res.value_counts().plot.pie(autopct='%.2f');
ajuste
ajuste

Com isso conseguimos equilibrar a nossa base!

# Visualizando a distribuição dos dados

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
pontos aleatórios

Podemos ver agora que todos os pontos em amarelo foram usados, mas que somente alguns dos pontos roxos foram pegos, agora estamos considerando apenas os que estão em vermelho.

Existe outra forma de fazer essa amostragem?

Sim, existem algumas formas, podemos também substituir um conjunto de amostras (um cluster) pelo seu centróide utilizando o ClusterCentroids, dessa forma vamos ter uma perda menor de informação, com ele não selecionamos os pontos de forma aleatória, usamos os centróides de cada ponto.

Documentação

documentação
documentação
# Importando

from imblearn.under_sampling import ClusterCentroids

# Definindo o ClusterCentroids

cc = ClusterCentroids(random_state=42)

# Criando a amostra dos dados

X_res, y_res = cc.fit_resample(X, y)

# Visualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
formação de centróides

Observe que agora uma quantidade menor de pontos do grupo majoritário foi pega, mas, foram formados grupos entre os pontos e definido um centróide, este centróide é o que está sendo considerado como pondo para análise.

Temos também uma terceira opção que é o NearMiss

Ou utilizar o NearMiss para manter apenas os pontos com menor distância aos pontos da classe minoritária

Documentação

documentação
documentação

Nesse caso, irá retirar os pontos, mas vai continuar mantendo a região de separação entre as classes

# Fazendo a reamostragem usando o NearMiss

from imblearn.under_sampling import NearMiss

nm = NearMiss()

X_res, y_res = nm.fit_resample(X, y)

# Visualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
pontos mais próximos

Observe o que foi feito agora, os pontos mais próximos ao grupo minoritário é que foram considerados.

Existem várias outras formas de fazermos o undersampling e todas elas são explicadas na própria documentação:

https://imbalanced-learn.org/stable/under_sampling.html#

Aumentando os registros da classe minoritária

Podemos gerar novos valores baseado nos atuais registros da base de dados, seja apenas duplicando os valores ou utilizando outros métodos (como o KNN) para criar pontos

Precisamos garantir que não vamos ter overfitting por mostrar ao modelo várias vezes dados semelhantes

Podemos começar gerando os registros também de forma aleatória com o RandomOverSample

Documentação

documentação
documentação
# Importando

from imblearn.over_sampling import RandomOverSampler

# Definindo o RandomOverSampler

ros = RandomOverSampler(random_state=42)

# Refazendo nossa amostra

X_res, y_res = ros.fit_resample(X, y)

# Contando os valores

y_res.value_counts()
quantidades
quantidades

Neste caso, estamos usando o modelo de oversampling, aumentando o valor da classe minoritária até igualar a classe majoritária.

# E visualizando graficamente

y_res.value_counts().plot.pie(autopct='%.2f');
Datasets Desbalanceados
ajustes
# Vsualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
aumento da classe minoritária

Agora todos os valores majoritários foram considerados enquanto os minoritários estão sendo repetidos várias vezes no mesmo ponto até alcançar o valor dos majoritários, observe que a cor dos pontos do grupo minoritário está mais forte, porque temos vários pontos um sobre o outro.

Se a repetição dos dados for um problema, podemos utilizar o parâmetro shrinkage.

Quando o parâmetro for passado, ele vai gerar uma “suavização” nos dados considerando os pontos, não um exatamente sobre o outro, mas, considerando pontos ao redor de acordo com o parâmetro de distância que for passado, o ideal é que tenham pouca distância do ponto original.

# Definindo o ros

ros = RandomOverSampler(random_state=42,shrinkage=0.5)

# Refazendo nossa amostra

X_res, y_res = ros.fit_resample(X, y)

# Vsualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
pontos próximos

Observe que foram criados pontos no grupo minoritário próximos aos pontos originais, para gerar dados coerentes até igualar os grupos.

Outra opção é utilizarmos o SMOTE ou ADASYN, que vai utilizar o KNN para gerar novos registros em uma distância aleatória entre o ponto de dado e um dos seus K vizinhos mais próximos

Enquanto o SMOTE vai considerar todos os pontos sem distinção, o ADASYN vai gerar mais observações para aqueles pontos da classe minoritária que tiverem mais observações da classe majoritária na região dos vizinhos mais próximos

Documentação SMOTE

documentação
documentação
# Utilizando o SMOTE

from imblearn.over_sampling import SMOTE

s = SMOTE(random_state=42)

X_res, y_res = s.fit_resample(X, y)

# Vsualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
SMOTE

Documentação – ADASYN

documentação
documentação
# Utilizando ADASYN

from imblearn.over_sampling import ADASYN

a = ADASYN(random_state=42)

X_res, y_res = a.fit_resample(X, y)

# Vsualizando graficamente

fig, ax = plt.subplots(figsize=(6,4))

ax.scatter(base.SaldoConta, base.SaldoInvestimento, c=base.Situacao)

ax.scatter(X_res.SaldoConta, X_res.SaldoInvestimento, c='red',alpha=0.4)

plt.show()
Datasets Desbalanceados
ADASYN

Existem várias outras formas de fazermos o oversampling e todas elas são explicadas na própria documentação de forma bem completa:

https://imbalanced-learn.org/stable/over_sampling.html

Conclusão

Nessa aula eu te mostrei como trabalhar com datasets desbalanceados da forma correta para que você não pense que uma acurácia de 99% nesses casos é um bom modelo.

É importante analisar outras métricas e depois até balancear o dataset para que possa obter melhores resultados.

Pois em datasets desbalanceados as informações mais importantes são as que temos em quantidade mínima, então precisamos analisá-las melhor e não as ignorar!

Lembrando que a segunda análise está no arquivo disponível para download, então você pode verificar quais foram os resultados e pode fazer suas alterações, colocar outros algoritmos para verificar se encontra melhores modelos!

Hashtag Treinamentos

Para acessar outras publicações de Ciência de Dados, clique aqui!


Quer aprender mais sobre Python com um minicurso básico gratuito?

Quer sair do zero no Power BI e virar uma referência na sua empresa? Inscreva-se agora mesmo no Power BI Impressionador