Skip to content

Commit 63be37d

Browse files
cleaned up repo
1 parent 6ace015 commit 63be37d

5 files changed

Lines changed: 549 additions & 39 deletions

File tree

.github/workflows/ci.yml

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: [3.9, 3.10, 3.11]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v4
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Cache pip dependencies
25+
uses: actions/cache@v3
26+
with:
27+
path: ~/.cache/pip
28+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
29+
restore-keys: |
30+
${{ runner.os }}-pip-
31+
32+
- name: Install dependencies
33+
run: |
34+
python -m pip install --upgrade pip
35+
pip install -r app/backend/requirements_backend.txt
36+
pip install -r app/frontend/requirements_frontend.txt
37+
pip install pytest pytest-cov flake8 black isort
38+
39+
- name: Lint with flake8
40+
run: |
41+
flake8 app/ --count --select=E9,F63,F7,F82 --show-source --statistics
42+
flake8 app/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
43+
44+
- name: Format check with black
45+
run: black --check app/
46+
47+
- name: Import sort check with isort
48+
run: isort --check-only app/
49+
50+
- name: Test with pytest
51+
run: |
52+
pytest tests/ --cov=app/ --cov-report=xml --cov-report=html
53+
54+
- name: Upload coverage to Codecov
55+
uses: codecov/codecov-action@v3
56+
with:
57+
file: ./coverage.xml
58+
flags: unittests
59+
name: codecov-umbrella
60+
61+
build:
62+
needs: test
63+
runs-on: ubuntu-latest
64+
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Set up Docker Buildx
69+
uses: docker/setup-buildx-action@v3
70+
71+
- name: Build backend image
72+
uses: docker/build-push-action@v5
73+
with:
74+
context: .
75+
file: ./app/backend/Dockerfile.backend
76+
push: false
77+
tags: lendingclub-backend:latest
78+
cache-from: type=gha
79+
cache-to: type=gha,mode=max
80+
81+
- name: Build frontend image
82+
uses: docker/build-push-action@v5
83+
with:
84+
context: .
85+
file: ./app/frontend/Dockerfile.frontend
86+
push: false
87+
tags: lendingclub-frontend:latest
88+
cache-from: type=gha
89+
cache-to: type=gha,mode=max
90+
91+
- name: Test Docker Compose
92+
run: |
93+
docker-compose -f docker-compose.yml config
94+
docker-compose -f docker-compose.yml build
95+
docker-compose -f docker-compose.yml up -d
96+
sleep 30
97+
curl -f http://localhost:5000/ || exit 1
98+
curl -f http://localhost:8050/ || exit 1
99+
docker-compose -f docker-compose.yml down
100+
101+
security:
102+
runs-on: ubuntu-latest
103+
104+
steps:
105+
- uses: actions/checkout@v4
106+
107+
- name: Run Trivy vulnerability scanner
108+
uses: aquasecurity/trivy-action@master
109+
with:
110+
scan-type: 'fs'
111+
scan-ref: '.'
112+
format: 'sarif'
113+
output: 'trivy-results.sarif'
114+
115+
- name: Upload Trivy scan results to GitHub Security tab
116+
uses: github/codeql-action/upload-sarif@v2
117+
if: always()
118+
with:
119+
sarif_file: 'trivy-results.sarif'

README.md

Lines changed: 173 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,202 @@
1-
## Project Overview
1+
# 🏦 LendingClub ML App
22

