import streamlit as st import joblib import numpy as np from huggingface_hub import hf_hub_download # Page configuration st.set_page_config( page_title="Loan Approval System", page_icon="🏦", layout="centered", initial_sidebar_state="collapsed" ) # Custom CSS for styling with the specified color theme st.markdown(""" """, unsafe_allow_html=True) # App header with logo col1, col2 = st.columns([1, 5]) with col1: st.markdown('
🏦
', unsafe_allow_html=True) with col2: st.title("AI-Powered Loan Approval System") st.markdown('

Fast and reliable loan approval decisions

', unsafe_allow_html=True) # Load the trained model from Hugging Face @st.cache_resource def load_model(): model_path = hf_hub_download(repo_id="ifiecas/LoanApproval-DT-v1.0", filename="best_pruned_dt.pkl") return joblib.load(model_path) model = load_model() # Initialize session state for restart functionality if 'restart_clicked' not in st.session_state: st.session_state.restart_clicked = False # Create tabs for better organization tab1, tab2 = st.tabs(["Loan Application", "About the System"]) with tab1: # Reset all form values if restart was clicked if st.session_state.restart_clicked: st.session_state.restart_clicked = False # Reset flag # Add any other reset logic here if needed # Note: Streamlit will reset most inputs automatically on rerun # Personal Information Section st.markdown('

Personal Information

', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: gender = st.selectbox("Gender", ["Male", "Female"]) education = st.selectbox("Education Level", ["Graduate", "Under Graduate"]) with col2: marital_status = st.selectbox("Marital Status", ["Married", "Not Married"]) number_of_dependents = st.number_input("Number of Dependents", min_value=0, max_value=10, value=0) self_employed = st.selectbox("Self-Employed", ["No", "Yes"]) st.markdown('
', unsafe_allow_html=True) # Financial Details Section st.markdown('

Financial Details

', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: applicant_income = st.number_input("Monthly Income ($)", min_value=0, value=5000) loan_amount = st.number_input("Loan Amount ($)", min_value=0, value=100000) credit_history = st.selectbox("Credit History Status", [1, 0], format_func=lambda x: "No existing unsettled loans (1)" if x == 1 else "Have unsettled loans (0)") with col2: coapplicant_income = st.number_input("Co-Applicant's Income ($)", min_value=0) loan_term = st.slider("Loan Term (months)", min_value=12, max_value=360, value=180, step=12) location = st.selectbox("Property Location", ["Urban", "Semiurban", "Rural"]) st.markdown('
', unsafe_allow_html=True) # Summary section st.markdown('

Application Summary

', unsafe_allow_html=True) total_income = applicant_income + coapplicant_income # Calculate monthly payment (simplified calculation) interest_rate = 0.05 # Assuming 5% annual interest rate monthly_interest = interest_rate / 12 num_payments = loan_term # Monthly payment using the loan amortization formula if monthly_interest == 0 or num_payments == 0: monthly_payment = 0 else: monthly_payment = loan_amount * (monthly_interest * (1 + monthly_interest) ** num_payments) / \ ((1 + monthly_interest) ** num_payments - 1) # Calculate proper Debt-to-Income ratio (monthly payment / monthly income) dti = (monthly_payment / total_income) if total_income > 0 else 0 dti_percent = dti * 100 col1, col2, col3 = st.columns(3) col1.metric("Total Monthly Income", f"${total_income:,}") col2.metric("Estimated Monthly Payment", f"${monthly_payment:.2f}") col3.metric("Loan Term", f"{loan_term//12} years") # Create DTI visualization section st.markdown("

Debt-to-Income Assessment

", unsafe_allow_html=True) # Cap the displayed percentage at 100% for the visual display_percent = min(dti_percent, 100) # Determine the status and color if dti_percent <= 36: dti_status = "Good" dti_color = "#4CAF50" # Green emoji = "✅" elif dti_percent <= 43: dti_status = "Moderate" dti_color = "#FF9800" # Orange emoji = "⚠️" else: dti_status = "High" dti_color = "#F44336" # Red emoji = "❗" # Create a visual progress bar st.markdown(f"""
0% 50% 100%+
""", unsafe_allow_html=True) # Show a simple explanation of DTI with actual values if dti_percent > 100: st.markdown(f"""
{emoji} Your monthly payment (${monthly_payment:.2f}) would be {dti_percent/100:.1f}× your monthly income (${total_income:,})

Most lenders require this to be below 43% for approval

""", unsafe_allow_html=True) else: st.markdown(f"""
{emoji} Your monthly payment (${monthly_payment:.2f}) would be {dti_percent:.1f}% of your monthly income (${total_income:,})

Most lenders require this to be below 43% for approval

