top of page

Modelos para Detecção de Fraudes em Cartões de Crédito

  • Foto do escritor: Vinicius Goia
    Vinicius Goia
  • 6 de set. de 2023
  • 9 min de leitura

Atualizado: 13 de set. de 2023


Se você está com pressa!!!


Com todas as facilidades que a digitalização de processos gera, inevitavelmente o grande número de adeptos atrai caçadores de recompensas os quais querem dinheiro fácil. Fraudes em cartões de crédito é o tema central desse estudo, focado em sua detecção através de técnicas de Machine Learning. A análise de um dataset disponibilizado publicamente com informações pessoais descaracterizadas e a aplicação de modelos supervisionados, como Regressão Logística e Árvores de Decisão, gerou métricas interessantes tanto para aplicações de produção quanto para geração de insights.


Contextualizando...


Não devemos negar as grandes facilidades que o meio digital nos proporcionou e nos proporciona até hoje. Realizar compras sem sair de casa, ver notícias em tempo real, redes sociais, comunicação e por aí vai. Porém todo esse ambiente fomenta grupos criminosos à praticarem golpes que afetam tanto as instituições como as pessoas comuns.

Segundo o Estadão, um levantamento feito pela Serasa Experian mostrou que, em maio de 2021, um total de 331,2 mil brasileiros foram vítimas de algum tipo de fraude, sendo que 53,3% se concentraram em contas bancárias ou em cartões de crédito (ou mais de 176 mil ocorrências).


E o problema parece ser mais grave no Brasil. Em um estudo de fevereiro de 2022, a gigante americana IBM revelou que 31% dos brasileiros afirmaram ter sofrido algum tipo de golpe relacionado a cartões de crédito ao longo do ano anterior. Na Alemanha, por exemplo, esse número foi de 7% e nos Estados Unidos, de 18%.


As fraudes bancárias são apenas uma ramificação das áreas que golpistas podem atuar, conforme figura abaixo. Segundo Dornadula & Geetha (2019), fraudadores sempre tentam fazer com que as transações fraudulentas se pareçam legítimas, o que dificulta muito a sua percepção.




Gigantes da tecnologia, como a Amazon, disponibilizam soluções em Machine Learning para prevenção dessas fraudes, reduzindo as perdas de receita, evitando danos à marca e fornecendo experiências online sem atritos ao cliente enquanto se adaptam aos padrões de ameaças em constante mudança. De acordo com Domashova & Zabelina (2021), empresas como IBM, FICO E SAS também lideram em disponibilização de sistemas antifraude.


Aliás, Machine Learning nada mais é do que um conjunto de algoritmos que têm a capacidade de aprender algo a partir de dados históricos. De certa forma, adquirem experiência com os dados e realizam certa tarefa pré-definida, sem a necessidade de uma nova programação.


Obs: Esse artigo foi baseado em um notebook criado no Google Colab. As saídas dos comandos em Python referentes à textos e tabelas não serão exibidos. Apenas gráficos, vídeos e outras imagens serão mostradas.


Sobre os Dados


O dataset à ser estudado aqui está disponível no Kaggle para download. Trata-se de um dataset que contém as transações de cartão de crédito feitas por europeus em setembro de 2013. Foi coletado e analisado durante uma pesquisa de colaboração do grupo Worldline and Machine Learning da UBL (Universitá Libre de Bruxelles) para detecção de fraudes.


Nele encontram-se apenas variáveis numéricas resultantes da aplicação do PCA. Principal Component Analysis, segundo Casey Cheng, é uma técnica que transforma conjuntos grandes de dados em dimensões menores sem muita perda de informação. É como se diminuísse a variação dos dados em uma escala menor.


Outra particularidade do dataset é que, devido à questões de confidencialidade, as features foram descaracterizadas, sendo as colunas apresentadas como V1, V2, ... V28. Apenas as colunas Time e Amount se mantiveram originais.


Dicionário de Variáveis


