File size: 5,424 Bytes
047d6a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import streamlit as st
import numpy as np
import pickle  # Change: 'pickle' imported instead of 'joblib'
from tensorflow.keras.models import load_model

# --- Load Model and Scaler ---
@st.cache_resource
def load_keras_model():
    """Load the saved Keras model."""
    try:
        model = load_model("model_churn.keras")
        return model
    except Exception as e:
        st.error(f"Error loading Keras model (model_churn.keras): {e}")
        return None

# ----- START: UPDATED SECTION -----
@st.cache_resource
def load_scaler_model():
    """Load the saved Scaler (pickle)."""
    try:
        # Pickle files must be opened in 'rb' (read binary) mode
        with open("scaler_churn", "rb") as f:
            scaler = pickle.load(f)
        return scaler
    except FileNotFoundError:
        st.error("Error: 'scaler_churn' file not found. Please make sure the file is uploaded.")
        return None
    except Exception as e:
        st.error(f"Error loading Scaler (scaler_churn): {e}")
        return None
# ----- END: UPDATED SECTION -----

# Load models
model = load_keras_model()
scaler = load_scaler_model()

# Order of the 11 features expected by your model/scaler
MODEL_INPUT_COLUMNS_ORDER = [
    'CreditScore', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard',
    'IsActiveMember', 'EstimatedSalary', 'Geography_Germany', 'Geography_Spain',
    'Gender_Male'
]

# --- User Interface (UI) ---
st.set_page_config(page_title="Customer Churn Prediction", layout="wide")
st.title("🏦 Customer Churn Prediction Model")

col1, col2 = st.columns([1, 1])

with col1:
    st.header("Customer Information")
    st.caption("Please enter customer information.")
    
    geography = st.selectbox("Country", ("France", "Spain", "Germany"), index=0)
    gender = st.radio("Gender", ("Female", "Male"), index=0)
    has_cr_card = st.radio("Has Credit Card?", ("Yes", "No"), index=0)
    is_active_member = st.radio("Active Member?", ("Yes", "No"), index=0)
    
    credit_score = st.number_input("Credit Score", min_value=300, max_value=900, value=619)
    age = st.number_input("Age", min_value=18, max_value=100, value=42)
    tenure = st.number_input("Tenure (Years)", min_value=0, max_value=10, value=2)
    balance = st.number_input("Balance", value=0.00, format="%.2f")
    num_of_products = st.number_input("Number of Products", min_value=1, max_value=4, value=1)
    estimated_salary = st.number_input("Estimated Salary", value=101348.88, format="%.2f")

    predict_button = st.button("Calculate Risk", type="primary")

with col2:
    st.header("Prediction Result")
    st.caption("Model's churn probability prediction.")

    if predict_button:
        if model is None or scaler is None:
            st.error("Models could not be loaded. Please contact administrator.")
        else:
            try:
                # --- Step 1: Collect All Raw Inputs in a Dictionary ---
                raw_data_dict = {
                    'CreditScore': credit_score,
                    'Age': age,
                    'Tenure': tenure,
                    'Balance': balance,
                    'NumOfProducts': float(num_of_products),
                    'HasCrCard': 1.0 if has_cr_card == "Yes" else 0.0,
                    'IsActiveMember': 1.0 if is_active_member == "Yes" else 0.0,
                    'EstimatedSalary': estimated_salary,
                    'Geography_Germany': 1.0 if geography == "Germany" else 0.0,
                    'Geography_Spain': 1.0 if geography == "Spain" else 0.0,
                    'Gender_Male': 1.0 if gender == "Male" else 0.0
                }
                
                # --- Step 2: Order Data According to Model's Expected Order ---
                raw_input_features = [raw_data_dict[col] for col in MODEL_INPUT_COLUMNS_ORDER]
                raw_input_array = np.array(raw_input_features).reshape(1, -1)
                
                # --- Step 3: Scaling ---
                scaled_input_array = scaler.transform(raw_input_array)
                
                # --- Step 4: Make Prediction ---
                with st.spinner("Model running, making prediction..."):
                    prediction_proba = model.predict(scaled_input_array)[0][0]
                    churn_probability_percent = prediction_proba * 100
                    threshold = 50.0

                    # --- Step 5: Display Result ---
                    if churn_probability_percent > threshold:
                        st.error(f"Customer Churn Probability: {churn_probability_percent:.2f}%")
                        st.warning("This customer has HIGH churn risk. 🚨")
                    else:
                        st.success(f"Customer Churn Probability: {churn_probability_percent:.2f}%")
                        st.info("This customer has LOW churn risk. ✅")
                
                with st.expander("Processed (Scaled) Data Seen by Model"):
                    scaled_features_list = scaled_input_array.flatten().tolist()
                    st.json({col: val for col, val in zip(MODEL_INPUT_COLUMNS_ORDER, scaled_features_list)})
                
                with st.expander("Raw Data Entered to Scaler (for verification)"):
                    st.json({col: val for col, val in zip(MODEL_INPUT_COLUMNS_ORDER, raw_input_features)})

            except Exception as e:
                st.error(f"An error occurred during prediction: {e}")