Smart Lender: AI-Powered Loan Approval Prediction System ML Guide
Part 5: Interactive Notebook - Exploration & Preprocessing
Open your notebook.ipynb file in VS Code and run the following code cells.
5.1 Understanding Exploratory Data Analysis (EDA)
Exploratory Data Analysis (EDA) is the first phase of any data science project. It allows us to view basic statistical metrics, check distributions, look for missing fields, and visualize relationships between features using correlation matrices.
[JUPYTER CELL 1] Ingesting Data & Stripping Whitespace Quirks
This specific Kaggle dataset contains a common raw data issue: every column header and text value contains a leading whitespace. If left uncleaned, columns like df['education'] will throw key errors. We load the dataset and immediately strip these whitespaces:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Load dataset
df = pd.read_csv('data/loan_approval_dataset.csv')
# Clean leading/trailing spaces from column headers
df.columns = df.columns.str.strip()
# Clean leading/trailing spaces from string text values inside the columns
for col in df.columns:
if df[col].dtype == 'object':
df[col] = df[col].str.strip()
print("Dataset Ingested & Whitespaces Cleaned Successfully!")
print(f"Dataset Shape: {df.shape} (Rows, Columns)")
print("\nFirst 5 Records:")
print(df.head())
5.2 Line-by-Line Code Breakdown & Real-World Analogy (Cell 1)
Let’s understand exactly what each block in this cell accomplishes:
import pandas as pd: Imports the Pandas library, renaming it topdfor brevity. Think of Pandas as Python’s version of Microsoft Excel. It allows us to view and manipulate tabular data sheets (called DataFrames).df = pd.read_csv('data/loan_approval_dataset.csv'): Opens the raw spreadsheet and loads it into memory as a DataFrame nameddf.df.columns = df.columns.str.strip(): Trims trailing and leading spaces from column headers.- Real-world analogy: Imagine a file cabinet folder labeled
" cibil_score ". If you search for it by typing"cibil_score", the system won’t find it because of the hidden spaces. This command strips those spaces away, leaving clean folders likecibil_score.
- Real-world analogy: Imagine a file cabinet folder labeled
df[col] = df[col].str.strip(): Trims spaces from string values inside the columns. This cleans values like" Approved"to"Approved".df.head(): Displays the top 5 rows of our virtual spreadsheet so we can visually inspect the layout.
[JUPYTER CELL 2] Statistical Summaries & Data Quality Audits
We inspect statistical ranges, audit missing values, and check for duplicate rows:
print("Data Summary Statistics:")
print(df.describe())
print("\nMissing Values per Feature:")
print(df.isnull().sum())
print("\nTarget Class Distribution:")
print(df['loan_status'].value_counts(normalize=True) * 100)
5.3 Line-by-Line Code Breakdown & Real-World Analogy (Cell 2)
Let’s look at how we audit our data quality in this cell:
df.describe(): Generates statistical metrics for every numeric column (including the mean, standard deviation, minimum value, maximum value, and quartiles).- Real-world analogy: Imagine a school principal reviewing a report card summary. This tells us that CIBIL scores range from 300 to 900, with a mean score around 599.
df.isnull().sum(): Checks for empty cells (NaNvalues) and outputs the total count for each column.- Real-world analogy: Checking an application form to ensure the applicant didn’t leave any fields blank. Machine learning algorithms cannot calculate blank values and will crash if they encounter them.
df['loan_status'].value_counts(...): Calculates the percentage ratio of approved vs. rejected loans.- What it shows: It outputs approximately 61.8% Approved and 38.2% Rejected. This is a very healthy balance, meaning our model will have plenty of positive and negative examples to learn from.
[JUPYTER CELL 3] Correlation Heatmap of Financial Features
We compute and plot the linear relationships between numeric variables:
plt.figure(figsize=(10, 8))
numeric_cols = df.select_dtypes(include=[np.number]).drop(columns=['loan_id'])
sns.heatmap(numeric_cols.corr(), annot=True, cmap='coolwarm', fmt=".2f")
plt.title('Correlation Heatmap of Financial Features')
plt.show()
5.4 Line-by-Line Code Breakdown & Real-World Analogy (Cell 3)
Let’s understand how variables relate to each other:
numeric_cols = df.select_dtypes(...): Filters the dataset, keeping only numeric columns (integers/floats) and dropping the uniqueloan_idsince it’s just a sequence index.numeric_cols.corr(): Computes the Pearson Correlation coefficient matrix. A value close to1.0means strong positive correlation (when feature A rises, feature B also rises), while0means no connection.sns.heatmap(..., annot=True): Draws the matrix as a colored grid.- Real-world analogy: Think of a weather radar map. Red/warm blocks indicate high correlation (e.g.,
income_annumandluxury_assets_valueshow a high correlation of 0.92, indicating that higher earners predictably accumulate more luxury items). Blue/cool blocks represent weak or negative connections.
- Real-world analogy: Think of a weather radar map. Red/warm blocks indicate high correlation (e.g.,
[JUPYTER CELL 4] Split, Label Encode, Scale, and Train Baseline Model
We split our features, encode categorical text variables, scale numerical ranges to prevent bias, and train a baseline Random Forest:
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, accuracy_score
# Drop redundant identifiers
X = df.drop(columns=['loan_id', 'loan_status'])
y = df['loan_status']
# Label encode categorical text columns
le = LabelEncoder()
cat_cols = ['education', 'self_employed']
for col in cat_cols:
X[col] = le.fit_transform(X[col])
# Encode target values ('Approved' -> 0, 'Rejected' -> 1)
y = y.map({'Approved': 0, 'Rejected': 1})
# Train-Test Split (80% training, 20% validation testing)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Fit and apply StandardScaler to normalize continuous ranges
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Train a baseline Random Forest Classifier
clf = RandomForestClassifier(random_state=42, n_estimators=100)
clf.fit(X_train_scaled, y_train)
# Evaluate
y_pred = clf.predict(X_test_scaled)
print(f"Baseline Accuracy: {accuracy_score(y_test, y_pred) * 100:.2f}%")
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
5.5 Line-by-Line Code Breakdown & Real-World Analogy (Cell 4)
Let’s inspect our model preparation and training steps:
X = df.drop(...)andy = df[...]: Separates our questions (featuresXlike income and asset values) from our answer key (the targetyrepresenting loan status).le.fit_transform(X[col]): Converts text parameters into integers (e.g.,'Graduate'becomes0,'Not Graduate'becomes1).- Why we do it: Machine learning algorithms are mathematical calculators—they cannot subtract or multiply string text words, so we must encode them into numerical values.
train_test_split(..., test_size=0.2, stratify=y): Partitions our dataset. The model trains on 80% of applications, and we reserve 20% to test its predictive performance on unseen applicants. Thestratify=yflag ensures both subsets preserve identical approved/rejected ratios.StandardScaler(): Normalizes feature scales.- Real-world analogy: Imagine comparing a student’s grade out of 100 (e.g. 85%) to another student’s grade out of 10 (e.g. 9/10). To evaluate them fairly, you must scale both scores to percentages. In our data,
income_annumhas values in millions, whileno_of_dependentshas values like1or2. Scaling prevents the model from assuming income is more important simply because its numbers are larger.
- Real-world analogy: Imagine comparing a student’s grade out of 100 (e.g. 85%) to another student’s grade out of 10 (e.g. 9/10). To evaluate them fairly, you must scale both scores to percentages. In our data,
RandomForestClassifier(n_estimators=100): Builds an ensemble model consisting of 100 independent decision trees.- Real-world analogy: Instead of relying on a single bank manager to make the loan decision, we ask 100 managers to look at the application and vote, taking the majority decision as the final approval state.