Sari la conținutul principal

Data Science în banking: detectarea fraudelor

Află cum este implementată data science în sectorul bancar, explorând unul dintre cele mai comune cazuri de utilizare: detectarea fraudelor.
Actualizat 31 aug. 2026  · 11 min. citire

Explorează cu AI

ChatGPTClaudePerplexity

Ilustrație concept Fintech

Bankingul este unul dintre acele domenii norocoase în care, istoric, s-au colectat multe date structurate și, de asemenea, printre primele în care au fost aplicate tehnologiile de data science.

Cum este folosită data science în banking? În prezent, datele au devenit cel mai valoros activ în această sferă. Data science este o cerință necesară pentru ca băncile să țină pasul cu rivalii, să atragă mai mulți clienți, să crească loialitatea celor existenți, să ia decizii mai eficiente bazate pe date, să-și potențeze afacerea, să-și îmbunătățească eficiența operațională, să îmbunătățească serviciile/produsele existente și să introducă unele noi, să consolideze securitatea și, ca rezultat al tuturor acestor acțiuni, să obțină venituri mai mari. Nu e de mirare că majoritatea cererii de joburi în data science vine din banking.

Data science le permite băncilor să îndeplinească cu succes numeroase sarcini, inclusiv: 

  • analiza riscului investițional
  • predicția valorii pe viață a clientului (CLV)
  • segmentarea clienților
  • predicția ratei de churn
  • marketing personalizat
  • analiza sentimentului clienților
  • asistenți virtuali și chatboți

Mai jos, vom analiza mai îndeaproape unul dintre cele mai comune cazuri de utilizare a data science în banking.

Caz de utilizare data science în banking: detectarea fraudelor 

Activitățile frauduloase reprezintă o problemă dificilă nu doar în banking, ci și în multe alte domenii, precum guvern, asigurări, sector public, vânzări și sănătate. Orice afacere care se confruntă cu un număr mare de tranzacții online are un risc semnificativ de fraudă. Infracțiunile financiare pot lua diverse forme, inclusiv tranzacții frauduloase cu cardul de credit, cecuri bancare falsificate, evaziune fiscală, spălare de bani, atacuri cibernetice, furt de conturi de client, identități sintetice, aplicații false și înșelătorii.

Detectarea fraudelor este un set de măsuri proactive întreprinse pentru a identifica și preveni activitățile frauduloase și pierderile financiare. Principalele sale tehnici analitice pot fi împărțite în două grupuri:

  • Statistice: calculul parametrilor statistici, regresie, distribuții de probabilitate, potrivire de date
  • Inteligență artificială (AI): data mining, machine learning, deep learning

Machine learning reprezintă un pilon esențial pentru detectarea fraudelor. Instrumentele sale oferă două abordări:

  • Metode supravegheate: cei mai apropiați k vecini, regresie logistică, mașini cu vectori de susținere, arbore de decizie, pădure aleatoare, analiză de serii temporale, rețele neuronale etc.
  • Metode nesupravegheate: analiză de clustere, analiză de legături, hărți autoorganizatoare, analiză a componentelor principale, recunoașterea anomaliilor etc.

Nu există un algoritm universal și fiabil de machine learning pentru detectarea fraudelor. În schimb, în cazurile reale de utilizare în data science, se testează de obicei mai multe tehnici sau combinații ale acestora, se calculează acuratețea predictivă a modelului și se selectează abordarea optimă.

Provocarea principală pentru sistemele de detectare a fraudelor este să se adapteze rapid la modelele de fraudă și tacticile fraudatorilor, aflate în continuă schimbare, și să descopere prompt scheme noi și tot mai elaborate. Cazurile de fraudă sunt întotdeauna o minoritate și sunt bine ascunse printre tranzacțiile reale.

Pregătirea setului de date

Hai să explorăm o implementare de machine learning pentru detectarea fraudelor pe cardul de credit folosind limbajul de programare Python. Vom lucra pe setul de date creditcard_data, care este un eșantion modificat dintr-un set de date Kaggle despre Detectarea fraudelor cu cardul de credit. Datele originale reprezintă tranzacțiile efectuate pe carduri deținute de titulari europeni pe parcursul a două zile din septembrie 2013.

Hai să importăm datele și să aruncăm o privire rapidă:

import pandas as pd

creditcard_data = pd.read_csv('creditcard_data.csv', index_col=0)
print(creditcard_data.info())
print('\n')
pd.options.display.max_columns = len(creditcard_data)
print(creditcard_data.head(3))
<class 'pandas.core.frame.DataFrame'>
Int64Index: 5050 entries, 0 to 5049
Data columns (total 30 columns):
#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
0   V1      5050 non-null   float64
1   V2      5050 non-null   float64
2   V3      5050 non-null   float64
3   V4      5050 non-null   float64
4   V5      5050 non-null   float64
5   V6      5050 non-null   float64
6   V7      5050 non-null   float64
7   V8      5050 non-null   float64
8   V9      5050 non-null   float64
9   V10     5050 non-null   float64
10  V11     5050 non-null   float64
11  V12     5050 non-null   float64
12  V13     5050 non-null   float64
13  V14     5050 non-null   float64
14  V15     5050 non-null   float64
15  V16     5050 non-null   float64
16  V17     5050 non-null   float64
17  V18     5050 non-null   float64
18  V19     5050 non-null   float64
19  V20     5050 non-null   float64
20  V21     5050 non-null   float64
21  V22     5050 non-null   float64
22  V23     5050 non-null   float64
23  V24     5050 non-null   float64
24  V25     5050 non-null   float64
25  V26     5050 non-null   float64
26  V27     5050 non-null   float64
27  V28     5050 non-null   float64
28  Amount  5050 non-null   float64
29  Class   5050 non-null   int64 
dtypes: float64(29), int64(1)
memory usage: 1.2 MB


        V1        V2        V3        V4        V5        V6        V7  \
0  1.725265 -1.337256 -1.012687 -0.361656 -1.431611 -1.098681 -0.842274  
1  0.683254 -1.681875  0.533349 -0.326064 -1.455603  0.101832 -0.520590  
2  1.067973 -0.656667  1.029738  0.253899 -1.172715  0.073232 -0.745771  

        V8        V9       V10       V11       V12       V13       V14  \
0 -0.026594 -0.032409  0.215113  1.618952 -0.654046 -1.442665 -1.546538  
1  0.114036 -0.601760  0.444011  1.521570  0.499202 -0.127849 -0.237253  
2  0.249803  1.383057 -0.483771 -0.782780  0.005242 -1.273288 -0.269260  

        V15       V16       V17       V18       V19       V20       V21  \
0 -0.230008  1.785539  1.419793  0.071666  0.233031  0.275911  0.414524  
1 -0.752351  0.667190  0.724785 -1.736615  0.702088  0.638186  0.116898  
2  0.091287 -0.347973  0.495328 -0.925949  0.099138 -0.083859 -0.189315  

        V22       V23       V24       V25       V26       V27       V28  \
0  0.793434  0.028887  0.419421 -0.367529 -0.155634 -0.015768  0.010790  
1 -0.304605 -0.125547  0.244848  0.069163 -0.460712 -0.017068  0.063542  
2 -0.426743  0.079539  0.129692  0.002778  0.970498 -0.035056  0.017313  

  Amount  Class 
0  189.00      0 
1  315.17      0 
2   59.98      0 

Setul de date conține următoarele variabile:

  • Variabile codificate numeric V1 până la V28, care sunt componentele principale obținute dintr-o transformare PCA. Din motive de confidențialitate, nu au fost furnizate informații de fundal despre caracteristicile originale.
  • Variabila Amount reprezintă suma tranzacției.
  • Variabila Class arată dacă tranzacția a fost fraudă (1) sau nu (0).

Prin natura lor, aparițiile de fraudă sunt, din fericire, o minoritate extremă în orice listă de tranzacții. Totuși, algoritmii de machine learning funcționează de obicei cel mai bine când clasele diferite din setul de date sunt mai mult sau mai puțin reprezentate în mod egal.  Altfel, există puține date din care să învețe. Această problemă se numește dezechilibru de clasă.

