ML-powered loan default prediction. A Gradient Boosting model trained on Lending Club data, served through a FastAPI backend and a React dashboard — deployed as a single app on Vercel.
🔗 Live demo: add your Vercel URL here after deploying · 📊 Interactive API docs: /api/docs
Given ten features from a loan application (amount, interest rate, income, debt-to-income, credit history, etc.), the model returns a calibrated probability of default, maps it to a risk tier (LOW → CRITICAL), a 300–850 credit score, a lending recommendation, and the top feature importances behind the decision. The dashboard lets you score applications interactively, replay history, and inspect model performance.
Honesty about a model's limits is a feature, not a weakness. Here is exactly how this model performs.
| Metric | Value | Reading |
|---|---|---|
| AUC-ROC (test) | 0.770 | Solid discrimination for consumer credit risk. |
| AUC-ROC (5-fold CV) | 0.777 ± 0.004 | Tiny variance → the model is stable and not overfit. |
| Recall | 0.703 | Catches ~70% of true defaulters. |
| Precision | 0.461 | Of applicants it flags, ~46% actually default. |
| F1 | 0.557 | Balance of the two. |
Data: Lending Club loans. Train 26,059 / Test 6,515. Base default rate 27.3% (imbalanced — worth stating).
Confusion matrix (test set):
| Predicted good | Predicted default | |
|---|---|---|
| Actually good | TN 3,280 | FP 1,459 |
| Actually default | FN 527 | TP 1,249 |
The deliberate tradeoff: this model is tuned to favor recall over precision. In lending, a missed defaulter (false negative) costs the whole loan, while a wrongly-flagged good borrower (false positive) just goes to manual review. Catching 70% of defaulters at the cost of some false alarms is the economically correct bias — and it's a choice, not an accident.
What drives predictions (feature importance):
- Annual income — 40%
- Interest rate — 31%
- Debt-to-income ratio — 14%
- Revolving utilization — 4%
- (remaining six features share ~11%)
Limitations (read before trusting it):
- Trained on historical Lending Club data; it inherits any bias in that data and is not validated for real lending decisions.
- Not a regulated credit-scoring system. It performs no FCRA/ECOA compliance, adverse-action handling, or fair-lending testing. It is a portfolio/educational demo, not a production underwriting tool.
- Only ten features — real underwriting uses hundreds.
credit-risk-api/
├── api/index.py # FastAPI inference service → /api/*
├── model/ # Pickled GBM + JSON scaler & metrics (~455 KB)
├── training/train_model.py
├── src/ # React + Vite dashboard (Tailwind, Recharts, lucide)
│ └── components/ # LoanForm, RiskResult, PredictionHistory, ModelMetrics, Header
├── tests/ # pytest: API + training
└── vercel.json # One deploy: Python serverless + static frontend, same origin
Why one origin: vercel.json builds the Python API and the static React app together, so the frontend calls /api/* on its own domain — no CORS gymnastics, no second deployment to babysit.
| Method | Route | Purpose |
|---|---|---|
POST |
/api/predict |
Score a loan application → probability, tier, score, recommendation, feature importances. |
GET |
/api/health |
Model status + version. |
GET |
/api/model-info |
Metrics, confusion matrix, feature importances. |
GET |
/api/sample |
Sample low/moderate/high-risk applications for testing. |
GET |
/api/docs |
Interactive Swagger UI. |
Example:
curl -X POST https://<your-app>.vercel.app/api/predict \
-H "Content-Type: application/json" \
-d '{"loan_amnt":20000,"int_rate":15,"annual_inc":55000,"dti":22,
"delinq_2yrs":1,"inq_last_6mths":2,"open_acc":8,"revol_util":55,
"total_acc":15,"emp_length":3}'# Backend (terminal 1)
pip install -r requirements.txt
uvicorn api.index:app --reload --port 8000
# Frontend (terminal 2)
npm install
npm run dev # http://localhost:5173, proxies /api → localhost:8000pip install -r requirements-dev.txt
pytest- Push to GitHub (already done).
- vercel.com → Add New → Project → import this repo.
- Vercel auto-detects
vercel.json(Python serverless + static build). Framework preset: Other. No env vars needed — frontend and API share one origin. - Deploy. Your app is live at
https://<project>.vercel.app, docs at/api/docs.
Total footprint is ~1.4 MB and well under Vercel's free-tier limits (100 GB bandwidth/month, 250 MB function size). Unlike Render's free tier, Vercel serverless doesn't cold-sleep, so the demo loads instantly for anyone who opens it.
ML: scikit-learn (GradientBoostingClassifier · 200 trees · depth 4 · lr 0.05), NumPy Backend: FastAPI, Pydantic, Uvicorn Frontend: React 18, Vite, Tailwind CSS, Recharts, lucide-react Deploy: Vercel (serverless Python + static)
MIT — built by Sumedha Hundekar. GitHub