- Use Case Data Science di Perbankan: Mendeteksi Penipuan
- Menyiapkan Dataset
- Menghitung Penipuan dalam Dataset
- Menggunakan SMOTE untuk Menyeimbangkan Data
- Menerapkan Regresi Logistik
- Kesimpulan
Perbankan adalah salah satu bidang yang beruntung karena secara historis banyak data terstruktur dikumpulkan, dan juga menjadi salah satu yang pertama menerapkan teknologi data science.
Bagaimana data science digunakan di perbankan? Saat ini, data telah menjadi aset paling berharga di ranah ini. Data science merupakan kebutuhan bagi bank untuk tetap bersaing, menarik lebih banyak nasabah, meningkatkan loyalitas nasabah yang sudah ada, membuat keputusan berbasis data yang lebih efisien, memberdayakan bisnis, meningkatkan efisiensi operasional, memperbaiki layanan/produk yang ada dan meluncurkan yang baru, memperkuat keamanan, dan sebagai hasil dari semua tindakan ini, memperoleh lebih banyak pendapatan. Tidak mengherankan jika mayoritas permintaan pekerjaan data science berasal dari perbankan.
Data science memungkinkan industri perbankan untuk berhasil menjalankan banyak tugas, termasuk:
- analisis risiko investasi
- prediksi nilai seumur hidup pelanggan (customer lifetime value)
- segmentasi pelanggan
- prediksi churn pelanggan
- pemasaran yang dipersonalisasi
- analisis sentimen pelanggan
- asisten virtual dan chatbot
Di bawah ini, kita akan melihat lebih dekat salah satu use case data science yang paling umum di perbankan.
Use Case Data Science di Perbankan: Mendeteksi Penipuan
Aktivitas penipuan merupakan masalah menantang tidak hanya di perbankan tetapi juga di banyak bidang lain, seperti pemerintahan, asuransi, sektor publik, penjualan, dan layanan kesehatan. Setiap bisnis yang menangani jumlah transaksi online yang tinggi berisiko besar mengalami penipuan. Kejahatan keuangan dapat berbentuk berbagai macam, termasuk transaksi kartu kredit palsu, cek bank palsu, penghindaran pajak, pencucian uang, serangan siber, pencurian akun pelanggan, identitas sintetis, aplikasi palsu, dan penipuan.
Deteksi penipuan adalah serangkaian tindakan proaktif yang dilakukan untuk mengidentifikasi dan mencegah aktivitas penipuan serta kerugian finansial. Teknik analitis utamanya dapat dibagi menjadi dua kelompok:
- Statistik: perhitungan parameter statistik, regresi, distribusi probabilitas, pencocokan data
- Kecerdasan buatan (AI): penambangan data, pembelajaran mesin, pembelajaran mendalam
Pembelajaran mesin merupakan pilar penting untuk deteksi penipuan. Perangkatnya menyediakan dua pendekatan:
- Metode terawasi: k-nearest neighbors, regresi logistik, support vector machines, decision tree, random forest, analisis deret waktu, neural network, dan lain-lain.
- Metode tidak terawasi: analisis klaster, analisis keterkaitan (link analysis), self-organizing maps, analisis komponen utama, pengenalan anomali, dan lain-lain.
Tidak ada algoritme pembelajaran mesin yang bersifat universal dan andal untuk deteksi penipuan. Sebaliknya, dalam use case data science dunia nyata, beberapa teknik atau kombinasinya biasanya diuji, akurasi prediktif model dihitung, dan pendekatan optimal dipilih.
Tantangan utama bagi sistem deteksi penipuan adalah beradaptasi dengan cepat terhadap pola penipuan dan taktik pelaku yang terus berubah serta segera mengungkap skema baru yang makin canggih. Kasus penipuan selalu merupakan minoritas dan tersembunyi rapat di antara transaksi yang valid.
Menyiapkan Dataset
Mari kita telusuri implementasi pembelajaran mesin untuk deteksi penipuan kartu kredit menggunakan bahasa pemrograman Python. Kita akan bekerja pada dataset creditcard_data, yang merupakan sampel modifikasi dari dataset Kaggle tentang Credit Card Fraud Detection. Data asli merepresentasikan transaksi yang dilakukan pada kartu kredit milik pemegang kartu di Eropa selama dua hari pada September 2013.
Mari impor datanya dan lihat sekilas:
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
Dataset ini berisi variabel berikut:
- Variabel yang dikodekan secara numerik V1 hingga V28 yang merupakan principal components yang diperoleh dari transformasi PCA. Karena alasan kerahasiaan, tidak ada informasi latar belakang tentang fitur asli yang disediakan.
- Variabel Amount merepresentasikan jumlah transaksi.
- Variabel Class menunjukkan apakah transaksi tersebut penipuan (1) atau bukan (0).
Secara alami, kejadian penipuan untungnya merupakan minoritas ekstrem dalam daftar transaksi mana pun. Namun, algoritme pembelajaran mesin biasanya bekerja paling baik ketika kelas yang berbeda dalam dataset kurang lebih sama banyak. Jika tidak, hanya ada sedikit data untuk dipelajari. Masalah ini disebut ketidakseimbangan kelas.
Menghitung Penipuan dalam Dataset
Mari hitung persentase transaksi penipuan dari total jumlah transaksi dalam dataset kita:
round(creditcard_data['Class'].value_counts()*100/len(creditcard_data)).convert_dtypes()
0 99
1 1
Name: Class, dtype: Int64
dan buat plot untuk memvisualisasikan titik data penipuan dibanding non-penipuan:
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)