Sendo assim, as únicas variáveis disponíveis são:

  • Time: tempo, em segundos, entre cada transação com relação a primeira transação do dataset;

  • Amount: valor da transação;

  • Class: variável que define o tipo de transação. 1 para fraudulenta e 0 para normal.

Para a utilização dos dados, primeiramente importou-se as bibliotecas necessárias. Os dados foram disponibilizados neste link para facilitar a manipulação.


Visualizou-se também as primeiras entradas para uma ideia geral do dataset.

# Importar as bibliotecas necessárias
import pandas as pd

# Leitura do arquivo .csv em um dataframe
data_bank = pd.read_csv ("https://www.dropbox.com/s/b44o3t3ehmnx2b7/creditcard.csv?dl=1")

# Visualização das primeiras entradas
data_bank.head()

Análise Exploratória


O primeiro contato


É de extrema importância verificarmos nesse primeiro contato o que o dataset nos informa. Iremos utilizar duas funções que mostram informações gerais do conjunto: info() e describe().

# Obtendo descrição das variáveis
data_bank.info()

Observa-se que a maioria dos valores são floats e apenas uma coluna possui dados inteiros. Outro ponto é que não há valores ausentes. Um bom sinal!

# Verificação da porcentagem de dados ausentes
data_bank.isnull().sum() / data_bank.shape[0]
# Obtendo resumo dos atributos numéricos
data_bank.describe()

Com 284807 transações, tem-se apenas 492 lançamentos classificados como fraude, segundo a própria descrição do dataset no site. Vamos verificar esses valores.

# Contagem das classificações
data_bank.Class.value_counts()
# Importação de bibliotecas necessárias
import matplotlib.pyplot as plt
import seaborn as sns

# Configuração do estilo de plotagem
sns.set_style('dark')
# Configuração para plotagem das frequências de fraudes
fig, ax = plt.subplots()

data_bank.Class.value_counts().plot(kind='bar', ax=ax)

ax.set_title ("Distribuição das Classes")

plt.show()


# Verificação da porcentagem de fraudes
perc = (data_bank.Class.value_counts()[1]/data_bank.shape[0])*100

print("A porcentagem de transações fraudulentas no dataset é de {0:4.3f}%".format(perc,))

Com isso, observa-se que os dados dessas classificações estão bastante desbalanceados. Dessa maneira, para aplicação de Machine Learning, teremos que balancear esses dados através de técnicas especificas, as quais veremos mais adiante. Vamos verificar agora em qual faixa de valores se encontram as transações fraudulentas.

# Obtendo resumo dos atributos numéricos para as transações fraudulentas
data_bank.Amount.loc[data_bank.Class==1].describe()
# Configurações para plotagem de boxplot
fig, ax = plt.subplots(figsize=(6,10))

sns.boxplot(data_bank.Class,data_bank.Amount,showmeans=True, ax=ax)
plt.ylim((-20, 400))
plt.xticks([0, 1], ['Normal', 'Fraude'])

plt.tight_layout()
plt.show()


Os boxplots indicam diversos valores outliers. Isso sugere que provavelmente essa coluna não foi padronizada como as outras. Tal fato pode prejudicar as predições realizadas pelos modelos de Machine Learning. Portanto, iremos padronizar as colunas Time e Amount em um novo dataset. Mas antes, vamos verificar em quais valores as fraudes são frequentes.

# Plotagem de histograma para visualização de frequência de fraudes
data_bank.Amount.loc[data_bank.Class==1].hist()

Para este dataset, observa-se que a maioria das transação fraudulentas são realizadas com valores teoricamente baixos.


Veremos agora o valor total dessas transações.

# Verificação do valor total das transações fraudulentas
total_fraud = data_bank.Amount.loc[data_bank.Class==1].sum()

print("O total de prejuízo gerado aos bancos foi de {}".format(total_fraud))

Realizaremos a plotagem da frequência dos movimentos fraudulentos com relação ao tempo para verificação de algum insight.

# Configurações para plotagem de frequencia de fraudes com relação ao tempo
fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(20,10))

num_bins = 50

