Shaw Labs

Loan Approval · machine learning · 2026

Who gets the loan?

Two questions from a bank. Can machine learning predict which clients get approved for a loan? And for those approved, can it predict the maximum loan amount?

Suraj Shaw · Notebooks on GitHub

58,645applications
54,221after cleaning
8,349declined
6models

Cleaning the data

The dataset needed work before any model could use it.

Part 1: approved or declined

I trained three models on an 80/20 split, stratified so both sets kept the same approved to declined ratio, with a fixed random state so the results can be reproduced. Each model was tested on the same 10,845 unseen applications.

The bank wanted a model that catches as many declined applications as possible, and is right when it does. So accuracy was not the main measure. Recall, precision and F1 on the declined class were.

ModelAccuracyPrecisionRecallF1AUC
Naive Bayes0.870.950.040.070.86
Logistic regression0.900.720.390.510.88
kNN, k = 130.900.690.490.570.87

kNN was the best model. It had the highest recall and F1 for declined loans, so it was better at catching rejections than the other two, even though it still misses some.

Tuning kNN

GridSearchCV picked k = 29 with Manhattan distance.

kNNAccuracyPrecisionRecallF1
Before, k = 130.900.690.490.57
After, k = 290.900.720.440.55

Precision went up, but recall and F1 went down. For a bank that wants to catch declined loans, tuning did not improve the model.

An ensemble

I combined Naive Bayes and logistic regression in a soft voting ensemble, since both output probabilities. Precision rose to 0.88, but recall dropped to 0.16. It missed too many declined applications, and its F1 was worse than either model on its own. For the bank's goal, logistic regression is the better choice than the ensemble.

Part 2: the maximum loan amount

For approved clients I compared two decision tree regressors: a fully grown tree, and a tree pruned to four levels.

ModelMAEMSER²
DT-1, fully grown559.931,641,015.560.9985
DT-2, pruned to 4 levels8,116.98122,045,545.500.8875

DT-1 was better on every metric. The pruned tree was too simple and underfitted. But DT-1 is 24 levels deep, and an R² that close to 1 suggests it may be overfitting. A tuned tree, with depth 21 found by cross-validated grid search, scored almost the same (R² 0.9984) and is the safer choice in practice.

One client

Client 60256 was 56, earned 57,000 and asked for 25,700. The tuned tree predicted a maximum of 16,750. Several of this client's values were outside anything the model was trained on: their age, a 35 year credit history, and a 23% interest rate. For values out of range, the tree gave a lower amount.

Limitations

Ethics

Because older age groups were removed from the training data, the model can be biased against older applicants. Age should not decide whether someone gets a loan.

Python, pandas, scikit-learn and Jupyter.

The notebooks are on GitHub. All projects.