Menggunakan SMOTE untuk Menyeimbangkan Data
Kini kita dapat memastikan bahwa rasio transaksi penipuan sangat rendah dan kita menghadapi masalah ketidakseimbangan kelas. Untuk mengatasinya, kita dapat menyeimbangkan kembali data menggunakan synthetic minority oversampling technique (SMOTE). Berbeda dengan oversampling acak, SMOTE sedikit lebih canggih karena tidak hanya membuat salinan persis dari observasi. Sebagai gantinya, teknik ini menggunakan karakteristik tetangga terdekat dari kasus penipuan untuk membuat sampel sintetis baru yang cukup mirip dengan observasi yang ada pada kelas minoritas. Mari terapkan SMOTE pada data kartu kredit kita:
from imblearn.over_sampling import SMOTE
method = SMOTE()
X_resampled, y_resampled = method.fit_resample(X, y)
plot_data(X_resampled, y_resampled)

Seperti yang terlihat, penggunaan SMOTE tiba-tiba memberi kita lebih banyak observasi pada kelas minoritas. Untuk melihat hasil pendekatan ini dengan lebih jelas, kita akan membandingkannya dengan data asli:
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

Dengan demikian, metode SMOTE telah menyeimbangkan data kita sepenuhnya, dan ukuran kelas minoritas kini sama dengan kelas mayoritas.
Kita akan kembali ke penerapan praktis metode SMOTE segera, tetapi untuk saat ini, mari kembali ke data asli dan coba deteksi kasus penipuan. Mengikuti cara "old-school", kita harus membuat beberapa aturan untuk menangkap penipuan. Aturan tersebut dapat berkaitan, misalnya, dengan lokasi transaksi yang tidak biasa atau frekuensi transaksi yang mencurigakan. Gagasannya adalah menentukan nilai ambang berdasarkan statistik umum, sering kali pada nilai rata-rata observasi, dan menggunakan ambang tersebut pada fitur kita untuk mendeteksi penipuan.
print(creditcard_data.groupby('Class').mean().round(3)[['V1', 'V3']])
V1 V3
Class
0 0.035 0.037
1 -4.985 -7.294
Pada kasus khusus kita, mari terapkan kondisi berikut: V1 < -3 dan V3 < -5. Lalu, untuk mengestimasi kinerja pendekatan ini, kita bandingkan kasus yang ditandai sebagai penipuan dengan yang sebenarnya:
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
Menerapkan Regresi Logistik
Kita mendeteksi 22 dari 50 kasus penipuan, tetapi tidak dapat mendeteksi 28 lainnya, dan menghasilkan 16 positif palsu. Mari lihat apakah penggunaan teknik pembelajaran mesin dapat melampaui hasil tersebut.
Sekarang kita akan mengimplementasikan algoritme klasifikasi regresi logistik sederhana pada data kartu kredit kita untuk mengidentifikasi kejadian penipuan dan kemudian memvisualisasikan hasilnya pada confusion matrix:
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
Penting untuk dicatat bahwa di sini kita memiliki lebih sedikit observasi pada confusion matrix karena kita hanya menggunakan himpunan uji untuk menghitung hasil model, yaitu hanya 30% dari keseluruhan dataset.
Kita menangkap persentase kasus penipuan yang lebih tinggi: 90% (9 dari 10), dibandingkan hasil sebelumnya 44% (22 dari 50). Kita juga mendapatkan jauh lebih sedikit positif palsu dibanding sebelumnya, sehingga ada peningkatan.
Sekarang mari kembali ke masalah ketidakseimbangan kelas yang dibahas sebelumnya dan telusuri apakah kita dapat meningkatkan hasil prediksi lebih jauh dengan menggabungkan model regresi logistik dengan metode resampling SMOTE. Untuk melakukannya secara efisien dan sekaligus, kita perlu mendefinisikan pipeline dan menjalankannya pada data kita:
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
Seperti terlihat, dalam kasus kita SMOTE tidak memberikan peningkatan: kita tetap menangkap 90% kejadian penipuan dan, terlebih lagi, jumlah positif palsu sedikit lebih tinggi. Penjelasannya adalah resampling tidak selalu menghasilkan hasil yang lebih baik dalam semua kasus. Ketika kasus penipuan tersebar sangat luas di seluruh data, tetangga terdekatnya belum tentu juga kasus penipuan, sehingga penggunaan SMOTE dapat memperkenalkan bias.
Kesimpulan
Ke depan, untuk meningkatkan akurasi model regresi logistik, kita dapat menyetel beberapa parameter algoritme. K-fold cross-validation juga dapat dipertimbangkan alih-alih hanya membagi dataset menjadi dua bagian. Terakhir, kita dapat mencoba beberapa algoritme pembelajaran mesin lain (misalnya, decision tree atau random forest) dan melihat apakah hasilnya lebih baik.
Jika Anda ingin mempelajari lebih lanjut aspek teoretis dan teknis penerapan model deteksi penipuan, Anda dapat menelusuri materi kursus Fraud Detection in Python.

