Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

Repository files navigation

Credit Risk Prediction Model (FICO HELOC)

End-to-end, interpretable machine-learning system that predicts the probability of a Home Equity Line of Credit (HELOC) applicant becoming seriously delinquent (90+ days past due) within 24 months, using real credit-bureau data from the FICO Explainable ML Challenge.

The project demonstrates a full, explainability-first ML lifecycle: EDA → leakage-aware preprocessing → penalised logistic regression → cost-optimised decision threshold → FastAPI inference → Streamlit dashboard with SHAP explanations → Dockerised deployment.


Screenshots

Prediction tool with per-applicant SHAP waterfall explanation — red bars push the default probability up, blue bars pull it down, from the average applicant's base rate:

SHAP waterfall explanation

Model evaluation — honest holdout performance at the cost-optimised threshold:

Evaluation metrics

Global feature importance (mean |SHAP|) — which credit behaviours drive default risk across the portfolio:

Global feature importance


Why this dataset?

The previous version of this project used the synthetic AmExpert dataset, whose engineered columns do not reward honest, leakage-free modelling. It was replaced with the FICO HELOC dataset (~10.4k real applicants, 23 credit-bureau attributes, ~52% "Bad" rate within 24 months). It is a well-known benchmark for interpretable credit scoring, with a strong, honest baseline achievable by a linear model.

Test-set ROC-AUC: 0.793 with a plain penalised logistic regression - no leakage, no feature magic.


Model

  • Algorithm: penalised (elastic-net) logistic regression - interpretable by design.
  • Tuning: 5-fold GridSearchCV (C and L1 ratio) optimising ROC-AUC on a stratified 80/20 split.
  • Decision threshold: chosen to minimise an asymmetric cost function weighting a false negative (approving a future defaulter, cost 150) higher than a false positive (declining a good customer, cost 100) - mirroring a lender's real loss asymmetry.
  • Validation: stratified holdout; all imputation statistics fitted on the training set only.

Performance (stratified 80/20 holdout)

Metric Value
ROC-AUC 0.793
Precision (Bad) 0.61
Recall (Bad) 0.95
Decision threshold 0.25 (cost-optimised)

At that threshold the model catches 95% of future defaulters while keeping precision at 61%, reflecting the deliberate bias towards avoiding bad approvals.


Data & preprocessing

FICO records missing data as special value codes rather than blanks:

Code Meaning
-9 No Bureau record (thin file)
-8 No usable / valid trades
-7 Condition not met (e.g. never delinquent)
-2 No / insufficient data

These are treated as meaningful signals, not random missingness:

  • Binary flags are derived before imputation (no_bureau, never_delinquent) - an applicant who has never been delinquent is genuinely lower risk, so this must not be discarded.
  • Sentinels are then removed and remaining gaps are median-imputed using statistics fitted on the training split only (no leakage).
  • NumInqLast6Mexcl7days is excluded as a near-duplicate of NumInqLast6M (r > 0.99); keeping both destabilised the elastic-net coefficients (opposite-sign artifacts) and hurt interpretability.

Feature direction checks (model agrees with credit intuition)

  • Lowers default risk: higher external risk score, more satisfactory trades, longer credit history, "never delinquent".
  • Raises default risk: revolving utilisation, high-utilisation bank/national trades, recent hard inquiries.

Project layout

api/                     FastAPI inference endpoint (input validation, batch predict)
dashboard/               Streamlit app (dataset explorer, metrics, prediction + SHAP)
src/data/preprocess.py   Sentinel handling, flags, median imputation + feature metadata
src/data/pipeline.py     sklearn transformer wrapper (fit/transform)
src/data/eda.ipynb       Exploratory analysis of the HELOC dataset
src/models/model1/train.py   Training + evaluation + threshold selection
src/models/model1/predict.py Inference + SHAP LinearExplainer
artifacts/               Trained model, scaler/pipeline, threshold, splits (gitignored)
data/raw/                Dataset (gitignored)

Requirements

  • Python 3.14+ (Docker image python:3.14.3)
  • Dataset placed at data/raw/train.csv
# get the data
mkdir -p data/raw
curl -L -o data/raw/train.csv https://raw.githubusercontent.com/Ali-Abbass313/DSPP-HELOC/main/heloc_dataset_v1.csv

Setup

python -m venv venv
source venv/bin/activate          # or venv\Scripts\activate on Windows
pip install -r requirements.txt

Train the model

python src/models/model1/train.py

Writes model, best hyperparameters, cost-optimised threshold and train/test splits to artifacts/.

Run the API

uvicorn api.main:app --reload
# docs: http://localhost:8000/docs

Run the dashboard

streamlit run dashboard/app.py
# http://localhost:8501

Run with Docker

The image bakes in the trained artefacts and dataset, so train before building:

docker build -t credit-api .
docker run -p 8000:8000 credit-api

API example

curl -X POST http://localhost:8000/predict \
  -H 'Content-Type: application/json' \
  -d '[{
    "ExternalRiskEstimate": 90, "MSinceOldestTradeOpen": 240,
    "MSinceMostRecentTradeOpen": 5, "AverageMInFile": 120,
    "NumSatisfactoryTrades": 25, "NumTrades60Ever2DerogPubRec": 0,
    "NumTrades90Ever2DerogPubRec": 0, "PercentTradesNeverDelq": 100,
    "MSinceMostRecentDelq": -7, "MaxDelq2PublicRecLast12M": -7,
    "MaxDelqEver": -7, "NumTotalTrades": 28, "NumTradesOpeninLast12M": 1,
    "PercentInstallTrades": 30, "MSinceMostRecentInqexcl7days": 8,
    "NumInqLast6M": 0, "NetFractionRevolvingBurden": 12,
    "NetFractionInstallBurden": 50, "NumRevolvingTradesWBalance": 2,
    "NumInstallTradesWBalance": 2,
    "NumBank2NatlTradesWHighUtilization": 0, "PercentTradesWBalance": 55
  }]'

The three delinquency fields accept -7 (FICO's "never delinquent" code); the API enforces that they are all -7 or all real values.


Explainability

Interpretability is the point of the model, not an afterthought:

  • By design: linear, penalised model with stable, monotonic-sensible coefficients.
  • Per prediction: the dashboard renders a SHAP waterfall showing exactly which credit behaviours pushed an applicant's default probability up or down from the base rate.
  • Global view: mean-|SHAP| feature importance shows the portfolio-level drivers of risk.

This mirrors the transparency expected of credit models under responsible-lending and regulatory (e.g. model risk / assurance) review.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages