case study · risk scoring

Choosing What to Review

Prioritize possible fraud within the time a review team actually has.

← Systems we builtCase study

The problem

A review team cannot inspect every payment. The useful question is how much fraud it can find within the number of transactions it has time to review.

How we approached it

A LightGBM model ranks transactions using payment and card-history features. Training uses earlier records; the final evaluation uses later transactions. Scores are calibrated on separate validation data, and review capacity determines how far down the ranked queue the team looks.

Choose a review capacity

Select a review budget to see the trade-off between fraud caught and legitimate transactions sent for review. These are measured results on historical data, not a live queue.

What Reviewing More Transactions Buys

Four measured review budgets on the 118,108 held-out transactions. Pick one. No line is drawn between the points: only these four were measured.

Fraud Caught (Recall)
26.2%
Flags That Are Real Fraud (Precision)
90.1%
Transactions Reviewed
1,181
Non-fraud Transactions Reviewed
117
Recall and Precision at Four Measured Review Budgets 0%25%50%75%100% 0.5%1%2%5% Share of transactions reviewed (measured points only) Rate 13.4%26.2%42.7%58.1% 91.9%90.1%73.5%40.0% Fraud caught (recall)Flags that are real (precision)

4,064 of the 118,108 held-out transactions are labeled fraud (3.44%). "Non-fraud transactions reviewed" = transactions reviewed minus true positives. From outputs/metrics_before_feature_pass.json, the baseline evaluation.

What the evaluation showed

Reviewing more transactions catches more fraud, but also sends more legitimate payments to the team. That makes the operating threshold a staffing and customer-experience decision, as well as a modeling decision.

Evaluation offline holdout; serving parity unverified

Risk scoring at a fixed review capacity.

Top 2% reviewed: 73.5% precision, 42.7% recall; 118,108 time-held-out transactions.

Offline serving-model results. Live historical-feature parity and deployment of the stronger challenger remain unverified.

Evaluation data →

What still needs checking

The published results are offline measurements. Matching the live service’s historical features to the offline evaluation still needs verification. A later feature experiment improved the offline scores, but deployment of that stronger model is unverified.

Score one transaction

Choose a held-out transaction to inspect the deployed model’s response. This illustrates scoring; it does not reproduce the full historical evaluation.

Score a Transaction

Choose a held-out transaction to score with the deployed model.

Examples are real holdout transactions the model never trained on. Scores run against the live model API.

Methods, calibration and full results

Results

ROC-AUC
0.893
PR-AUC
0.526
Holdout Transactions
118,108
Fraud in Holdout
4,064
Precision, 1% Review
90.1%
Recall, 1% Review
26.2%
Precision, 2% Review
73.5%
Recall, 2% Review
42.7%

Measured on 118,108 transactions the model never trained on, held out by time, not by random split. Reviewing the riskiest 1% of transactions (1,181 of them) catches 26.2% of the fraud at 90.1% precision. The most any model could catch in that budget is 29.1% (1,181 reviews against 4,064 fraud cases), so the model fills 90% of the budget with real fraud. Reviewing the riskiest 2% (2,362) catches 42.7% at 73.5% precision, against a ceiling of 58.1%. The live review flag uses a cutoff fitted on validation data, not on the holdout; on the holdout it flags 1.65% of transactions at 80.1% precision and 38.5% recall. From outputs/metrics_before_feature_pass.json in the repo below, build d29088a, reported on this site as the serving model. The latest live deployment and training-versus-serving historical-feature parity require a separate verification.

One Feature Pass, Measured on the Same Holdout

  • Added on Sep 19: count and mean-amount aggregates per card, per card and address, and per card and email domain; time since the card's previous transaction; amount relative to the card's mean; a card-level id from card, address, and account start day, with its counts. All fit on the training window only, with tests that the value for a transaction uses only earlier rows.
  • Same split, seed, class weighting, and calibration. ROC-AUC 0.893 → 0.900, PR-AUC 0.526 → 0.553, Brier 0.0215 → 0.0206. At 1% review, recall 26.2% → 26.8% and precision 90.1% → 92.1%; at 2%, recall 42.7% → 44.4% and precision 73.5% → 76.5%.
  • The two strongest features after the pass are the card id (28% of gain) and the new card-level id (23%).
  • Scope: this is an offline feature comparison. The live demo and the other results on this page use the serving model shown in the table.
MeasureServing ModelAfter the Feature Pass
ROC-AUC0.8930.900
PR-AUC0.5260.553
Brier score (lower is better)0.02150.0206
Recall at 0.5% review13.4%13.7%
Precision at 0.5% review91.9%94.1%
Recall at 1% review26.2%26.8%
Precision at 1% review90.1%92.1%
Recall at 2% review42.7%44.4%
Precision at 2% review73.5%76.5%
Recall at 5% review58.1%59.8%
Precision at 5% review40.0%41.2%
Live review flag: share flagged · precision · recall1.65% · 80.1% · 38.5%1.73% · 82.4% · 41.5%

Before: outputs/metrics_before_feature_pass.json (build d29088a, serving). After: outputs/metrics.json (build 6377aa2). Same 118,108 held-out transactions.

Calibration

Transactions grouped into 10 equal-sized bins by predicted score. Predicted and observed fraud rates track each other across the ten bins, with observed rates running above predicted in the low bins. Each bin holds about 11,811 transactions. Weighted by bin size, the average gap between predicted and observed rates is 0.58 points (expected calibration error). The score is a calibrated estimate, not an exact probability.

BinTransactionsMean PredictedObserved Fraud Rate
111,8100.088%0.144%
211,8110.145%0.263%
311,8110.161%0.372%
411,8110.177%0.491%
511,8110.272%0.838%
611,8100.658%0.957%
711,8111.071%1.651%
811,8111.745%2.633%
911,8113.763%3.666%
1011,81126.049%23.393%

Code

The model, the training pipeline, and the scoring service: github.com/alphan-ml/fraud-radar

Where It Runs Data, deployment and checks
Where It Runs
ComputeAWS Lambda behind API Gateway, us-east-1. Function fraud-score-transaction. Endpoint r3skxlusm4.execute-api.us-east-1.amazonaws.com.
ModelLightGBM model, calibration table and feature maps. Single-transaction implementation parity was checked against the local scorer; equivalence to batch offline metrics for historical transaction features is still being evaluated. Read from S3 (giggit-fraud-radar-models) at cold start.
DeployA merge to main runs the tests, swaps the handler in the Lambda, and checks /health. GitHub Actions with an AWS role; no stored keys.
ChecksEvery six hours a job scores 500 held-out transactions against this endpoint and writes the result to a public ledger. Live Checks.