import streamlit as st import joblib import numpy as np st.set_page_config(page_title="Loan Default Predictor", layout="centered") st.title("Loan Default Predictor — Give Me Some Credit") st.write("Enter applicant features below and click **Predict** to get `SeriousDlqin2yrs` prediction.") @st.cache_resource def load_model(path="model.pkl"): return joblib.load(path) try: model = load_model("model.pkl") except Exception as e: st.error(f"Unable to load model.pkl — check file path. Error: {e}") st.stop() st.subheader("Applicant features") col1, col2 = st.columns(2) with col1: RevolvingUtilizationOfUnsecuredLines = st.number_input( "Revolving Utilization Of Unsecured Lines", value=0.769413, format="%.6f" ) age = st.number_input("age", value=32, min_value=18, max_value=120, step=1) NumberOfTime30_59DaysPastDueNotWorse = st.number_input( "Number Of Time 30-59 Days Past Due Not Worse", value=2, step=1 ) DebtRatio = st.number_input("DebtRatio", value=0.161342, format="%.6f") MonthlyIncome = st.number_input("MonthlyIncome", value=45000.0, format="%.2f") with col2: NumberOfOpenCreditLinesAndLoans = st.number_input( "Number Of Open Credit Lines And Loans", value=6.0, step=1.0 ) NumberOfTimes90DaysLate = st.number_input( "Number Of Times 90 Days Late", value=1.0, step=1.0 ) NumberRealEstateLoansOrLines = st.number_input( "Number Real Estate Loans Or Lines", value=6.0, step=1.0 ) NumberOfTime60_89DaysPastDueNotWorse = st.number_input( "Number Of Time 60-89 Days Past Due Not Worse", value=0.0, step=1.0 ) NumberOfDependents = st.number_input( "Number Of Dependents", value=0.999883, format="%.6f" ) col3, col4 = st.columns(2) with col3: TotalPastDue = st.number_input("Total Past Due", value=2.0, step=1.0) DebtRatioPerDependent = st.number_input("DebtRatio Per Dependent", value=25.1344) UtilizationPerLine = st.number_input("Utilization Per Line", value=0.217371) with col4: IncomeDebtRatio = st.number_input("IncomeDebtRatio", value=3003.393701) HasDependents = st.selectbox("HasDependents", options=[0, 1], index=1) HighDebtRatio = st.selectbox("HighDebtRatio", options=[0, 1], index=0) HighUtilization = st.selectbox("HighUtilization", options=[0, 1], index=0) feature_order = [ RevolvingUtilizationOfUnsecuredLines, age, NumberOfTime30_59DaysPastDueNotWorse, DebtRatio, MonthlyIncome, NumberOfOpenCreditLinesAndLoans, NumberOfTimes90DaysLate, NumberRealEstateLoansOrLines, NumberOfTime60_89DaysPastDueNotWorse, NumberOfDependents, TotalPastDue, DebtRatioPerDependent, UtilizationPerLine, IncomeDebtRatio, HasDependents, HighDebtRatio, HighUtilization, ] X_input = np.array(feature_order).reshape(1, -1) if st.button("Predict"): try: pred = model.predict(X_input)[0] except Exception as e: st.error(f"Prediction failed. Check feature order/types. Error: {e}") st.stop() label_map = {0: "No Default (Good Credit)", 1: "Default (High Risk)"} meaning = label_map.get(int(pred), str(pred)) proba_str = "" try: proba = model.predict_proba(X_input)[0] if len(proba) == 2: proba_str = f" — P(Default) = {proba[1]:.4f}" else: proba_str = " — probabilities: " + ", ".join(f"{p:.4f}" for p in proba) except Exception: proba_str = "" if int(pred) == 1: st.error(f"Prediction: {pred} → {meaning}{proba_str}") else: st.success(f"Prediction: {pred} → {meaning}{proba_str}") with st.expander("Show raw inputs and model output"): st.write("Input vector (order):", feature_order) st.write("Raw prediction:", int(pred)) if proba_str: st.write("Raw probabilities:", proba if 'proba' in locals() else None) st.caption("Model expects features in a specific order. If predictions seem off, verify the feature order and preprocessing used during training.")