Machine Learning Loan Approval Prediction Project

Machine Learning project 10

Machine Learning Loan Approval Prediction Project

Build and evaluate a complete loan approval prediction workflow with reproducible Python code, explicit metrics, and honest limitations.

Explore Machine Learning training in VizagView all project ideas

Dataset and objective

A reproducibly generated table of income, requested amount, credit score, employment type, debt ratio, and a synthetic approval label.

Skills practised

  • Mixed tabular features
  • ColumnTransformer
  • One-hot encoding
  • Responsible-use limits

Requirements

  • Python 3.10 or later
  • A terminal or command prompt
  • python -m pip install numpy pandas scikit-learn
  • About 45-60 minutes to build and review

Machine Learning workflow

  1. Data: A reproducibly generated table of income, requested amount, credit score, employment type, debt ratio, and a synthetic approval label.
  2. Preprocessing: ColumnTransformer scales numeric fields and one-hot encodes employment type without leaking holdout information.
  3. Model: LogisticRegression estimates a synthetic binary target.
  4. Evaluation: ROC AUC and a precision/recall/F1 classification report on a stratified holdout set.

Complete Python code

Save the code as ml_loan_approval_prediction.py. The random state and data handling are included so the result can be reproduced and reviewed.

"""Demonstrate a loan-approval pipeline on explicitly synthetic data."""

from __future__ import annotations

import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler


def make_demo_data(rows: int = 3000, random_state: int = 42) -> pd.DataFrame:
    rng = np.random.default_rng(random_state)
    income = rng.lognormal(mean=10.7, sigma=0.45, size=rows)
    loan_amount = rng.uniform(50_000, 900_000, rows)
    credit_score = np.clip(rng.normal(690, 70, rows), 300, 850)
    employment = rng.choice(["salaried", "self-employed"], rows, p=[0.7, 0.3])
    debt_ratio = rng.uniform(0.05, 0.75, rows)
    logit = -1.5 + 0.006 * (credit_score - 650) + 0.00002 * income - 2.8 * debt_ratio - 0.000001 * loan_amount
    probability = 1 / (1 + np.exp(-logit))
    approved = rng.binomial(1, probability)
    return pd.DataFrame({
        "income": income,
        "loan_amount": loan_amount,
        "credit_score": credit_score,
        "employment": employment,
        "debt_ratio": debt_ratio,
        "approved": approved,
    })


def train_model(random_state: int = 42):
    data = make_demo_data(random_state=random_state)
    x = data.drop(columns="approved")
    y = data["approved"]
    x_train, x_test, y_train, y_test = train_test_split(
        x, y, test_size=0.25, random_state=random_state, stratify=y
    )
    numeric = ["income", "loan_amount", "credit_score", "debt_ratio"]
    categorical = ["employment"]
    preprocessing = ColumnTransformer([
        ("numeric", StandardScaler(), numeric),
        ("categorical", OneHotEncoder(handle_unknown="ignore"), categorical),
    ])
    model = make_pipeline(preprocessing, LogisticRegression(max_iter=2000, random_state=random_state))
    model.fit(x_train, y_train)
    predictions = model.predict(x_test)
    probabilities = model.predict_proba(x_test)[:, 1]
    return model, y_test, predictions, probabilities


def main() -> None:
    _, y_test, predictions, probabilities = train_model()
    print("Synthetic Loan Approval Demonstration")
    print(f"ROC AUC: {roc_auc_score(y_test, probabilities):.3f}")
    print(classification_report(y_test, predictions, zero_division=0))
    print("Synthetic education only—not a lender policy, eligibility decision, or fair-lending validation.")


if __name__ == "__main__":
    main()

How the pipeline works

ColumnTransformer scales numeric fields and one-hot encodes employment type without leaking holdout information.

LogisticRegression estimates a synthetic binary target. ROC AUC and a precision/recall/F1 classification report on a stratified holdout set.

Run the project

  1. Create and activate a virtual environment.
  2. Install the dependencies with python -m pip install numpy pandas scikit-learn.
  3. Run python ml_loan_approval_prediction.py.
  4. Review every printed metric together with the limitation below; a single score never proves deployment readiness.

How to interpret the evaluation

Classification projects report class-aware metrics so majority classes do not hide weak performance. Regression projects report errors in target units and include R-squared or a simple baseline where appropriate. Always verify the split strategy matches how new data will arrive.

Accuracy, ethics, and safety limits

Synthetic education only—not a lender policy, eligibility decision, credit recommendation, or fair-lending validation. Real lending requires law, governance, explanations, adverse-action processes, and bias testing.

Ways to extend the project

Test calibration, remove sensitive proxies, conduct subgroup error analysis with qualified reviewers, compare transparent scorecards, and document every data source.

Continue learning Machine Learning

Try the next project, return to the Softenant project library, or explore the Machine Learning course in Vizag for guided data preparation, model evaluation, and portfolio feedback.