ax[0].hist(data_bank.Time[data_bank.Class==0], bins=num_bins)
ax[0].set_title('Normal')

ax[1].hist(data_bank.Time[data_bank.Class==1], bins=num_bins)
ax[1].set_title('Fraud')

plt.xlabel('Tempo (segundos)')
plt.ylabel('Transações')
plt.tight_layout()


Como observado, nenhum insight significativo foi gerado com os gráficos. Antes de iniciarmos nossas manipulações, iremos dividir o conjunto de dados em Treino e Teste, seguindo os passos abaixo:

# Dimensões do conjunto original
print("Dimensões do Conjunto Original: ", data_bank.shape)

# Criando o conjunto de teste
test = data_bank.sample(frac=0.15, random_state=0)

# Drop das linhas de teste
data_bank = data_bank.drop(test.index)

# Verificação do conjunto
print("Dimensões do Conjunto de Teste: ", test.shape)
print("Dimensões do Conjunto de Treino: ", data_bank.shape)

Preparando o Terreno


Padronização dos dados existentes


A partir de agora, iremos realizar as preparações dos dados para que nossos modelos de Machine Learning possam performar de maneira adequada.


Como comentado anteriormente, padronizaremos os valores das colunas que se mantiveram originais ao dataset.

# Importação de biblioteca necessária
from sklearn.preprocessing import StandardScaler

# Cópia do dataset original
data_mach = data_bank.copy()

# Padronização das colunas Time e Amount em novas colunas
std_scaller = StandardScaler()
data_mach['std_amount'] = std_scaller.fit_transform(data_mach.Amount.values.reshape(-1,1))
data_mach['std_time'] = std_scaller.fit_transform(data_mach.Time.values.reshape(-1,1))

# Exclusão das colunas existentes
data_mach.drop(['Time','Amount'], axis=1, inplace=True)

# Visualização das primeiras entradas
data_mach.head()

Divisão dos dados de treino e validação


Dividiu-se os dados para a realização dos procedimentos de teste e validação. Como nossos modelos de Machine Learning possuirão características de sistemas supervisionados, iremos também dividir os dados em conjunto de features e conjunto de target.

# Importação de bibliotecas necessárias
from sklearn.model_selection import train_test_split

# Divisão do dataset em features e target
X = data_mach.drop('Class', axis=1)
y = data_mach.Class

# Divisão dos dados em treino e validação
X_train, X_val, y_train, y_val = train_test_split (X, y)

print(
    "Tamanho do conjunto X: {}\n".format(X.shape),
    "Tamanho do conjunto y: {}\n".format(y.shape),
    "Tamanho do conjunto X_train: {}\n".format(X_train.shape),
    "Tamanho do conjunto X_val: {}\n".format(X_val.shape),
    "Tamanho do conjunto y_train: {}\n".format(y_train.shape),
    "Tamanho do conjunto y_val: {}\n".format(y_val.shape)

Balanceamento dos dados de Target


Dados desbalanceados indicam entropia baixa. Neste caso, com 0,173% de dados demarcados como fraude, temos praticamente um conjunto puro, o que dificulta o entendimento do algoritmo de classificação. Para a resolução deste problema, iremos utilizar o método Random Under-sampling (RUS), que, segundo Moreira (2022), descarta um subconjunto aleatório da classe majoritária, preservando as características da classe minoritária, favorecendo grandes volumes de dados.

# Importação de bibliotecas necessárias
from imblearn.under_sampling import RandomUnderSampler

# Usar técnica under-sampling
rus = RandomUnderSampler()
X_rus, y_rus = rus.fit_resample(X_train, y_train)

# Ver o balanceamento das classes
print(pd.Series(y_rus).value_counts())

# Plotar a nova distribuição de classes
fig, ax = plt.subplots()

sns.countplot(y_rus, ax=ax)

ax.set_title ("Distribuição das Classes")

plt.show()


Observa-se claramente no gráfico que os dados foram balanceados.


Abaixo comparamos a matriz de correlação antes e depois do processo. Sem dúvidas os dados passaram a se correlacionar melhor após o balanceamento.

# Plotagem de matriz de correlação
corr = X_train.corr()
corr_rus = pd.DataFrame(X_rus).corr()

fig, ax = plt.subplots(nrows=1, ncols=2, figsize = (18,8))
fig.suptitle('Matriz de Correlação')

sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns,
            linewidths=.1, cmap="coolwarm", ax=ax[0])
