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)

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.