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:
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!
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
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!
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.
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.
E então vamos avaliar 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.
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.
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.
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.
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.
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:
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)
# Contando a quantidade de valores
base.Situacao.value_counts()
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');
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()
Como podemos balancear o gráfico?
Antes, vamos entender sobre as classes, temos 2 classes:
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
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
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()
Observe que igualamos as quantidades de registros para as duas classes
# E visualizando graficamente
y_res.value_counts().plot.pie(autopct='%.2f');
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()
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
# 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()
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
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()
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
# 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()
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');
# 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()
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()
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
# 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()
Documentação – ADASYN
# 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()
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
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!
Para acessar outras publicações de Ciência de Dados, clique aqui!
Expert em conteúdos da Hashtag Treinamentos. Auxilia na criação de conteúdos de variados temas voltados para aqueles que acompanham nossos canais.