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
- 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
| Metric | Value | Source |
|---|---|---|
| Random forest, average precision (PR-AUC) | 0.9541 | public/projects/fraud/curves.json |
| Random forest, ROC-AUC | 0.9957 | public/projects/fraud/curves.json |
| Random forest at the threshold with the best F1 on validation: precision / recall / F1 | 0.933 / 0.881 / 0.906 | public/projects/fraud/curves.json |
| Isolation forest, average precision (PR-AUC) | 0.0753 | public/projects/fraud/curves.json |
| Isolation forest, ROC-AUC | 0.9008 | public/projects/fraud/curves.json |
| Isolation forest at its best-F1 validation threshold: precision / recall / F1 | 0.120 / 0.263 / 0.165 | public/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 kaggleData
kaggle datasets download kartik2112/fraud-detection -p training/data/sparkov --unzipTrain and score
python training/fraud_sparkov/train.pyData: Credit Card Transactions Fraud Detection Dataset (simulated with Sparkov) by kartik2112 on Kaggle, generated with Brandon Harris's Sparkov simulator, CC0 1.0.