Prévia do material em texto
Classificação
Naive Bayes
Naive Bayes é um algoritmo de machine learning simples e rápido, usado para problemas de
classificação. Ele é baseado no Teorema de Bayes, da teoria da probabilidade. A palavra “naive”
(ingênuo) significa que o algoritmo faz uma suposição simples: ele considera que todas as
características (variáveis) são independentes entre si.
A Fórmula
A fórmula básica do Teorema de Bayes é:
P(A|B) = P(B|A) × P(A) / P(B)
Para classificação, usamos esta versão:
P(classe|características) = P(características|classe) × P(classe) /
P(características)
O que isso significa?
• P(classe|características): Probabilidade de uma classe dado o conjunto de características
(o que queremos descobrir)
• P(características|classe): Probabilidade de observar essas características em uma
determinada classe
• P(classe): Probabilidade da classe (quão comum ela é)
• P(características): Probabilidade das características (podemos ignorar para comparação)
Quando usar Naive Bayes?
O Naive Bayes funciona bem para:
• Classificação de textos – detecção de spam, análise de sentimento, categorização de
documentos
• Diagnóstico médico – previsão de doenças com base em sintomas
• Sistemas de recomendação – sugestão de produtos ou conteúdos
• Previsões em tempo real – quando você precisa de resultados rápidos
Onde aplicar?
Boas situações:
• Quando você tem dados categóricos (como palavras, categorias, valores sim/não)
• Quando precisa de um algoritmo rápido e que use pouca memória
• Quando tem um conjunto de dados pequeno para treino
• Quando as características são, em grande parte, independentes (ou quando essa
suposição é aceitável)
Não é ideal para:
• Relações complexas entre as características
• Situações em que é necessária altíssima precisão para decisões críticas
• Dados numéricos contínuos (embora possa ser adaptado)
Tipos de Naive Bayes
• Existem três tipos principais:
• Naive Bayes Gaussiano – para dados numéricos contínuos
• Naive Bayes Multinomial – para dados de contagem (como frequência de palavras)
• Naive Bayes Bernoulli – para dados binários (sim/não, verdadeiro/falso)
Vantagens
• Muito rápido para treinar e fazer previsões
• Funciona bem com conjuntos de dados pequenos
• Simples de entender e implementar
• Bons resultados em classificação de textos
Desvantagens
• A suposição de independência geralmente está errada
• Não consegue aprender relações entre as características
• Nem sempre é o algoritmo mais preciso
Exemplo:
P (C∣X )=P (X∣C )⋅P (C )
P (X )
Onde:
• C = classe (Alto, Moderado, Baixo)
• X = conjunto de atributos (História, Dívida, Garantias, Renda)
• P(C) = probabilidade a priori da classe
• P(X C) = probabilidade dos atributos dado a classe∣
• P(X) = constante de normalização
Na imagem:
P(Alto)=P(Alto) x P(História∣Alto) × P(Dívida∣Alto) ×
P(Garantias∣Alto) × P(Renda∣Alto)
P (A lt o )= 6
14
⋅ 1
6
⋅ 4
6
⋅ 6
6
⋅ 1
6
Carregamento da base de dados
import pandas as pd
import random
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
dataset = pd.read_csv("/content/drive/MyDrive/Estatística para Ciência
de Dados e Machine Learning/Bases de dados/credit_data.csv")
dataset.shape
(2000, 5)
dataset.head()
{"summary":"{\n \"name\": \"dataset\",\n \"rows\": 2000,\n
\"fields\": [\n {\n \"column\": \"i#clientid\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
577,\n \"min\": 1,\n \"max\": 2000,\n
\"num_unique_values\": 2000,\n \"samples\": [\n 1861,\
n 354,\n 1334\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"income\",\n \"properties\":
{\n \"dtype\": \"number\",\n \"std\":
14326.32711885004,\n \"min\": 20014.4894700497,\n
\"max\": 69995.6855783239,\n \"num_unique_values\": 2000,\n
\"samples\": [\n 40240.7275559381,\n
46706.4588610083,\n 51211.6540386342\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"age\",\n \"properties\": {\n
\"dtype\": \"number\",\n \"std\": 13.624469455596008,\n
\"min\": -52.4232799196616,\n \"max\": 63.971795841120205,\n
\"num_unique_values\": 1997,\n \"samples\": [\n
36.6687041711994,\n 43.0130229773931,\n
32.553030352108195\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n },\n {\n \"column\":
\"loan\",\n \"properties\": {\n \"dtype\": \"number\",\n
\"std\": 3045.4100243915154,\n \"min\": 1.37762959325451,\n
\"max\": 13766.0512393337,\n \"num_unique_values\": 2000,\n
\"samples\": [\n 7498.630446855849,\n
7084.263509070559,\n 4093.360006036261\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"c#default\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
0,\n \"min\": 0,\n \"max\": 1,\n
\"num_unique_values\": 2,\n \"samples\": [\n 1,\n
0\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n }\n ]\
n}","type":"dataframe","variable_name":"dataset"}
dataset.tail()
{"summary":"{\n \"name\": \"dataset\",\n \"rows\": 5,\n \"fields\":
[\n {\n \"column\": \"i#clientid\",\n \"properties\": {\n
\"dtype\": \"number\",\n \"std\": 1,\n \"min\": 1996,\n
\"max\": 2000,\n \"num_unique_values\": 5,\n
\"samples\": [\n 1997,\n 2000,\n 1998\n
],\n \"semantic_type\": \"\",\n \"description\": \"\"\n
}\n },\n {\n \"column\": \"income\",\n \"properties\":
{\n \"dtype\": \"number\",\n \"std\":
12770.554147657615,\n \"min\": 43756.0566049069,\n
\"max\": 69516.1275728606,\n \"num_unique_values\": 5,\n
\"samples\": [\n 69516.1275728606,\n
69436.57955154781,\n 44311.44926231349\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"age\",\n \"properties\": {\n
\"dtype\": \"number\",\n \"std\": 17.724525188227087,\n
\"min\": 23.162104470655304,\n \"max\": 63.971795841120205,\n
\"num_unique_values\": 5,\n \"samples\": [\n
23.162104470655304,\n 56.1526170284487,\n
28.0171668957919\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n },\n {\n \"column\":
\"loan\",\n \"properties\": {\n \"dtype\": \"number\",\n
\"std\": 2446.0023471942495,\n \"min\": 1622.72259832146,\n
\"max\": 7378.833598730591,\n \"num_unique_values\": 5,\n
\"samples\": [\n 3503.1761563262603,\n
7378.833598730591,\n 5522.786693255141\n ],\n
\"semantic_type\": \"\",\n \"description\": \"\"\n }\
n },\n {\n \"column\": \"c#default\",\n
\"properties\": {\n \"dtype\": \"number\",\n \"std\":
0,\n \"min\": 0,\n \"max\": 1,\n
\"num_unique_values\": 2,\n \"samples\": [\n 1,\n
0\n ],\n \"semantic_type\": \"\",\n
\"description\": \"\"\n }\n }\n ]\n}","type":"dataframe"}
# Checking for null values
dataset.isnull().sum()
i#clientid 0
income 0
age 3
loan 0
c#default 0
dtype: int64
# Deleting Null values
dataset.dropna(inplace=True)
dataset.shape
(1997, 5)
dataset.isnull().sum()
i#clientid 0
income 0
age 0
loan 0
c#default 0
dtype: int64
sns.countplot(x='c#default', data=dataset);
plt.title('Default Status Distribution(0 = Paid, 1 = Not Paid)');
x = dataset.iloc[:, 1:4].values
y = dataset.iloc[:, 4].values
x.shape, y.shape
((1997, 3), (1997,))
Observação.
Quando há valores muito discrepantes entre as variáveis em estudo, o conjunto de dados pode
tornar-se inadequado para o treinamento do modelo, uma vez que o algoritmo passa a favorecer
a classe majoritária. Para contornar esse problema, faz-se necessário o uso de técnicas de
amostragem.
Base de treinamento e teste
x_train, x_test, y_train, y_test = train_test_split(x, y,
test_size=0.2, stratify=y)
# 80% of dataset for train
x_train.shape, y_train.shape
((1597, 3), (1597,))
# 20% of dataset for test
x_test.shape, y_test.shape
((400, 3), (400,))
np.unique(y, return_counts=True)
(array([0, 1]), array([1714, 283]))
print(f"Paying clients: {(1714 / len(dataset)) * 100:.2f}%")
print(f"Non-paying clients: {(283 / len(dataset)) * 100:.2f}%")
Paying clients: 85.83%
Non-paying clients: 14.17%
np.unique(y_train, return_counts=True)
(array([0, 1]), array([1371, 226]))
print(f"Paying clients: {(1371 / len(y_train)) * 100:.2f}%")
print(f"Non-paying clients: {(226 / len(y_train)) * 100:.2f}%")
Paying clients: 85.85%
Non-paying clients: 14.15%
np.unique(y_test, return_counts=True)
(array([0, 1]), array([343, 57]))
print(f"Paying clients: {(343 / len(y_test)) * 100:.2f}%")
print(f"Non-paying clients: {(57 / len(y_test)) * 100:.2f}%")
Paying clients: 85.75%
Non-paying clients: 14.25%
Observação
Tadas as bases de dados y estão com o mesmo valor percentual, ou seja, a estratificação foi feita
corretamente, mas mesmo assim ainda temos valores descrepante entre os dois valores.
Classificação com Naive Bayes.
from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
model.fit(x_train, y_train)
GaussianNB()
"""
Predict() is used to train the Naive Bayes model (model) to make
predictions on the x_test dataset.
This means it's asking the model to classify each instance in the test
set,
and these predicted classifications are then stored in the forecast
variable
"""
forecast = model.predict(x_test)
forecast
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0,
0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0,
1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0,
0, 0, 0, 0])
# Original data
y_test
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0,
0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1,
0,
0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
0,
1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0,
0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
1,
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
0,
0, 0, 0, 0])
Measuring accuracy between forecast and y_test
from sklearn.metrics import accuracy_score, confusion_matrix
accuracy = accuracy_score(forecast, y_test)
print(f"Accuracy: {accuracy * 100:.2f}%")
Accuracy: 91.75%
# Show the values that were classified correctly
cm = confusion_matrix(y_test, forecast)
print("Confusion Matrix:\n", cm)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.show()
Confusion Matrix:
[[335 8]
[ 25 32]]
paid_0 = cm[0][0]
paid_1 = cm[0][1]
print("Client who paid off the loan\n")
print(f"Correct Classified: {(paid_0 / (paid_0 + paid_1)*100):.2f}%")
print(f"Incorrect Classified: {(paid_1 / (paid_0 + paid_1)*100):.2f}
%")
Client who paid off the loan
Correct Classified: 97.67%
Incorrect Classified: 2.33%
not_paid_0 = cm[1][0]
not_paid_1 = cm[1][1]
print("Client who paid off the loan\n")
print(f"Correct Classified: {(not_paid_1 / (not_paid_0 +
not_paid_1)*100):.2f}%")
print(f"Incorrect Classified: {(not_paid_0 / (not_paid_0 +
not_paid_1)*100):.2f}%")
Client who paid off the loan
Correct Classified: 56.14%
Incorrect Classified: 43.86%
import locale
locale.setlocale(locale.LC_ALL, '')
# Example:
losses = 5000 # monetary value of the loss per person
non_paying_client = 1000
error = (23 / (23 + 34)) * 100
total_non_paying_client = round(non_paying_client * error / 100)
loss_amount = total_non_paying_client * losses
print(f"Total possible customers who will not pay:
{total_non_paying_client}")
print(f"Possible loss for the bank: {locale.currency(loss_amount,
grouping=True)}")
Total possible customers who will not pay: 404
Possible loss for the bank: $2,020,000.00
Subamostragem (Undersampling)
• https://imbalanced-learn.org/stable/user_guide.html
Conceito
Subamostragem (Undersampling) é uma técnica utilizada em Machine Learning para lidar com
conjuntos de dados desbalanceados, ou seja, quando uma classe (a classe majoritária) possui
significativamente mais amostras do que outra(s) classe(s) (a(s) classe(s) minoritária(s)).
O Problema do Desbalanceamento:
Em muitos problemas de classificação, os modelos tendem a dar mais atenção à classe
majoritária, resultando em um desempenho ruim na classificação da classe minoritária, que
pode ser a mais interessante para o problema (por exemplo, detecção de fraude, doenças raras,
clientes que dão 'default' no crédito).
https://imbalanced-learn.org/stable/user_guide.html
Como Funciona o Undersampling: A ideia principal do undersampling é reduzir o número de
amostras da classe majoritária para equilibrar a proporção entre as classes. Existem várias
abordagens para fazer isso:
1. Undersampling Aleatório (Random Undersampling):
– Remove aleatoriamente um certo número de amostras da classe majoritária até
que a proporção desejada seja atingida. É a forma mais simples e direta.
2. Tomek Links:
– Identifica pares de amostras de classes diferentes que são vizinhos muito
próximos. Se essas amostras forem de classes diferentes, e a amostra da classe
majoritária estiver muito próxima da amostra da classe minoritária, a amostra da
classe majoritária é removida. Isso ajuda a remover ruídose a criar fronteiras de
decisão mais claras.
3. Edited Nearest Neighbours (ENN):
– Remove uma amostra da classe majoritária se ela não for classificada
corretamente por seus k-vizinhos mais próximos (que devem ser da mesma
classe).
4. Condensed Nearest Neighbours (CNN):
– Seleciona um subconjunto de amostras da classe majoritária que, quando
combinadas com todas as amostras da classe minoritária, são capazes de
classificar corretamente todas as amostras originais. Isso busca reter as amostras
mais informativas da classe majoritária.
Vantagens do Undersampling:
• Pode ajudar a melhorar o desempenho do modelo na classe minoritária.
• Reduz o tamanho do dataset, o que pode diminuir o tempo de treinamento e o custo
computacional, especialmente em datasets muito grandes.
Desvantagens do Undersampling:
• Perda de Informação: A maior desvantagem é a perda de dados valiosos. Ao remover
amostras da classe majoritária, podemos perder informações importantes e
representativas sobre essa classe, o que pode levar a um modelo menos robusto ou a um
overfitting da classe minoritária.
• Pode não ser a melhor opção se a classe majoritária já for pequena ou se a perda de
dados for crítica.
Quando Usar:
• Undersampling é geralmente considerado quando se tem um dataset muito grande,
onde a redução do número de amostras da classe majoritária não comprometerá
significativamente a informação global, ou quando o tempo de treinamento é uma
preocupação.
• É importante sempre comparar com outras técnicas de balanceamento, como o
oversampling (SMOTE, por exemplo) ou o uso de pesos de classe, para encontrar a
melhor estratégia para o seu problema.
Tomek Links Algoritimo
from imblearn.under_sampling import TomekLinks
"""Undersampling"""
tl = TomekLinks(sampling_strategy='majority')
x_under, y_under = tl.fit_resample(x, y) # Uso de fit_resample, que
retorna apenas X e y reamostrados.
x_under.shape, y_under.shape
((1897, 3), (1897,))
np.unique(y, return_counts=True) # Dataset original
(array([0, 1]), array([1714, 283]))
np.unique(y_under, return_counts=True) # Dataset TomekLinks
(array([0, 1]), array([1614, 283]))
""" Split the dataset """
x_train_tl, x_test_tl, y_train_tl, y_test_tl =
train_test_split(x_under, y_under, test_size=0.2, stratify=y_under)
x_train_tl.shape, y_train_tl.shape # 80% of dataset for train
((1517, 3), (1517,))
x_test_tl.shape, y_test_tl.shape # 20% of dataset for train
((380, 3), (380,))
""" To Train """
model_u = GaussianNB()
model_u.fit(x_train_tl, y_train_tl)
GaussianNB()
""" Predict """
forecast_tl = model_u.predict(x_test_tl)
accuracy_tl = accuracy_score(forecast_tl, y_test_tl)
print(f"Accuracy: {accuracy_tl * 100:.2f}%")
Accuracy: 90.00%
""" Confusion Matrix """
cm_tl = confusion_matrix(y_test_tl, forecast_tl)
print("Confusion Matrix:\n", cm_tl)
sns.heatmap(cm_tl, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.show()
paid_tl_0 = cm_tl[0][0]
paid_tl_1 = cm_tl[0][1]
print("Client who paid off the loan\n")
print(f"Correct Classified: {(paid_tl_0 / (paid_tl_0 +
paid_tl_1)*100):.2f}%")
print(f"Incorrect Classified: {(paid_tl_1 / (paid_tl_0 +
paid_tl_1)*100):.2f}%")
not_paid_tl_0 = cm_tl[1][0]
not_paid_tl_1 = cm_tl[1][1]
print("Client who paid off the loan\n")
print(f"Correct Classified: {(not_paid_tl_1 / (not_paid_tl_0 +
not_paid_tl_1)*100):.2f}%")
print(f"Incorrect Classified: {(not_paid_tl_0 / (not_paid_tl_0 +
not_paid_tl_1)*100):.2f}%")
Sobreamostragem (Oversampling)
Conceito
Como Funciona o Oversampling:
A ideia principal do oversampling é aumentar o número de amostras da classe minoritária,
replicando-as ou gerando novas amostras sintéticas, até que a proporção entre as classes seja
mais equilibrada. Existem várias técnicas de oversampling, as mais comuns incluem:
1. Oversampling Aleatório (Random Oversampling):
– Simplesmente duplica aleatoriamente as amostras existentes da classe
minoritária. É a técnica mais direta.
– Vantagem: Fácil de implementar.
– Desvantagem: Pode levar a overfitting, pois o modelo pode memorizar as
amostras duplicadas, e não contribui com nova informação ou variedade aos
dados.
2. SMOTE (Synthetic Minority Over-sampling Technique):
– É uma das técnicas de oversampling mais populares e sofisticadas. Em vez de
simplesmente duplicar, o SMOTE gera novas amostras sintéticas para a classe
minoritária. Ele faz isso selecionando um k-vizinho mais próximo para cada
amostra da classe minoritária e criando novas amostras ao longo da linha que une
a amostra original e seus vizinhos.
– Vantagem: Adiciona variedade aos dados, criando amostras que são ligeiramente
diferentes das originais, o que pode ajudar a evitar o overfitting e melhorar a
generalização do modelo.
– Desvantagem: Pode gerar amostras ruidosas ou sobrepor-se à classe majoritária
em áreas de fronteira mal definidas, especialmente em espaços de alta dimensão.
3. ADASYN (Adaptive Synthetic Sampling):
– Semelhante ao SMOTE, mas gera mais amostras sintéticas para as instâncias da
classe minoritária que são mais difíceis de classificar (aquelas que estão mais
próximas da fronteira da classe majoritária). Ele avalia a densidade das amostras
da classe minoritária em relação à classe majoritária e foca em gerar amostras
onde a classe minoritária é mais esparsa.
– Vantagem: Adapta a geração de amostras às necessidades do conjunto de dados,
focando nas áreas mais desafiadoras.
– Desvantagem: Pode ser mais sensível a ruídos e outliers do que o SMOTE.
Vantagens do Oversampling:
• Não há perda de informação, pois todas as amostras existentes são mantidas.
• Pode melhorar significativamente o desempenho do modelo na classe minoritária,
permitindo que ele aprenda melhor os padrões dessa classe.
• Gera modelos mais equilibrados e justos, especialmente quando a classe minoritária é
crucial para o problema.
Desvantagens do Oversampling:
• Aumento do Tamanho do Dataset: O principal problema é que ele aumenta o tamanho
do conjunto de dados, o que pode levar a um aumento no tempo de treinamento e nos
custos computacionais, especialmente com técnicas como SMOTE e ADASYN.
• Overfitting (em Random Oversampling): O oversampling aleatório pode causar
overfitting, pois o modelo simplesmente memoriza as amostras duplicadas.
• Geração de Ruído (em SMOTE/ADASYN): Se a classe minoritária já for ruidosa, técnicas
sintéticas podem amplificar esse ruído ou criar amostras que não são representativas da
verdadeira distribuição dos dados.
Quando Usar:
• Oversampling é uma escolha comum quando a perda de dados da classe majoritária
(como ocorreria no undersampling) é inaceitável ou quando o conjunto de dados original
não é excessivamente grande.
• A escolha da técnica específica (SMOTE, ADASYN, etc.) depende da complexidade do
problema e das características do desbalanceamento.
SMOTE Algoritmo
from imblearn.over_sampling import SMOTE
smote = SMOTE(sampling_strategy='minority')
x_smote, y_smote = smote.fit_resample(x, y)
x_smote.shape, y_smote.shape
np.unique(y, return_counts=True)
np.unique(y_smote, return_counts=True)
""" Split the dataset """
x_train_sm, x_test_sm, y_train_sm, y_test_sm =
train_test_split(x_smote, y_smote, test_size=0.2, stratify=y_smote)
train_80 = x_train_sm.shape, y_train_sm.shape
test_20 = x_test_sm.shape, y_test_sm.shape
print(f"Train:{train_80}\nTest: {test_20}")
""" Train """
model_sm = GaussianNB()
model_sm.fit(x_train_sm, y_train_sm)
""" Predict """
forecast_sm = model_sm.predict(x_test_sm)
accuracy_sm = accuracy_score(forecast_sm, y_test_sm)
print(f"Accuracy: {accuracy_sm * 100:.2f}%")
""" Confusion Matrix """
cm_sm = confusion_matrix(y_test_sm, forecast_sm)
print("Confusion Matrix:\n", cm_sm)
sns.heatmap(cm_sm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.show()
paid_sm_correct = cm_sm[0][0]
paid_sm_incorrect = cm_sm[0][1]
print("Client who paid off the loan\n")print(f"Correct Classified: {(paid_sm_correct / (paid_sm_correct +
paid_sm_incorrect)*100):.2f}%")
print(f"Incorrect Classified: {(paid_sm_incorrect / (paid_sm_correct +
paid_sm_incorrect)*100):.2f}%")
non_paid_sm_incorrect = cm_sm[1][0]
non_paid_sm_correct = cm_sm[1][1]
print("Client who paid off the loan\n")
print(f"Correct Classified: {(non_paid_sm_correct /
(non_paid_sm_incorrect + non_paid_sm_correct)*100):.2f}%")
print(f"Incorrect Classified: {(non_paid_sm_incorrect /
(non_paid_sm_incorrect + non_paid_sm_correct)*100):.2f}%")
#
import locale
locale.setlocale(locale.LC_ALL, '')
# Example:
losses = 5000 # monetary value of the loss per person
non_paying_client = 1000
error = (non_paid_sm_incorrect / (non_paid_sm_incorrect +
non_paid_sm_correct)*100)
total_non_paying_client = round(non_paying_client * error / 100)
loss_amount = total_non_paying_client * losses
print(f"Total possible customers who will not pay:
{total_non_paying_client}")
print(f"Possible loss for the bank: {locale.currency(loss_amount,
grouping=True)}")
Classificação
Naive Bayes
A Fórmula
O que isso significa?
Quando usar Naive Bayes?
Onde aplicar?
Tipos de Naive Bayes
Vantagens
Desvantagens
Exemplo:
Carregamento da base de dados
Observação.
Base de treinamento e teste
Observação
Classificação com Naive Bayes.
Measuring accuracy between forecast and y_test
Subamostragem (Undersampling)
Conceito
Tomek Links Algoritimo
Sobreamostragem (Oversampling)
Conceito
SMOTE Algoritmo