""", unsafe_allow_html=True) # Add eligibility check section st.markdown('

Loan Eligibility Check

', unsafe_allow_html=True) eligibility_issues = [] # Check minimum income threshold (example: $1500/month) if total_income < 1500: eligibility_issues.append("⚠️ Total monthly income below minimum requirement ($1,500)") # Check if DTI is too high (above 43% is typically problematic) if dti_percent > 43: eligibility_issues.append("⚠️ Debt-to-income ratio exceeds maximum threshold (43%)") # Credit history is critical if credit_history == 0: eligibility_issues.append("⚠️ Existing unsettled loans may affect approval odds") # Display eligibility issues if any if eligibility_issues: st.markdown('
', unsafe_allow_html=True) st.markdown("

Potential eligibility concerns:

", unsafe_allow_html=True) for issue in eligibility_issues: st.markdown(f"

{issue}

", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) else: st.markdown('
', unsafe_allow_html=True) st.markdown("

No obvious eligibility concerns

", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) # Prediction and restart buttons col1, col2 = st.columns([3, 1]) with col1: predict_button = st.button("Check Loan Approval Status", use_container_width=True) with col2: restart_button = st.button("🔄 Restart", use_container_width=True, help="Reset all form fields and start over") def preprocess_input(): # Convert categorical inputs to numerical format based on encoding reference gender_num = 0 if gender == "Male" else 1 marital_status_num = 0 if marital_status == "Not Married" else 1 education_num = 0 if education == "Under Graduate" else 1 self_employed_num = 0 if self_employed == "No" else 1 credit_history_num = credit_history # Already numerical (0,1) # One-Hot Encoding for Location location_semiurban = 1 if location == "Semiurban" else 0 location_urban = 1 if location == "Urban" else 0 # Convert Term from months to years term_years = loan_term / 12 # Compute Derived Features - use the same monthly payment calculated above debt_to_income = monthly_payment / total_income if total_income > 0 else 0 credit_amount_interaction = loan_amount * credit_history_num # Interaction effect income_term_ratio = total_income / term_years if term_years > 0 else 0 # Avoid divide by zero # Return array with all 16 features return np.array([[ gender_num, marital_status_num, number_of_dependents, education_num, self_employed_num, applicant_income, coapplicant_income, loan_amount, credit_history_num, total_income, debt_to_income, location_semiurban, location_urban, term_years, credit_amount_interaction, income_term_ratio ]]) # Handle restart button click if restart_button: st.session_state.restart_clicked = True st.rerun() # Using st.rerun() instead of st.experimental_rerun() # Display prediction if predict_button: with st.spinner("Processing your application..."): input_data = preprocess_input() prediction = model.predict(input_data) # Apply additional rules to override the model in certain cases manual_rejection = False rejection_reason = "" # Rule-based rejections that override the model if total_income < 1500: manual_rejection = True rejection_reason = "Insufficient income (below $1,500 monthly minimum)" elif dti_percent > 50: # Very high DTI is an automatic rejection manual_rejection = True rejection_reason = "Debt-to-income ratio too high (exceeds 50%)" elif credit_history == 0 and dti_percent > 35: manual_rejection = True rejection_reason = "Combination of unsettled loans and high debt-to-income ratio" # Final decision combines model prediction and manual eligibility checks final_approval = (prediction[0] == 1) and not manual_rejection # Show result with enhanced styling if final_approval: st.markdown("""

✅ Loan Approved

Congratulations! Based on your information, you're eligible for this loan.

""", unsafe_allow_html=True) else: st.markdown(f"""

❌ Loan Not Approved

Unfortunately, based on your current information, we cannot approve your loan application.

Primary reason: {rejection_reason if manual_rejection else "Multiple factors considered by our approval algorithm"}

Consider improving your credit score, reducing existing debt, or applying with a co-applicant with higher income.

""", unsafe_allow_html=True) with tab2: st.markdown("""

About the Loan Approval System

This AI-powered system uses advanced machine learning algorithms to determine loan approval eligibility based on multiple factors.

""", unsafe_allow_html=True) st.markdown("

How it works

", unsafe_allow_html=True) st.write("The system analyzes various factors including:") st.markdown(""" - Personal and financial information - Credit history status - Loan amount and term - Income and employment status - Debt-to-income ratio """) st.write(""" Our decision engine combines a trained machine learning model with industry-standard lending criteria. The system evaluates your application against patterns from thousands of previous loan applications while also applying standard financial rules used by major lenders. """) st.markdown('
', unsafe_allow_html=True) st.markdown("

Important Factors for Approval

", unsafe_allow_html=True) st.write("To maximize your chances of approval:") st.markdown(""" - Maintain a debt-to-income ratio below 43% - Have sufficient monthly income (minimum $1,500) - Clear existing unsettled loans when possible - Consider adding a co-applicant to strengthen your application """) st.markdown('
', unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) st.markdown("

Key Features

", unsafe_allow_html=True) st.write("Our system provides:") st.markdown(""" - Instant loan approval decisions - Transparent evaluation process - Detailed eligibility assessment - Secure data handling """) st.markdown('
', unsafe_allow_html=True) # Footer st.markdown(""" """, unsafe_allow_html=True)