DEV Community 👩‍💻👨‍💻

Cover image for Projeto de Detecção de Fraudes em Cartão de Crédito
Sávio Santos
Sávio Santos

Posted on • Updated on

Projeto de Detecção de Fraudes em Cartão de Crédito

Projeto requisitado na disciplina de Tópicos Avançados em Eng. de Software 1 - Universidade de Pernambuco Campus Garanhuns - Bacharelado em Engenharia de Software - 7º período


1 - Preparação do ambiente:

  • Google Colab (para construir o notebook e realizar a análise utilizando as bibliotecas já existentes na linguagem Python);
  • Dataset (base de dados que pode ser encontrada aqui que possui um conjunto de transações anonimizadas com operações fraudulentas e genuínas em operações com cartão de crédito.

Vamos lá!!! Crie um projeto em branco em colab.research.google.com e vamos começar!!!


2 - Importando as bibliotecas necessárias:

# Para manipulação do dataset e visualização de dados
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split

# Para classificação dos dados
from sklearn import model_selection
from sklearn.metrics import classification_report
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from imblearn.under_sampling import NearMiss
from sklearn import tree
Enter fullscreen mode Exit fullscreen mode

3 - Importando e atribuindo o dataset a uma variável:

# Use o Dropbox, Github ou até a importação
# direta do Colab para ter acesso aos dados
file_path = "https://www.dropbox.com/s/b44o3t3ehmnx2b7/creditcard.csv?dl=1"

df = pd.read_csv(file_path)
Enter fullscreen mode Exit fullscreen mode

4 - Vamos verificar o tamanho do dataset e já vamos separar 15% dos dados para testes:

df.shape
# (284807, 31) quase 300k transações e 31 colunas

# separando 15% dos dados para os testes
test = df.sample(frac=0.15, random_state=0)

# removendo do dataset principal 
# as transações selecionadas para teste 
df = df.drop(test.index)

test.shape
# (42721, 31) cerca de 43k transações para testes

df.shape
# (242086, 31) agora cerca de 243k 
# transações no dataset principal
Enter fullscreen mode Exit fullscreen mode

5 - Apresentado as 5 primeiras entradas do dataset e o resumo estatístico:

# 5 primeiras entradas
df.head()

# Resumo estatístico
df.describe()
Enter fullscreen mode Exit fullscreen mode

5 primeitas entradas do dataset

Resumo estatístico do dataset

Conseguimos perceber que as colunas com o prefixo V estão anonimizadas, então são provavelmente referentes a informações sensíveis das transações. Porém as colunas de Time, Amount e Class estão presentes sem anonimização. Confira a descrição do dataset no Kaggle para ter mais informações sobre essas colunas.


6 - Verificando a porcentagem de valores ausentes:

percent_missing = df.isnull().sum() * 100 / len(df)
missing_values = pd.DataFrame({'Coluna': df.columns, '% de valores ausentes': percent_missing})
missing_values
Enter fullscreen mode Exit fullscreen mode

Porcentagem de valores ausentes no dataset

Coisa boa!! nenhum valor ausente. Um passo a menos a realizar, pois caso a base estivesse com valores ausentes deveria ser analisado uma estratégia para preencher ou remover esses dados.


7 - Apresentando gráfico de barras da coluna de Class (que é a coluna que identifica se a transação é fraudulenta ou não):

sns.countplot(x="Class", data=df)
Enter fullscreen mode Exit fullscreen mode

Gráfico de barras da coluna de Class do dataset

Conseguimos perceber que o dataset está bastante desbalanceado porquê a quantidade de fraudes é muitíssimo baixa em comparação com as transações verídicas. Existem bibliotecas de balanceamento com o SMOTE e NearMiss. Nesse cenário específico não consegui balancear o dataset usando o SMOTE. Mas obtive êxito ao balancear usando NearMiss que será aplicado mais a frente.


8 - Apresentando histogramas para as colunas de Time e Amount nos cenários de fraude (Class = 1) e não fraude (Class = 0):

# Histograma da variável Time no caso de não fraude
df.Time[df.Class == 0].hist(figsize=(10,5))

# Histograma da variável Time no caso de fraude
df.Time[df.Class == 1].hist(figsize=(10,5))

# Histograma da variável Amount no caso de não fraude
df.Amount[df.Class == 0].hist(figsize=(10,5))

# Histograma da variável Amount no caso de fraude
df.Amount[df.Class == 1].hist(figsize=(10,5))
Enter fullscreen mode Exit fullscreen mode
  • Histograma da variável Time no caso de não fraude Histograma da variável Time no caso de não fraude
  • Histograma da variável Time no caso de fraude Histograma da variável Time no caso de fraude
  • Histograma da variável Amount no caso de não fraude Histograma da variável Amount no caso de não fraude
  • Histograma da variável Amount no caso de fraude Histograma da variável Amount no caso de fraude Conseguimos perceber através desses gráficos que o valor das transações fraudulentas são valores baixos que possivelmente visam não levantar suspeita. Ademais, o intervalo entre a primeira transação e as transções fraudulentas são muitos menores em comparação dessa diferença com as transações verídicas.

9 - Apresentando gráfico de Box Plot para a variável Amount no caso de fraude:

fig = plt.figure(figsize=(10, 7))
plt.boxplot(df.Amount[df.Class == 1])
plt.show()
Enter fullscreen mode Exit fullscreen mode

Box Plot para a variável Amount no caso de fraude

Também confirma que as transações fraudulentas se concentram em valores baixos.


10 - Removendo outliers da variável Amount (dados no intervalo do 3º quartil):

df = df.loc[(df['Amount'] < 1500)]
Enter fullscreen mode Exit fullscreen mode

11- Apresentando Box Plot novamente sem os outliers da variável Amount:

Box Plot sem outliers para a variável Amount no caso de fraude


12 - Apresentando Matriz de Correlação:

fig, ax = plt.subplots(figsize=(30, 20))
sns.heatmap(df.corr(), annot=True, linewidths=.3)
plt.show()
Enter fullscreen mode Exit fullscreen mode

Matriz de Correlação
Percebe-se uma correlação muito baixa entre as variáveis nesse dataset em questão.


13 - Apresentando gráficos de densidade para as variáveis Amount e Time:

df['Amount'].plot(kind = 'density')

print(df['Time'].plot(kind = 'density'))
Enter fullscreen mode Exit fullscreen mode
  • Gráfico de densidade para a variável Amount:
    Gráfico de densidade para a variável Amount

  • Gráfico de densidade para a variável Time:
    Gráfico de densidade para a variável Time


Vamos para classificação!!! Hora de testar o desempenho dos algoritmos.


14 - Preparando os dados para classificação:

X = test.drop('Class', axis=1)
y = test['Class']

#Balanceando os dados 
nm = NearMiss()
X_res, y_res = nm.fit_resample(X,y)

X_train, X_validation, y_train, y_validation = train_test_split(X_res,y_res)
Enter fullscreen mode Exit fullscreen mode

15 - Treinando os classificadores:

classifiers = [
    ["Logistic Regr.", LogisticRegression(max_iter=1000)],
    ["Decision Tree ", DecisionTreeClassifier(random_state=10)],
    ["Gaussian NB   ", GaussianNB()],
    ["XG Boost      ", XGBClassifier(n_estimators = 100, learning_rate = 0.05)]
]

for alg in classifiers:
  alg[1].fit(X_train, y_train)
  Y_pred = alg[1].predict(X_validation)
  report = classification_report(y_validation, Y_pred)
  print("{} - Report: \n{}".format(alg[0], report))
Enter fullscreen mode Exit fullscreen mode
  • Resultado dos algoritmos:

Resultado dos algoritmos


Considerações sobre os resultados:
Em uma primeira análise sem balancear os dados o XG Boost apresentou os melhores resultados em relação aos demais. Porém agora balanceando os dados com a biblioteca NearMiss todos os 4 algoritmos testados obtiveram resultados melhores e o Gaussian NB foi o melhor que o Xg Boost.


Segue o link do colab com o código completo: https://colab.research.google.com/drive/14gC9gg678_qgOwf0PtIItvDXOu_wVrF7?usp=sharing


No Colab existe um exemplo adicional demostrando graficamente como ficaria estruturada a árvore de decisão para os dados balanceados e não balanceados.


Feedbacks são bem-vindos. Obrigado e até mais!!!

Top comments (0)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.