Calcularea fraudei în setul de date

Hai să calculăm procentul tranzacțiilor frauduloase din numărul total de tranzacții din setul nostru de date:

round(creditcard_data['Class'].value_counts()*100/len(creditcard_data)).convert_dtypes()
0    99
1     1
Name: Class, dtype: Int64

și să creăm un grafic pentru a vizualiza punctele de date fraudă vs. non-fraudă:

import matplotlib.pyplot as plt
import numpy as np

def prep_data(df):
    X = df.iloc[:, 1:28]
    X = np.array(X).astype(float)
    y = df.iloc[:, 29]
    y = np.array(y).astype(float)
    return X, y

def plot_data(X, y):
    plt.scatter(X[y==0, 0], X[y==0, 1], label='Class #0', alpha=0.5, linewidth=0.15)
    plt.scatter(X[y==1, 0], X[y==1, 1], label='Class #1', alpha=0.5, linewidth=0.15, c='r')
    plt.legend()
    return plt.show()

X, y = prep_data(creditcard_data)

plot_data(X, y)

Tranzacții frauduloase

Folosirea SMOTE pentru reechilibrarea datelor 

Putem confirma acum că raportul tranzacțiilor frauduloase este foarte scăzut și că avem un caz de dezechilibru de clasă. Pentru a-l remedia, ne putem reechilibra datele folosind tehnica de supra-eșantionare a minorității sintetice (SMOTE). Spre deosebire de supra-eșantionarea aleatorie, SMOTE este puțin mai sofisticată, deoarece nu creează doar copii exacte ale observațiilor. În schimb, folosește caracteristicile celor mai apropiați vecini ai cazurilor de fraudă pentru a crea eșantioane sintetice noi, destul de similare cu observațiile existente din clasa minoritară. Hai să aplicăm SMOTE pe datele noastre de card de credit:

from imblearn.over_sampling import SMOTE

method = SMOTE()
X_resampled, y_resampled = method.fit_resample(X, y)
plot_data(X_resampled, y_resampled)

Grafic SMOTE

După cum putem vedea, folosirea SMOTE ne oferă brusc mai multe observații ale clasei minoritare. Pentru a vedea și mai bine rezultatele acestei abordări, le vom compara cu datele originale:

def compare_plot(X, y, X_resampled, y_resampled, method):
    f, (ax1, ax2) = plt.subplots(1, 2)
    c0 = ax1.scatter(X[y==0, 0], X[y==0, 1], label='Class #0',alpha=0.5)
    c1 = ax1.scatter(X[y==1, 0], X[y==1, 1], label='Class #1',alpha=0.5, c='r')
    ax1.set_title('Original set')
    ax2.scatter(X_resampled[y_resampled==0, 0], X_resampled[y_resampled==0, 1], label='Class #0', alpha=.5)
    ax2.scatter(X_resampled[y_resampled==1, 0], X_resampled[y_resampled==1, 1], label='Class #1', alpha=.5,c='r')
    ax2.set_title(method)
    plt.figlegend((c0, c1), ('Class #0', 'Class #1'), loc='lower center', ncol=2, labelspacing=0.)
    plt.tight_layout(pad=3)
    return plt.show()

print(f'Original set:\n'
      f'{pd.value_counts(pd.Series(y))}\n\n'
      f'SMOTE:\n'
      f'{pd.value_counts(pd.Series(y_resampled))}\n')

compare_plot(X, y, X_resampled, y_resampled, method='SMOTE')
Original set:
0.0    5000
1.0      50
dtype: int64


SMOTE:
0.0    5000
1.0    5000
dtype: int64

Grafic metoda Smote

Prin urmare, metoda SMOTE ne-a echilibrat complet datele, iar clasa minoritară este acum egală ca mărime cu clasa majoritară.