ax[0].set_title('Desbalanceado')

sns.heatmap(corr_rus, xticklabels=corr.columns, yticklabels=corr.columns,
            linewidths=.1, cmap="coolwarm", ax=ax[1])
ax[1].set_title('Balanceado')

plt.show()


Modelos de Machine Learning


De acordo com Moreira (2022), as técnicas de aprendizado supervisionado mais comuns utilizadas em detecção de fraudes são as variantes de árvore de decisão, redes neurais, regressão linear, regressão logística, KNN e Naive Bayes.


Para este estudo iremos comparar o desempenho das técnicas de Regressão Logística e Árvores de Decisão.



Na figura acima podemos verificar o processo de implementação de Machine Learning em um sistema financeiro.


Regressão Logística


Aqui iremos descrever em forma de código os passos para construção do modelo.

# Importação de biliotecas necessárias
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_auc_score, roc_curve, accuracy_score
# Instanciamento e escolha dos hiperparâmetros
model1 = LogisticRegression()

# Treinamento do Modelo
model1.fit(X_rus, y_rus)

# Previsões em cima dos dados de teste
y_pred = model1.predict(X_val)
y_proba = model1.predict_proba(X_val)

# Plote de matrix de confusão
mat = confusion_matrix (y_val, y_pred, normalize='true')
sns.heatmap (mat, square=True, annot=True)

# imprimir relatório de classificação
print("Relatório de Classificação:\n", classification_report(y_val, y_pred, digits=4))

# imprimir a acurácia do modelo
print("Acurácia: {:.4f}\n".format(accuracy_score(y_val, y_pred)))

# imprimir a área sob da curva
print("AUC: {:.4f}\n".format(roc_auc_score(y_val, y_pred)))


Previsões com o conjunto Teste


No começo do projeto, realizamos um split nos dados para que tivéssemos 3 conjuntos: Um de treino, um de validação e um de teste.


Agora que já exploramos e preparamos os dados, instanciamos o modelo e fizemos previsões no conjunto de validação, é hora de descobrirmos o potencial desse simples modelo com os dados de teste.


O que faremos é apenas utilizar o modelo que treinamos com um novo conjunto. Mas, para que os resultados sejam justos, precisamos fazer com que os novos dados estejam nas mesmas condições daqueles que o nosso modelo espera.


Nesse caso, precisamos padronizar as colunas Time e Amount. Não podemos balancear os dados pois haveria perda. Nosso modelo precisa ser tratado mas precisamos fazer previsões em todas as linhas que ele receber.

# Padronizar as colunas Time e Amount - Teste
test_clean = test.copy()

std_scaler = StandardScaler()
test_clean['std_amount'] = std_scaler.fit_transform(test_clean['Amount'].values.reshape(-1, 1))
test_clean['std_time'] = std_scaler.fit_transform(test_clean['Time'].values.reshape(-1, 1))

test_clean.drop(['Time', 'Amount'], axis=1, inplace=True)

# ver as primeiras entradas
test_clean.head()
# separar variáveis entre X e y
X_test = test_clean.drop('Class', axis=1)
y_test = test['Class']

# fazer as previsões em cima dos dados de teste
y_pred = model1.predict(X_test)
y_proba = model1.predict_proba(X_test)

# plotar a matrix de confusão
mat = confusion_matrix (y_test, y_pred, normalize='true')
sns.heatmap (mat, square=True, annot=True)

# imprimir relatório de classificação
print("Relatório de Classificação:\n", classification_report(y_test, y_pred, digits=4))

# imprimir a acurácia do modelo
print("Acurácia: {:.4f}\n".format(accuracy_score(y_test, y_pred)))