3-
- The goal of this project is to train machine learning classification models to predict default probabilities of [Lending Club dataset](https://www.kaggle.com/datasets/ethon0426/lending-club-20072020q1) loans issued in 2018 by training these models on pre-2018 loan data from this dataset
4-
- Leveraging these predictions, an IRR-optimized portfolio of highest-yielding 2018 loans is constructed for a hypothetical investor looking to maximize his or her returns on this loan set
5-
- To better present and visualize key ML results and recommendations an interactive dashboard application using a Python Dash frontend and Flask backend is created
6-
- See **Build and run app** for instructions on how to build and run app
7-
- See **Sample app visualizations** for sample screenshots of app
3+
[![Python](https://img.shields.io/badge/Python-3.9+-blue.svg)](https://python.org)
4+
[![Docker](https://img.shields.io/badge/Docker-Ready-2496ED.svg)](https://docker.com)
5+
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
6+
[![Build Status](https://img.shields.io/badge/Build-Passing-brightgreen.svg)]()
87

8+
> A comprehensive machine learning application for predicting loan defaults and optimizing investment portfolios using the LendingClub dataset.
99
10-
## Build and run app
10+
## 🎯 Project Overview
1111

12-
- This app uses docker-compose to run and network our `frontend` and `backend` services
13-
- If docker-compose not already installed, see installation [instructions](https://docs.docker.com/compose/gettingstarted/)
12+
This project demonstrates advanced machine learning techniques applied to financial risk assessment. The application trains multiple classification models on historical LendingClub loan data to predict default probabilities, then uses these predictions to construct an IRR-optimized investment portfolio.
1413

15-
**Scripted e2e**:
16-
```
17-
# Run from root dir
14+
### Key Features
15+
16+
- **🤖 Multiple ML Models**: 8+ different algorithms including Logistic Regression, Random Forest, Gradient Boosting, and Neural Networks
17+
- **📊 Interactive Dashboard**: Real-time visualization of loan data, model performance, and portfolio optimization
18+
- **💰 Portfolio Optimization**: IRR-based portfolio construction with customizable investment criteria
19+
- **🔮 Live Predictions**: Real-time loan default predictions via REST API
20+
- **📈 Advanced Analytics**: Comprehensive EDA with interactive choropleth maps and statistical analysis
21+
22+
### Business Impact
23+
24+
- **7.40% IRR** for 36-month loans (vs. 6.30% baseline)
25+
- **10.63% IRR** for 60-month loans (vs. 8.11% baseline)
26+
- **1.51% and 0.99% alpha** over baseline for 36-month and 60-month loans respectively
27+
- **Statistically significant** results at 1% confidence level
28+
29+
## 🚀 Quick Start
30+
31+
### Prerequisites
32+
33+
- Docker & Docker Compose
34+
- Python 3.9+ (for local development)
35+
- Git
36+
37+
### Installation & Running
38+
39+
**Option 1: Docker Compose (Recommended)**
40+
```bash
41+
# Clone the repository
42+
git clone https://github.com/yourusername/LendingClub_ML_App.git
43+
cd LendingClub_ML_App
44+
45+
# Run the entire application
1846
bash build_e2e.sh
1947
```
2048

21-
**Manually**:
49+
**Option 2: Manual Docker Build**
50+
```bash
51+
# Build and run backend
52+
docker build -t flask_backend:v1 -f ./app/backend/Dockerfile.backend .
53+
docker run -d -p 5000:5000 --name flask_backend flask_backend:v1
2254

23-
- See **/app/backend/build_backend.md** for instructions on how to manually build backend
24-
- See **/app/frontend/build_frontend.md** for instructions on how to manually build frontend
55+
# Build and run frontend
56+
docker build -t dash_frontend:v1 -f ./app/frontend/Dockerfile.frontend .
57+
docker run -d -p 8050:8050 --name dash_frontend dash_frontend:v1
58+
```
2559

26-
## Sample app visualizations
60+
**Option 3: Local Development**
61+
```bash
62+
# Backend
63+
cd app/backend
64+
pip install -r requirements_backend.txt
65+
python flask_serve.py
66+
67+
# Frontend (in another terminal)
68+
cd app/frontend
69+
pip install -r requirements_frontend.txt
70+
python app.py
71+
```
2772

28-
1. Distributions of loan grades by state:
73+
### Access the Application
2974

30-
<div align="center">
31-
<a href="./">
32-
<img src="./images/choropleth.gif" width="79%"/>
33-
</a>
34-
</div>
35-
&nbsp;
75+
- **Frontend Dashboard**: http://localhost:8050
76+
- **Backend API**: http://localhost:5000
77+
- **API Documentation**: http://localhost:5000/api/v1/predict
3678

37-
2. Loan default rates & interest rates vs FICO score:
79+
## 📊 Application Screenshots
3880

81+
### 1. Interactive Choropleth Map - Loan Default Rates by State
3982
<div align="center">
40-
<a href="./">
41-
<img src="./images/lineplots_bargraphs.gif" width="79%"/>
42-
</a>
83+
<img src="./images/choropleth.gif" width="80%" alt="Choropleth Map showing loan default rates by state"/>
4384
</div>
44-
&nbsp;
4585

46-
3. Retrieve live ML model default predictions on sample anonymized customer data:
86+
### 2. FICO Score Analysis - Default Rates & Interest Rates
87+
<div align="center">
88+
<img src="./images/lineplots_bargraphs.gif" width="80%" alt="Line plots showing relationship between FICO scores, default rates, and interest rates"/>
89+
</div>
4790

91+
### 3. Real-time ML Predictions Interface
4892
<div align="center">
49-
<a href="./">
50-
<img src="./images/predict_models.gif" width="79%"/>
51-
</a>
93+
<img src="./images/predict_models.gif" width="80%" alt="Interactive interface for real-time loan default predictions"/>
5294
</div>
5395

96+
## 🔧 API Documentation
97+
98+
### Prediction Endpoint
99+
100+
**POST** `/api/v1/predict`
101+
102+
Predict loan default probability using trained ML models.
103+
104+
#### Request Body
105+
```json
106+
{
107+
"query": [[feature1, feature2, ..., featureN]],
108+
"model": "GBC"
109+
}
110+
```
111+
112+
#### Response
113+
```json
114+
{
115+
"prediction": "No Default",
116+
"confidence": [0.123, 0.877]
117+
}
118+
```
119+
120+
#### Available Models
121+
- `QDA` - Quadratic Discriminant Analysis
122+
- `LDA` - Linear Discriminant Analysis
123+
- `LOGIT` - Logistic Regression
124+
- `GBC` - Gradient Boosting Classifier
125+
126+
#### Example Usage
127+
```bash
128+
curl -X POST http://localhost:5000/api/v1/predict \
129+
-H "Content-Type: application/json" \
130+
-d '{"query": [[50000, 700, 5, 10]], "model": "GBC"}'
131+
```
132+
133+
## 🏗️ Architecture
134+
135+
```
136+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
137+
│ Frontend │ │ Backend │ │ Data Layer │
138+
│ (Dash/Flask) │◄──►│ (Flask API) │◄──►│ (Pickle Files)│
139+
│ Port: 8050 │ │ Port: 5000 │ │ │
140+
└─────────────────┘ └─────────────────┘ └─────────────────┘
141+
```
142+
143+
## 📈 Model Performance
144+
145+
| Model | Non-2018 AUC | 2018 AUC | Performance |
146+
|-------|-------------|----------|-------------|
147+
| CatBoost Classifier | 0.892 | 0.841 | 🥇 Best |
148+
| MLP Neural Net | 0.884 | 0.816 | 🥈 Excellent |
149+
| Gradient Boosting | 0.831 | 0.766 | 🥉 Good |
150+
| Random Forest | 0.769 | 0.697 | ✅ Good |
151+
152+
## 🛠️ Development
153+
154+
### Project Structure
155+
```
156+
LendingClub_ML_App/
157+
├── app/
158+
│ ├── backend/ # Flask API server
159+
│ │ ├── flask_serve.py
160+
│ │ ├── requirements_backend.txt
161+
│ │ └── Dockerfile.backend
162+
│ ├── frontend/ # Dash web application
163+
│ │ ├── app.py
164+
│ │ ├── constants/
165+
│ │ ├── requirements_frontend.txt
166+
│ │ └── Dockerfile.frontend
167+
│ └── data/ # ML models and datasets
168+
├── notebooks/ # Jupyter notebooks for EDA
169+
├── presentation/ # Project presentation materials
170+
├── docker-compose.yml # Multi-container orchestration
171+
└── build_e2e.sh # End-to-end build script
172+
```
173+
174+
### Contributing
175+
176+
1. Fork the repository
177+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
178+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
179+
4. Push to the branch (`git push origin feature/amazing-feature`)
180+
5. Open a Pull Request
54181

55-
## Dataset
56-
- See [Kaggle dataset](https://www.kaggle.com/datasets/ethon0426/lending-club-20072020q1)
182+
## 📚 Resources
57183

184+
- **Dataset**: [LendingClub 2007-2020Q1](https://www.kaggle.com/datasets/ethon0426/lending-club-20072020q1)
185+
- **Blog Post**: [Predicting Loan Defaults using ML](https://nycdatascience.com/blog/student-works/predicting-loan-defaults-using-machine-learning-classification-models/)
186+
- **Video Presentation**: [YouTube](https://www.youtube.com/watch?v=1U1pIe5-GZ0&ab_channel=NYCDataScienceAcademy)
187+
- **Presentation Slides**: [PDF](./presentation/NYCDSA_Capstone_Presentation_vF.pdf)
58188

59-
## Blog post + live presentation
189+
## 📄 License
60190

61-
- Link to [blog post](https://nycdatascience.com/blog/student-works/predicting-loan-defaults-using-machine-learning-classification-models/)
191+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
62192

63-
- Link to [live presentation](https://www.youtube.com/watch?v=1U1pIe5-GZ0&ab_channel=NYCDataScienceAcademy) (youtube)
193+
## 👨‍💻 Author
64194

195+
**Philippe Heitzmann**
196+
- Email: philheitz6[at]gmail[dot]com
197+
- LinkedIn: [Your LinkedIn Profile]
198+
- GitHub: [@yourusername](https://github.com/yourusername)
65199

66-
## Presentation slides
200+
---
67201

68-
Please refer to **/presentation/NYCDSA_Capstone_Presentation_vF.pdf** for slides of presentation given on January 5th, 2021 to NYCDSA prospective students and alums regarding this project
202+
**Star this repository if you found it helpful!**

env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Environment Configuration
2+
# Copy this file to .env and update the values
3+
4+
# Flask Configuration
5+
FLASK_APP=flask_serve.py
6+
FLASK_ENV=development
7+
SECRET_KEY=your-secret-key-here
8+
9+
# API Configuration
10+
API_HOST=0.0.0.0
11+
API_PORT=5000
12+
API_DEBUG=True
13+
14+
# Frontend Configuration
15+
DASH_HOST=0.0.0.0
16+
DASH_PORT=8050
17+
DASH_DEBUG=True
18+
19+
# Data Paths
20+
DATA_PATH=/app/data
21+
MODEL_PATH=/app/data
22+
23+
# Logging
24+
LOG_LEVEL=INFO
25+
LOG_FILE=app.log
26+
27+
# Security
28+
CORS_ORIGINS=http://localhost:8050,http://127.0.0.1:8050

0 commit comments

Comments
 (0)