Spaces:
Sleeping
Sleeping
|
Download Readme.md from Nickanas/PaySim-Fraud: direct link, hf CLI and curl.
- Browser
- Download file 6.7 kB
-
https://huggingface.co/spaces/Nickanas/PaySim-Fraud/resolve/main/Readme.md
- Command line
-
hf download hf://spaces/Nickanas/PaySim-Fraud/Readme.md
-
curl -L -o Readme.md https://huggingface.co/spaces/Nickanas/PaySim-Fraud/resolve/main/Readme.md
6.7 kB
| # Fraud Detection on PaySim β End-to-End ML Pipeline | |
| A production-style machine learning pipeline that detects fraudulent mobile-money | |
| transactions in the [PaySim synthetic dataset](https://www.kaggle.com/datasets/ealaxi/paysim1) | |
| (~6.3M transactions). The project covers the full lifecycle: data validation, | |
| feature engineering, model training with experiment tracking, and model serving | |
| through both a REST API and a web UI. | |
| > **Focus:** this repo is less about squeezing out the last decimal of accuracy and | |
| > more about doing the *engineering* around a model correctly β no data leakage, | |
| > reproducible training, tracked experiments, saved artifacts, and a real serving layer. | |
| --- | |
| ## Results | |
| Evaluated on a **chronologically held-out test set** (later time steps the model never | |
| saw during training), so the numbers reflect genuine generalization rather than | |
| memorization. | |
| | Metric | @ threshold 0.50 | @ tuned threshold (0.64) | | |
| |---|---|---| | |
| | **PR-AUC** | **0.90** | 0.90 | | |
| | Precision | 0.83 | 0.95 | | |
| | Recall | 0.84 | 0.79 | | |
| | F1 | 0.83 | 0.87 | | |
| *PR-AUC (area under the precisionβrecall curve) is the headline metric β accuracy is | |
| misleading here because only ~0.2β4% of transactions are fraudulent.* | |
| **Known failure mode:** the model catches `TRANSFER` fraud almost perfectly (>99% | |
| confidence) but is weaker on `CASH_OUT` fraud. In PaySim, fraud is typically a | |
| `TRANSFER` of stolen funds *followed by* a `CASH_OUT` of the same money β the `TRANSFER` | |
| leg carries the obvious "account drained to zero" signature, while the `CASH_OUT` leg | |
| looks much like a legitimate withdrawal. Improving `CASH_OUT` recall (e.g. features | |
| that link a cash-out back to a preceding transfer) is the clearest next modelling step. | |
| > β οΈ **Honesty note:** the tuned threshold (0.64) was selected on the test set, so its | |
| > precision is mildly optimistic. The @0.50 numbers are the trustworthy ones. The test | |
| > window is also more fraud-dense than the training window, so real-world precision at a | |
| > lower fraud base rate would be lower. | |
| --- | |
| ## Approach | |
| **Avoiding data leakage** β the most common mistake on this dataset: | |
| - **Chronological split** by transaction `step` (train on earlier steps, test on later), | |
| mimicking how a fraud model is used in production: trained on the past, scoring the future. | |
| - The feature scaler is **fit on the training split only** and reused at inference. | |
| - The class-imbalance weight (`pos_weight`) is computed from the **training split only**. | |
| **Feature engineering** (in `src/data/preprocess.py`): | |
| - `errorBalanceOrig` / `errorBalanceDest` β accounting inconsistencies between stated | |
| balances and transaction amounts (the highest-signal engineered features). | |
| - `orig_balance_missing` / `dest_balance_missing` β flags for placeholder-zero balances. | |
| - One-hot encoded transaction type; only `TRANSFER` and `CASH_OUT` are kept, as these | |
| are the only types where fraud occurs in PaySim. | |
| **Model:** a small PyTorch MLP (`FraudMLP`) with BatchNorm and Dropout, trained with | |
| `BCEWithLogitsLoss` weighted for the severe class imbalance. | |
| **Threshold tuning:** instead of a naive 0.5 cutoff, the decision threshold is selected | |
| from the precisionβrecall curve to balance precision and recall (F1-optimal). | |
| --- | |
| ## Tech stack | |
| | Area | Tools | | |
| |---|---| | |
| | Data / features | pandas, scikit-learn | | |
| | Data validation | Great Expectations | | |
| | Modelling | PyTorch | | |
| | Experiment tracking | MLflow | | |
| | Serving | FastAPI, Gradio, Uvicorn, Pydantic | | |
| --- | |
| ## Project structure | |
| ``` | |
| fraud-paysim/ | |
| βββ src/ | |
| β βββ data/ | |
| β β βββ load_data.py # load the raw CSV | |
| β β βββ preprocess.py # cleaning + feature engineering | |
| β βββ features/ | |
| β β βββ build_features.py # chronological split, scaling, DataLoaders | |
| β βββ utils/ | |
| β β βββ validate_data.py # Great Expectations checks (gate before training) | |
| β βββ models/ | |
| β β βββ model.py # FraudMLP architecture | |
| β β βββ train.py # training loop + MLflow logging + test metrics | |
| β β βββ evaluate.py # evaluation + threshold tuning helpers | |
| β βββ app/ | |
| β βββ inference.py # shared predict(): raw transaction -> probability | |
| β βββ main.py # FastAPI API (/predict) + Gradio UI (/ui) | |
| βββ scripts/ | |
| β βββ run_pipeline.py # end-to-end: load -> validate -> train -> save | |
| βββ requirements.txt | |
| βββ Readme.md | |
| ``` | |
| --- | |
| ## Setup | |
| **1. Get the data.** The dataset is not included in the repo (it's ~470 MB). Download | |
| "Synthetic Financial Datasets For Fraud Detection" from | |
| [Kaggle](https://www.kaggle.com/datasets/ealaxi/paysim1) and place the CSV at: | |
| ``` | |
| fraud-paysim/data/Synthetic_Financial_datasets_log.csv | |
| ``` | |
| **2. Create a virtual environment and install dependencies:** | |
| ```bash | |
| python -m venv .venv | |
| # Windows | |
| .venv\Scripts\activate | |
| # macOS / Linux | |
| source .venv/bin/activate | |
| pip install -r requirements.txt | |
| ``` | |
| --- | |
| ## Usage | |
| ### Train the model | |
| Runs the full pipeline (load β validate β feature-build β train β evaluate β save artifacts): | |
| ```bash | |
| python scripts/run_pipeline.py | |
| ``` | |
| This logs metrics to MLflow and writes three artifacts to `artifacts/`: | |
| `model.pt` (weights), `scaler.joblib` (fitted scaler), and `metadata.json` | |
| (input dimension + exact feature column order). These three together are what the | |
| serving layer needs to reproduce training-time preprocessing exactly. | |
| Inspect experiments with: | |
| ```bash | |
| mlflow ui | |
| ``` | |
| ### Serve the model | |
| ```bash | |
| uvicorn src.app.main:app --reload | |
| ``` | |
| Then open: | |
| - **http://localhost:8000/docs** β interactive REST API (Swagger UI) for the `/predict` endpoint | |
| - **http://localhost:8000/ui** β Gradio web form for manual predictions | |
| **Example request** (a known fraud pattern β full balance transferred out, origin drained to zero): | |
| ```json | |
| { | |
| "step": 1, | |
| "type": "TRANSFER", | |
| "amount": 181.0, | |
| "oldbalanceOrg": 181.0, | |
| "newbalanceOrig": 0.0, | |
| "oldbalanceDest": 0.0, | |
| "newbalanceDest": 0.0 | |
| } | |
| ``` | |
| Response: | |
| ```json | |
| { "fraud_probability": 0.9952, "is_fraud": 1 } | |
| ``` | |
| --- | |
| ## Design notes | |
| - **Shared inference path.** Both the API and the Gradio UI call the same | |
| `predict()` function, so there is a single source of truth for how a raw transaction | |
| is turned into a prediction β no risk of training/serving skew between the two faces. | |
| - **Raw in, prediction out.** The serving layer accepts *raw* transaction fields and | |
| reconstructs the engineered features internally using the same `preprocess_data` | |
| used in training. Clients never compute features themselves. | |
| --- | |