# imprimir a área sob da curva
print("AUC: {:.4f}\n".format(roc_auc_score(y_test, y_pred)))


Neste caso, houve um mínimo aumento nos resultados no conjunto de testes.


Árvore de Decisão


Aqui iremos descrever em forma de código os passos para construção do modelo.

# Importação de biliotecas necessárias
from sklearn.tree import DecisionTreeClassifier

# Instanciamento e escolha dos hiperparâmetros
model2 = DecisionTreeClassifier(max_depth=4, criterion="entropy")

# Treinamento do Modelo
model2.fit(X_rus, y_rus)

# Previsões em cima dos dados de teste
y_pred = model2.predict(X_val)
y_proba = model2.predict_proba(X_val)

# Plote de matrix de confusão
mat = confusion_matrix (y_val, y_pred, normalize='true')
sns.heatmap (mat, square=True, annot=True)

# imprimir relatório de classificação
print("Relatório de Classificação:\n", classification_report(y_val, y_pred, digits=4))

# imprimir a acurácia do modelo
print("Acurácia: {:.4f}\n".format(accuracy_score(y_val, y_pred)))

# imprimir a área sob da curva
print("AUC: {:.4f}\n".format(roc_auc_score(y_val, y_pred)))


Previsões com o conjunto Teste

# fazer as previsões em cima dos dados de teste
y_pred = model2.predict(X_test)
y_proba = model2.predict_proba(X_test)

# plotar a matrix de confusão
mat = confusion_matrix (y_test, y_pred, normalize='true')
sns.heatmap (mat, square=True, annot=True)

# imprimir relatório de classificação
print("Relatório de Classificação:\n", classification_report(y_test, y_pred, digits=4))

# imprimir a acurácia do modelo
print("Acurácia: {:.4f}\n".format(accuracy_score(y_test, y_pred)))

# imprimir a área sob da curva
print("AUC: {:.4f}\n".format(roc_auc_score(y_test, y_pred)))


Neste caso, houve uma mínima diminuição nos resultados no conjunto de testes.


Conclusão


A construção de modelos de Machine Learning exige do cientista de dados o entendimento mínimo do business para gerar valor ao cliente. Definir bem as métricas de avaliação também é um ponto importante. Em nosso estudo, observamos que o modelo de Regressão Logística se sobressaiu ao modelo de Árvores de Decisão. Na detecção de fraudes é muito importante analisarmos de forma crítica não apenas os valores falsos negativos, mas também os falsos positivos, que geram alertas e podem fragilizar a relação entre instituição e cliente.


Percebemos também que o dataset, apesar de estar bem estruturado, sem valores ausentes, demandou métodos para a adequação de dados para aplicação nos algoritmos. Isso evidencia que o profissional deve não apenas aplicar técnicas decoradas, mas analisar cuidadosamente e explorar tudo o que for possível.


Para otimizar ainda mais os modelos aqui apresentados, outras técnicas de balanceamento poderiam ser utilizadas, bem como outros algoritmos de Machine Learning supervisionados.


Referências

  • ​​Domashova, J., & Zabelina, O. (2021). Detection of fraudulent transactions using SAS Viya machine learning algorithms. Procedia Computer Science, 190, 204–209. https://doi.org/10.1016/j.procs.2021.06.025

  • Dornadula, V. N., & Geetha, S. (2019). Credit Card Fraud Detection using Machine Learning Algorithms. Procedia Computer Science, 165, 631–641. https://doi.org/10.1016/j.procs.2020.01.057

  • ​Moreira, M. Â. L., Junior, C. de S. R., Silva, D. F. de L., de Castro Junior, M. A. P., Costa, I. P. de A., Gomes, C. F. S., & dos Santos, M. (2022). Exploratory analysis and implementation of machine learning techniques for predictive assessment of fraud in banking systems. Procedia Computer Science, 214, 117–124. https://doi.org/10.1016/j.procs.2022.11.156

Comments


©2023 by Natural Engines. Flowing Knowledge.

bottom of page