A complete machine learning pipeline for detecting credit card fraud on a highly imbalanced dataset. Compares 8 algorithms across 7 imbalance-handling strategies, including CTGAN-based synthetic data augmentation, evaluated with cost-sensitive business metrics.
European cardholders' credit card transactions, September 2013.
| Property | Value |
|---|---|
| Total transactions | 284,807 |
| Fraud cases | 492 (0.172%) |
| Normal cases | 284,315 (99.828%) |
| Features | Time, V1–V28 (PCA-transformed), Amount, Class |
| Target | Class — 1 = Fraud, 0 = Normal |
| Imbalance ratio | 1 : 578 |
The dataset is not included in this repository. Download
creditcard.csvfrom Kaggle and place it indataset/.
A missed fraud (False Negative) costs 10× more than a false alarm (False Positive).
| Predicted: Normal | Predicted: Fraud | |
|---|---|---|
| Actual: Normal | TN → cost = 0 | FP → cost = 1 |
| Actual: Fraud | FN → cost = 10 | TP → cost = 0 |
Total Business Cost = (10 × FN) + (1 × FP) — the primary ranking metric alongside AUPRC.
fraud_detection_ml/
│
├── dataset/
│ ├── creditcard.csv ← place dataset here (not tracked)
│ └── readme.txt
│
├── notebooks/
│ ├── 01_EDA.ipynb ← exploratory data analysis
│ ├── 02_Preprocessing.ipynb ← feature engineering + scaling + split
│ ├── 03_GAN.ipynb ← CTGAN training + synthetic data quality
│ ├── 04_Modeling.ipynb ← train 8 models × 7 strategies
│ └── 05_Evaluation.ipynb ← metrics, plots, final comparison tables
│
├── src/
│ ├── data_loader.py ← load CSV, save/load processed splits
│ ├── feature_engineering.py ← log-transform Amount, cyclic encode Time
│ ├── preprocessing.py ← StandardScaler, train/test split, validation
│ ├── imbalance_handler.py ← apply all 7 imbalance strategies
│ ├── gan_generator.py ← train CTGAN, generate + evaluate synthetic data
│ ├── models.py ← all 8 model definitions, train/predict/save helpers
│ ├── evaluation.py ← metrics, business cost, optimal threshold search
│ └── visualization.py ← all matplotlib/seaborn plots → outputs/figures/
│
├── outputs/
│ ├── figures/ ← all saved plots (.png)
│ ├── models/ ← trained model files (.pkl, .keras)
│ └── results/ ← comparison tables (.csv)
│
├── requirements.txt
├── PLAN.md
└── README.md
| Category | Libraries |
|---|---|
| Data | pandas, numpy |
| ML | scikit-learn, xgboost, lightgbm |
| Imbalance | imbalanced-learn (SMOTE, ADASYN, SMOTETomek, RandomUnderSampler) |
| Deep Learning | tensorflow >= 2.16 (Keras MLP + Autoencoder) |
| GAN | ctgan, sdv |
| Visualization | matplotlib, seaborn |
| Notebooks | jupyterlab |
Python 3.12 is required. TensorFlow 2.16+ is the first version with official Python 3.12 support.
# 1. Clone the repository
git clone https://github.com/<your-username>/fraud_detection_ml.git
cd fraud_detection_ml
# 2. Create a virtual environment (recommended)
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS / Linux
# 3. Install dependencies (~15–30 min, CTGAN downloads PyTorch ~2 GB)
pip install -r requirements.txt
# 4. Place the dataset
# Download creditcard.csv from Kaggle and put it in dataset/
# 5. Launch JupyterLab
jupyter labRun the notebooks in sequence. Each notebook saves its outputs so the next one can load them.
| Step | Notebook | Runtime (GPU) | Output |
|---|---|---|---|
| 1 | 01_EDA.ipynb |
~5 min | figures in outputs/figures/ |
| 2 | 02_Preprocessing.ipynb |
~3 min | outputs/results/X_train.csv etc., outputs/models/scaler.pkl |
| 3 | 03_GAN.ipynb |
~15–25 min | outputs/models/ctgan_model.pkl, outputs/results/synthetic_fraud.csv |
| 4 | 04_Modeling.ipynb |
~75–120 min | all model files, table_a/b/c_*.csv |
| 5 | 05_Evaluation.ipynb |
~8 min | all final plots and summary |
Total estimated runtime: 2 – 3 hours (with GPU).
| # | Model | Type | Notes |
|---|---|---|---|
| 1 | Logistic Regression | Classical | Baseline linear model |
| 2 | K-Nearest Neighbors | Classical | Distance-based |
| 3 | Random Forest | Ensemble | 200 trees, class_weight='balanced' |
| 4 | XGBoost | Gradient Boosting | scale_pos_weight, GPU-accelerated |
| 5 | LightGBM | Gradient Boosting | is_unbalance=True, 500 estimators |
| 6 | SVM (RBF) | Classical | Trained on 30k stratified subset (speed) |
| 7 | Keras MLP | Deep Learning | 64→32→16→1, BatchNorm + Dropout |
| 8 | Autoencoder | Deep Learning / Anomaly | Trained on normal only; fraud = high reconstruction error |
Step 1 trains all 8 on the baseline (class weighting) strategy. The top 2 models by business cost + F1 are selected for the full strategy comparison.
| # | Strategy | Description |
|---|---|---|
| 1 | Baseline | No resampling; class weights where applicable |
| 2 | Class Weighting | Weight minority class by imbalance ratio (~578×) |
| 3 | Random Undersampling | Reduce majority class to 1:10 ratio |
| 4 | SMOTE | Synthetic minority oversampling via interpolation |
| 5 | ADASYN | Adaptive synthetic sampling (focuses on hard samples) |
| 6 | SMOTE + Tomek Links | Oversample minority + remove ambiguous boundary samples |
| 7 | CTGAN Augmentation | 5,000 GAN-generated synthetic fraud samples added to training set |
All strategies are applied only to the training set. The test set is never touched.
| Feature | Transformation | Reason |
|---|---|---|
Amount |
log1p(Amount) → Amount_log |
Reduces right-skew and outlier influence |
Time |
Cyclic: sin(2π·t/86400), cos(2π·t/86400) |
Captures daily periodicity without arbitrary ordering |
V1–V28 |
No change | Already PCA-normalised by the dataset provider |
Only Amount_log, Time_sin, and Time_cos are passed through StandardScaler. Scaler is fit on training data only.
| Metric | Why it matters |
|---|---|
| AUPRC | Primary metric — robust under extreme imbalance |
| F1 (Fraud class) | Balances precision and recall for the minority class |
| Recall (Fraud) | Directly measures missed frauds (FN) |
| ROC-AUC | Overall discrimination ability |
| Business Cost | (10 × FN) + (1 × FP) — real-world impact ranking |
After running all notebooks:
outputs/
├── figures/
│ ├── 01_class_distribution.png
│ ├── 02_amount_time_dist.png
│ ├── 03_correlation_heatmap.png
│ ├── 04_top_feature_kde.png
│ ├── 05_time_pattern.png
│ ├── 06_roc_curves.png
│ ├── 07_pr_curves.png
│ ├── 08_cost_comparison_baseline.png
│ ├── gan_real_vs_synthetic.png
│ ├── gan_corr_comparison.png
│ ├── strategy_<model>.png ← one per top model
│ ├── cm_all_strategies_<model>.png ← confusion matrix grid
│ ├── ctgan_comparison.png
│ └── threshold_analysis.png
│
└── results/
├── table_a_baseline.csv ← all 8 models, baseline strategy
├── table_b_strategies.csv ← top 2 models × 7 strategies
├── table_c_ctgan.csv ← CTGAN with vs without
└── top2_models.csv ← names of the 2 selected models
- Which model achieves the lowest business cost on this dataset?
- Which imbalance strategy best improves fraud recall without excessive false alarms?
- Does CTGAN-generated synthetic data meaningfully improve model performance compared to traditional oversampling?
- SVM is trained on a stratified 30,000-row subset due to O(n²) training complexity on 284k rows.
- XGBoost uses
device='cuda'by default — change todevice='cpu'in src/models.py if no NVIDIA GPU is available. - The Autoencoder is trained exclusively on normal transactions. Fraud samples produce higher reconstruction error, which is used as the anomaly score.
- All random seeds are fixed at
42for reproducibility.