Aditya Sridhar

Project · Oct 2026 · interactive

Card fraud: what a review budget buys

In the test months, one transaction in 259 is fraud, so accuracy says nothing: flagging nothing at all is 99.61% accurate. What a bank actually chooses is how many transactions its team can review. Pick that budget and see what a supervised random forest and an unsupervised isolation forest each catch on half a year of simulated transactions they never saw.

Random forest PR-AUC, test
0.954
Isolation forest PR-AUC, test
0.075
Test transactions
555,719
Fraud in test
2,145 (0.39%)

Try it

Random forest (learns from labels)

Fraud caught
94.6% 2,029 of 2,145
Alerts that are fraud
73.3%
False alarms
740
Fraud dollars flagged
98.4% $1,115,708

Isolation forest (no labels)

Fraud caught
17.5% 375 of 2,145
Alerts that are fraud
13.5%
False alarms
2,394
Fraud dollars flagged
29.1% $329,993
0%25%50%75%100%0.1%1%10%100%transactions flagged (log scale)
  • Random forest (learns from labels)
  • Isolation forest (no labels)
  • Flagging at random

Counting missed fraud dollars plus $10 per alert, the cheapest budget for the random forest is 0.52% of transactions ($43,669 in total, against $1,133,325 with no review at all).

Reviewing the riskiest 0.5% (2,769 alerts), the random forest catches 94.6% of the fraud and the isolation forest 17.5%. The isolation forest never sees a label: it only learns what is unusual, and most unusual transactions are not fraud.

Results

MetricValueSource
Random forest, average precision (PR-AUC)0.9541public/projects/fraud/curves.json
Random forest, ROC-AUC0.9957public/projects/fraud/curves.json
Random forest at the threshold with the best F1 on validation: precision / recall / F10.933 / 0.881 / 0.906public/projects/fraud/curves.json
Isolation forest, average precision (PR-AUC)0.0753public/projects/fraud/curves.json
Isolation forest, ROC-AUC0.9008public/projects/fraud/curves.json
Isolation forest at its best-F1 validation threshold: precision / recall / F10.120 / 0.263 / 0.165public/projects/fraud/curves.json

At that threshold the random forest raises 2,025 alerts over the six test months: 1,889 real fraud, 136 false alarms, and 256 frauds missed. The threshold was chosen on the three months before the test period; nothing was tuned on the test months.

How it works

Split by time. Models fit on 2019-01-01 to 2020-03-20 (1,070,966 transactions, 6,250 fraud). 2020-03-21 to 2020-06-21 picks the threshold. 2020-06-21 to 2020-12-31 is the test. A random split would let the model see the same card's fraud spree on both sides.

Features a bank has at that moment. The transaction itself (amount, category, hour, weekday, distance from the cardholder's home to the merchant) and the card's own history up to, not including, this transaction: time since its last use, count and spend over the previous 24 hours, and the amount against the card's average so far. The random forest leans most on the amount, the card's spend in the last 24 hours, the amount against the card's usual amount.

Two models, two jobs. The random forest learns the fraud patterns that were labelled. The isolation forest scores how easy a transaction is to isolate with random splits: it needs no labels, so it can flag new kinds of fraud, at the price of many more false alarms.

Earlier version. This rebuilds my 2025 fraud notebook. It one-hot encoded merchants and jobs into 2,150 columns and tuned its threshold on a random 20% of the training file, but then fit the models on the whole file, those rows included. Validation F1 read 0.850; the test file gave 0.675. Here the threshold comes from later months the models never fit on, and per-card history replaces the one-hot columns.

Reproduce

Hardware
Intel64 Family 6 Model 154 Stepping 3, GenuineIntel, CPU, scikit-learn 1.9.1
Commit
e5e3567
Data
Credit Card Transactions Fraud Detection Dataset (simulated with Sparkov), CC0 1.0. Simulated transactions, not real cardholders.

Environment

pip install scikit-learn pandas kaggle

Data

kaggle datasets download kartik2112/fraud-detection -p training/data/sparkov --unzip

Train and score

python training/fraud_sparkov/train.py

Data: Credit Card Transactions Fraud Detection Dataset (simulated with Sparkov) by kartik2112 on Kaggle, generated with Brandon Harris's Sparkov simulator, CC0 1.0.