"We model credit risk using distance from an ideal borrower, reduce feature noise using PCA, and analyze feature importance using eigenvalues."
"We model credit risk using distance from an ideal borrower, reduce feature noise using PCA, and analyze feature importance using eigenvalues."
This project builds a mathematically rigorous Credit Risk Scoring System using core Linear Algebra techniques. Given a dataset of 20 loan applicants described by 6 financial features, the system computes a composite risk score for each customer, ranks them from safest to riskiest, and visualizes the underlying structure of the data using Principal Component Analysis (PCA).
The approach is entirely interpretable — no black-box ML models. Every score is derived from vector operations, matrix decompositions, and linear equations covered in a standard Linear Algebra syllabus.
| Field | Details |
|---|---|
| Subject | Linear Algebra / Applied Mathematics |
| Topic | Credit Risk Assessment using Linear Algebra |
| Tools Used | Python, NumPy, Matplotlib, Seaborn |
Banks and financial institutions face the challenge of evaluating loan applicants fairly and accurately.
Our Solution: Use Linear Algebra techniques to build a Credit Risk Scoring System that:
| Unit | Concept Used | Application |
|---|---|---|
| Unit 1 | System of Linear Equations (np.linalg.lstsq) |
Weighted Score Calculation via Least Squares |
| Unit 2 | Vector Norms (np.linalg.norm) |
Distance from Ideal Borrower |
| Unit 3 | Eigenvalues & Eigenvectors | Feature Importance Analysis |
| Unit 3 | PCA (Principal Component Analysis) | Dimensionality Reduction / Noise Removal |
The dataset consists of 20 synthetic loan applicants, each described by 6 financial features:
| Feature | Description |
|---|---|
Income |
Annual gross income (USD) |
Expenses |
Annual expenses (USD) |
Credit Score |
FICO-style score (300–850) |
Loan Amount |
Requested loan amount (USD) |
Emp. Years |
Years of continuous employment |
Existing Debt |
Outstanding debt balance (USD) |
All features are normalized to zero mean and unit variance so that features with larger numerical ranges (e.g., Income in USD) do not dominate features with smaller ranges (e.g., Employment Years).
normalized = (X - mean) / std
Features are assigned a polarity vector [+1, -1, +1, -1, +1, -1] to ensure that "higher is better" for positive features (Income, Credit Score, Employment Years) and "lower is better" for negative ones (Expenses, Loan Amount, Existing Debt). The normalized data is multiplied element-wise by this vector.
A target vector b is constructed from derived financial ratios (debt-to-income, loan-to-income, credit quality). The system solves:
A · w ≈ b → w = lstsq(A, b)
This yields a weight vector w that captures how much each feature contributes to creditworthiness. The least-squares solution minimizes the residual error across all 20 customers simultaneously.
An "ideal profile" is constructed as the best observed value across all customers for each feature. The Euclidean distance of each customer from this ideal is computed:
risk_distance[i] = ||aligned[i] - ideal||₂
A larger distance = further from the ideal = higher risk.
The two risk signals (distance score and least-squares score) are min-max normalized and combined with a weighted average:
final_score = minmax(0.6 × norm_distance − 0.4 × norm_ls_score)
Customers are then bucketed into Low Risk, Medium Risk, and High Risk using 33rd and 66th percentile thresholds.
The covariance matrix of the aligned data is computed, and its eigenvalues and eigenvectors are extracted. The top two principal components are used to project the 6-dimensional data into 2D for visualization. The PC1 loading bar chart reveals which original features drive the most variance in the dataset.
The project produces the following outputs:
Console Output
Visualization (3-panel figure)
pip install numpy matplotlib seaborn
python credit_risk_assessment.py
No external data files are needed — the dataset is embedded directly in the script.
credit_risk_assessment/
│
├── credit_risk_assessment.py # Main project script (all steps in one file)
└── README.md # This file
🏆 Risk Ranking (Safest → Riskiest):
Rank Customer Score Label
-------------------------------------
1 C13 0.000 Low Risk
2 C4 0.052 Low Risk
3 C1 0.118 Low Risk
...
19 C6 0.934 High Risk
20 C12 1.000 High Risk
np.linalg.lstsq, np.linalg.eig, np.linalg.norm