Machine Learning · Term 4 · PGDM 2025-27

* Receivables risk scoring

A collections team can only chase a fraction of its open accounts. Working the ledger top to bottom treats every account as equally likely to default. This model ranks them instead, so the same effort recovers more. It runs entirely in your browser: the trained trees ship as JSON and score as you type.

Pythonscikit-learnGradient BoostingCRISP-DMDeployed

30,000

accounts in the training file

0.783

AUC on held-out data

51%

of defaults in the top 20%

2.56x

lift over ledger order

* Score an account

Account details

Eight inputs. The other 22 features sit at their training median.

Last month first. This one column carries 51 percent of the model's importance.

Risk score

Probability of default next cycle

Loading 200 trees

* In short

I took 30,000 credit accounts from the UCI repository and built a model that answers one question: of the accounts that owe us money, which ones should we call first? I added seven features of my own on top of the raw columns, and two of them turned out to matter more than almost anything in the original file. Nine models were compared on the same split, and gradient boosting won. The result is not a number a manager has to interpret, it is a work list. Review the top fifth of the ledger and you reach half of everything that is going to go bad.

I picked this problem because my ERP capstone recommended it. We proposed three AI use cases to sit on top of an Odoo implementation, and scoring open invoices by payment risk was one of them. This is that recommendation, actually built and deployed.

* How it was built

Default of Credit Card Clients

UCI Machine Learning Repository, 30,000 accounts, 24 features, no missing values

Download CSV, 2.7 MB
IDLIMIT_BALSEXEDUCATIONMARRIAGEAGEPAY_1BILL_AMT1PAY_AMT1DEFAULT
120000221242391301
212000022226-1268201
3900002223402923915180
4500002213704699020000
55000012157-1861720000
6500001123706440025000
7500000112290367965550000
8100000222230118763800

First 8 of 30,000 rows. DEFAULT is the column being predicted.

What the columns mean

LIMIT_BAL
Approved credit limit in NT$, the total exposure on the account
SEX / EDUCATION / MARRIAGE
Demographics. Education and marital status carried codes outside the documented range
AGE
Age in years
PAY_1 to PAY_6
Repayment status for each of the last six months. Minus one means paid in full, one means one month late, and so on
BILL_AMT1 to BILL_AMT6
Bill amount for each of the last six months
PAY_AMT1 to PAY_AMT6
Amount actually paid in each of the last six months
DEFAULT
The target. One if the account defaulted the following month

What I found before modelling

345 records carried an education code outside the documented 1 to 4 range and 54 carried an undocumented marital code. Left alone, the model would treat each stray code as its own category and learn noise from a handful of rows. I folded them into "other".

The target is unbalanced: 22.1 percent of accounts default. Predicting "nobody defaults" scores 77.9 percent accuracy and recovers nothing, which is why accuracy is not the metric this model is judged on.

Data: Default of Credit Card Clients, UCI Machine Learning Repository. The model scores in your browser, so nothing you type is sent anywhere.