| import streamlit as st |
| import pandas as pd |
| import numpy as np |
| import joblib |
| import xgboost as xgb |
|
|
| st.set_page_config( |
| page_title="Customer Satisfaction Prediction", |
| page_icon="👤", |
| layout="centered") |
|
|
| st.title("👤 Customer Satisfaction Prediction") |
| st.markdown(""" |
| Enter the key financial details below to predict if a specific customer will be **Satisfied** or **Unsatisfied**. |
| *Note: Only the top influential features are shown for manual input. Others are set to default values.* |
| """) |
|
|
| |
| @st.cache_resource |
| def load_model(): |
| try: |
| model = joblib.load('src/xgb_model.pkl') |
| return model |
| except FileNotFoundError: |
| st.error("Model file (xgb_model.pkl) not found.") |
| return None |
|
|
| model = load_model() |
|
|
| |
| if model: |
| booster = model.get_booster() |
| all_features = booster.feature_names |
| |
| importance_map = booster.get_score(importance_type='gain') |
| sorted_features = sorted(importance_map.items(), key=lambda x: x[1], reverse=True) |
| top_feature_names = [f[0] for f in sorted_features[:10]] |
| |
| if 'var15' not in top_feature_names and 'var15' in all_features: |
| top_feature_names.insert(0, 'var15') |
|
|
| |
|
|
| st.sidebar.header("Customer Profile") |
| st.sidebar.write("Adjust the values below:") |
|
|
| user_inputs = {} |
|
|
| if model: |
| for col in top_feature_names: |
| label = col |
| default_val = 0.0 |
| min_val = 0.0 |
| max_val = 1000000.0 |
| step = 1.0 |
| |
| if col == 'var15': |
| label = "Customer Age" |
| default_val = 23.0 |
| min_val = 5.0 |
| max_val = 105.0 |
| elif col == 'saldo_var30': |
| label = "Account Balance" |
| default_val = 0.0 |
| elif col == 'var38': |
| label = "Mortgage Value" |
| default_val = 117310.97 |
| |
| val = st.sidebar.number_input( |
| label=label, |
| min_value=float(min_val) if col == 'var15' else None, |
| value=float(default_val), |
| step=step) |
| user_inputs[col] = val |
|
|
| |
|
|
| col1, col2 = st.columns([1, 2]) |
|
|
| with col1: |
| st.image("https://cdn-icons-png.flaticon.com/512/1077/1077114.png", width=150) |
|
|
| with col2: |
| st.subheader("Predict") |
| predict_btn = st.button("Calculate Satisfaction Score", type="primary") |
|
|
| if predict_btn and model: |
| input_data = {feature: 0 for feature in all_features} |
| |
| for key, value in user_inputs.items(): |
| if key in input_data: |
| input_data[key] = value |
| |
| if 'var3' in input_data and 'var3' not in user_inputs: |
| input_data['var3'] = 2 |
| |
| df_single = pd.DataFrame([input_data]) |
| |
| df_single = df_single[all_features] |
| |
| with st.spinner("Analyzing customer profile..."): |
| prob = model.predict_proba(df_single)[:, 1][0] |
| prediction = (prob > 0.5).astype(int) |
| |
| st.divider() |
| |
| col_res1, col_res2 = st.columns(2) |
| |
| col_res1.metric( |
| label="Unhappiness Probability", |
| value=f"{prob:.2%}", |
| delta="High Risk" if prob > 0.5 else "Low Risk", |
| delta_color="inverse") |
| |
| if prediction == 0: |
| col_res2.success("✅ Prediction: **SATISFIED** (Happy)") |
| st.balloons() |
| else: |
| col_res2.error("⚠️ Prediction: **UNSATISFIED** (Unhappy)") |
| st.warning("This customer is at high risk of churning or filing a complaint.") |
|
|
| with st.expander("See raw input data used for model"): |
| st.write(df_single) |
|
|
| elif not model: |
| st.warning("Please upload the 'xgb_model.pkl' file to the Space.") |