Desenvolvimento de modelo de Machine Learning para detecção de fraudes em cartões.
Autor
Luiz Felipe P. Figueiredo
Data de Publicação
03/12/2023
Objetivo
Este projeto tem como objetivo, desenvolver um modelo de aprendizado de maquina a fim de detectar transações fraudulentas envolvendo cartões de crédito. Isso será alcançado por meio da exploração e aplicação de vários algoritmos de aprendizado de máquina, seguidos pela avaliação e comparação de métricas de desempenho com o objetivo de selecionar o modelo mais eficaz.
Descrição dos Dados
Os dados que serão utilizado neste projeto, foram retirados do kaggle. Trata-se de uma base de dados que contém transações feitas por cartões de créditos europeus em setembro de 2013. Além disso a base de dados contém 28 variáveis ou colunas que foram anonimizadas a fim de proteger a sigilosidade dos dados em questão.
Descrição das variáveis
Time - Segundos que se passaram entre cada transação e a primeira transação no dataset;
V1 a V28 - Variáveis anonimizadas devido a confidencialidade dos dados, essa variáveis foram transformadas utilizando Análise de Componentes Principais;
Amount - Valor de cada transação;
Class - Variável resposta, onde 1 equivale a uma compra fraudulenta e 0 com não fraudulenta.
Código
# bibliotecas utilizadasimport numpy as npimport pandas as pdimport plotly.io as piopio.renderers.default ="notebook_connected"import plotly.colors as colorsimport plotly.express as pximport plotly.graph_objects as gofrom sklearn.preprocessing import RobustScaler
Verificação dos Dados
Código
# preview do datasetdf = pd.read_csv("C:/Users/luisf/Desktop/DATACAMP/Portfolio/datasets/credit_card_fraud/creditcard.csv")df.head()
Time
V1
V2
V3
V4
V5
V6
V7
V8
V9
...
V21
V22
V23
V24
V25
V26
V27
V28
Amount
Class
0
0.0
-1.359807
-0.072781
2.536347
1.378155
-0.338321
0.462388
0.239599
0.098698
0.363787
...
-0.018307
0.277838
-0.110474
0.066928
0.128539
-0.189115
0.133558
-0.021053
149.62
0
1
0.0
1.191857
0.266151
0.166480
0.448154
0.060018
-0.082361
-0.078803
0.085102
-0.255425
...
-0.225775
-0.638672
0.101288
-0.339846
0.167170
0.125895
-0.008983
0.014724
2.69
0
2
1.0
-1.358354
-1.340163
1.773209
0.379780
-0.503198
1.800499
0.791461
0.247676
-1.514654
...
0.247998
0.771679
0.909412
-0.689281
-0.327642
-0.139097
-0.055353
-0.059752
378.66
0
3
1.0
-0.966272
-0.185226
1.792993
-0.863291
-0.010309
1.247203
0.237609
0.377436
-1.387024
...
-0.108300
0.005274
-0.190321
-1.175575
0.647376
-0.221929
0.062723
0.061458
123.50
0
4
2.0
-1.158233
0.877737
1.548718
0.403034
-0.407193
0.095921
0.592941
-0.270533
0.817739
...
-0.009431
0.798278
-0.137458
0.141267
-0.206010
0.502292
0.219422
0.215153
69.99
0
5 rows × 31 columns
Verificação de Valores Faltantes e dados desbalanceados.
Código
# Verificação de valores faltantesn_valores_faltantes =int(df[df.columns[df.isnull().any()]].isnull().sum().sum())print(f'Existe um total de {n_valores_faltantes} valores faltantes nesta base de dados')
Existe um total de 0 valores faltantes nesta base de dados
Acima, pode-se se verificar que não existem valores faltantes neste dataset, além disso, estes dados são extremamente desbalanceados, a variável resposta Class contem 284.315 compras legitimas e somente 492 compras fraudulentas, deste modo, será necessário implementar técnicas para tratar este desbalanceamento, pois, implementar um modelo de aprendizado de maquina seria um problema e com certeza geraria um modelo com desempenho ruim.
Tratamento De Dados
Como as variáveis Time e Amount não foram dimensionadas, é preciso realizar a transformação dessas variáveis, utilizando o sklearn.preprocessing.RobustScaler já que esse “scaler” é robusto para outliers [1].
Código
# Dimensionamento das variáveis Time e Amount#robust_scaler = RobustScaler()#df['Dim_Amount'] = robust_scaler.fit_transform(df['Amount'].values.reshape(-1, 1))#df['Dim_Time'] = robust_scaler.fit_transform(df['Time'].values.reshape(-1, 1))#df.drop(['Time','Amount'], axis=1, inplace=True)
Código
# Supondo que 'df' seja o seu DataFrameholder = pd.DataFrame()# Atribuir as colunas 'Amount', 'Time' e 'Class' a variáveis separadasholder['Amount'] = df['Amount']holder['Time'] = df['Time']holder['Class'] = df['Class']df= df.drop(['Time', 'Amount', 'Class'], axis=1)
Código
holder
Amount
Time
Class
0
149.62
0.0
0
1
2.69
0.0
0
2
378.66
1.0
0
3
123.50
1.0
0
4
69.99
2.0
0
...
...
...
...
284802
0.77
172786.0
0
284803
24.79
172787.0
0
284804
67.88
172788.0
0
284805
10.00
172788.0
0
284806
217.00
172792.0
0
284807 rows × 3 columns
Tratando Dados Desbalanceados
Uma técnica que é amplamente utilizada é a Synthetic Minority Over-sampling Technique também conhecida como SMOTE, trata-se de uma técnica que gera dados sintéticos com base na classe de minoria, neste projeto, denotada como fraude ou Class = 0, a fim de balancear a distribuição da variável em questão. Esta técnica atua criando novas instâncias sintéticas que são combinações das instâncias existentes da classe minoritária da variável resposta [2,3].
Outra técnica que pode ser utilizada, é a Fuzzy C-Means
Código
data=dfc=5import skfuzzy as fuzzcntr, u, u0, d, jm, p, fpc= fuzz.cmeans(data.T, c, m=2, error=0.005, maxiter=1000)
def extrai_dataset_balanceado(df = pd.DataFrame(), ratios=tuple): temp_df = pd.DataFrame()# entro no primeiro clusterfor cluster inrange(0, 5): center =round(len(df[df['Cluster']==cluster])/2) # encontro o index do meioif df[df['Cluster']==cluster]['Class'].iloc[center] ==0: # se o index for uma fraude temp_df = pd.concat([temp_df, df[df['Cluster'] == cluster].iloc[center:center+1]])else:for i inrange(0, center]):if df[df['Cluster']==cluster]['Class'].iloc[center - i] ==0: temp_df = pd.concat([temp_df, df[df['Cluster'] == cluster].iloc[center:center+1-i]])for j inrange(df[df['Cluster']==cluster]):if df[df['Cluster']==cluster]['Class'].iloc[center + i] ==0:
# Reestruturando os dados para o formato "long" para usar com Plotly Expressteste_melted = teste.melt(id_vars=["ANO ", "LOJA"], var_name="Mês", value_name="Vendas")# Criando o gráfico de linhas com Plotly Expressfig = px.line(teste_melted[teste_melted['ANO ']==2018], x="Mês", y="Vendas", color="LOJA", title='Vendas Mensais por Loja', markers=True)# Mostrando o gráficofig.show()