Vom reveni în curând la aplicarea practică a metodei SMOTE, dar, deocamdată, să ne întoarcem la datele originale și să încercăm să detectăm cazurile de fraudă. Urmând o abordare „old-school”, trebuie să creăm câteva reguli pentru a prinde frauda. Astfel de reguli pot viza, de exemplu, locații neobișnuite ale tranzacțiilor sau tranzacții suspect de frecvente. Ideea este să definim valori prag bazate pe statistici comune, adesea pe valorile medii ale observațiilor, și să folosim aceste praguri pe caracteristicile noastre pentru a detecta frauda.

print(creditcard_data.groupby('Class').mean().round(3)[['V1', 'V3']])
        V1     V3
Class             
0      0.035  0.037
1     -4.985 -7.294

În cazul nostru particular, hai să aplicăm următoarele condiții: V1 < -3 și V3 < -5. Apoi, pentru a estima performanța acestei abordări, vom compara cazurile de fraudă semnalate cu cele reale:

creditcard_data['flag_as_fraud'] = np.where(np.logical_and(creditcard_data['V1']<-3, creditcard_data['V3']<-5), 1, 0)
print(pd.crosstab(creditcard_data['Class'], creditcard_data['flag_as_fraud'], rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud     0   1
Actual Fraud          
0              4984  16
1                28  22

Aplicarea regresiei logistice 

Am detectat 22 din 50 de cazuri de fraudă, dar nu putem detecta celelalte 28 și am obținut 16 alarme false. Să vedem dacă folosirea tehnicilor de machine learning poate depăși aceste rezultate.

Vom implementa acum un algoritm simplu de clasificare prin regresie logistică pe datele noastre de card de credit pentru a identifica aparițiile frauduloase și apoi vom vizualiza rezultatele într-o matrice de confuzie:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

lr = LogisticRegression()
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud   0.0  1.0
Actual Fraud           
0.0            1504    1
1.0             1      9

Este important de menționat că aici avem mai puține observații de privit în matricea de confuzie pentru că folosim doar setul de test pentru a calcula rezultatele modelului, adică doar 30% din întregul set de date.

Am prins un procent mai mare de cazuri de fraudă: 90% (9 din 10), comparativ cu rezultatul anterior de 44% (22 din 50). Am avut, de asemenea, mult mai puține alarme false decât înainte, deci este o îmbunătățire.

Hai să revenim acum la problema dezechilibrului de clasă discutată mai devreme și să explorăm dacă putem îmbunătăți și mai mult rezultatele de predicție combinând modelul de regresie logistică cu metoda de re-eșantionare SMOTE. Pentru a face asta eficient și dintr-o singură mișcare, trebuie să definim un pipeline și să-l rulăm pe datele noastre:

from imblearn.pipeline import Pipeline

# Defining which resampling method and which ML model to use in the pipeline
resampling = SMOTE()
lr = LogisticRegression()

pipeline = Pipeline([('SMOTE', resampling), ('Logistic Regression', lr)])
pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud   0.0  1.0
Actual Fraud           
0.0            1496    9
1.0               1    9

După cum putem vedea, în cazul nostru SMOTE nu a adus nicio îmbunătățire: tot am prins 90% din aparițiile de fraudă și, în plus, avem un număr ușor mai mare de alarme false. Explicația aici este că re-eșantionarea nu duce neapărat la rezultate mai bune în toate cazurile. Când cazurile de fraudă sunt foarte împrăștiate în date, cei mai apropiați vecini ai lor nu sunt neapărat tot cazuri de fraudă, astfel că folosirea SMOTE poate introduce un bias.

Concluzie 

Ca posibil pas înainte, pentru a crește acuratețea modelului de regresie logistică, putem regla anumiți parametri ai algoritmului. Se poate lua în considerare și validarea încrucișată k-fold în loc să împărțim setul de date doar în două părți. În final, putem încerca și alți algoritmi de machine learning (de exemplu, arbore de decizie sau pădure aleatoare) și să vedem dacă oferă rezultate mai bune. 

Dacă vrei să afli mai multe despre aspectele teoretice și tehnice ale implementării unui model de detectare a fraudelor, poți explora materialele cursului Fraud Detection in Python.

Subiecte
Data Science
Machine Learning