zaheerjk's picture
Upload 17 files
785ee14 verified
Raw
History Blame Contribute Delete
7.29 kB
import streamlit as st
import pandas as pd
import numpy as np
import joblib
from sklearn.preprocessing import StandardScaler
@st.cache_data
def load_data(path='Data/Customer-Churn.csv'):
df=pd.read_csv(path)
return df
@st.cache_resource
def build_preprocessor(df):
telco=df.copy()
telco['TotalCharges']=pd.to_numeric(telco['TotalCharges'],errors='coerce')
telco.dropna(how='any',inplace=True)
bins=[0,12,24,36,48,60,72]
labels=['1-12','13-24','25-36','37-48','49-60','61-72']
telco['tenure_bin']=pd.cut(telco['tenure'],labels=labels,bins=bins,include_lowest=True)
x_template=telco.drop(columns=['customerID','Churn','tenure'])
x_template=pd.get_dummies(x_template,drop_first=True)
scaler=StandardScaler()
scaler.fit(x_template)
print(f"[DEBUG] build_preprocessor : template_cols={x_template.shape[1]},template_rows={x_template.shape[0]}")
return {
'template_columns':list(x_template.columns),
'scaler':scaler,
'tenure_bins':(bins,labels),
'sample_df':telco
}
def preprocessor_input(user_input,prep):
df_in=pd.DataFrame([user_input])
bins,labels=prep['tenure_bins']
df_in['tenure_bin']=pd.cut(df_in['tenure'],bins=bins,labels=labels,include_lowest=True)
df_in=df_in.drop(columns=['tenure'])
df_in_enc=pd.get_dummies(df_in,drop_first=True)
template_cols=prep['template_columns']
df_in_enc=df_in_enc.reindex(columns=template_cols,fill_value=0)
scaler=prep['scaler']
x_scaled=scaler.transform(df_in_enc)
nonzero=[(col,int(val)) for col,val in zip(prep['template_columns'] ,df_in_enc.iloc[0]) if val!=0]
print(f"[DEBUG] Preprocess_input : nonzero_dummies={nonzero[:10]}")
print(f"[DEBUG] preprocess_input: x_scaled_shape={x_scaled.shape},first10={x_scaled.flatten()[:10].tolist()}")
return x_scaled
@st.cache_resource
def load_model(path='Models/Ada_boost_churn_model.pkl'):
print(f"[DEBUG] Load Model /; Loading model From {path}")
model=joblib.load(path)
print(f"[DEBUG] load_model : Model Type = {type(model)}")
return model
def main():
st.set_page_config(
page_title="Telecom Customer Churn Prediction",
page_icon="πŸ“±",
layout="wide"
)
st.title("πŸ“± Telecom Customer Churn Prediction")
st.markdown(
"Predict whether a telecom customer is likely to churn based on customer, account, and billing information."
)
st.divider()
df = load_data()
prep = build_preprocessor(df)
model = load_model()
sample = prep["sample_df"]
with st.form("input_form"):
st.subheader("πŸ“ Customer Details")
user_input = {}
with st.expander("πŸ‘€ Customer Information", expanded=True):
col1, col2 = st.columns(2)
with col1:
tenure = st.slider(
"Tenure (Months)",
min_value=int(sample["tenure"].min()),
max_value=int(sample["tenure"].max()),
value=12,
)
user_input["tenure"] = tenure
with col2:
if "SeniorCitizen" in sample.columns:
user_input["SeniorCitizen"] = st.selectbox(
"Senior Citizen",
sorted(sample["SeniorCitizen"].unique())
)
st.divider()
st.subheader("πŸ“‹ Account & Billing Information")
cols_to_ask = [
c for c in sample.columns
if c not in [
"customerID",
"Churn",
"tenure",
"tenure_bin",
"SeniorCitizen"
]
]
left, right = st.columns(2)
for i, col in enumerate(cols_to_ask):
target = left if i % 2 == 0 else right
with target:
if pd.api.types.is_numeric_dtype(sample[col]):
minv = float(sample[col].min())
maxv = float(sample[col].max())
default = float(sample[col].median())
if pd.api.types.is_integer_dtype(sample[col]):
minv = int(minv)
maxv = int(maxv)
default = int(default)
user_input[col] = st.number_input(
col.replace("_", " ").title(),
min_value=minv,
max_value=maxv,
value=default,
)
else:
opts = sorted(sample[col].dropna().unique())
user_input[col] = st.selectbox(
col.replace("_", " ").title(),
opts,
)
submitted = st.form_submit_button(
"πŸš€ Predict Churn",
type="primary",
use_container_width=True,
)
if submitted:
x_in = preprocessor_input(user_input, prep)
pred_class = model.predict(x_in)[0]
pred_proba = model.predict_proba(x_in)[0][1]
churn_text = "Yes" if pred_class == 1 else "No"
st.divider()
st.subheader("πŸ“Š Prediction Result")
c1, c2 = st.columns(2)
with c1:
st.metric("Prediction", churn_text)
with c2:
st.metric("Churn Probability", f"{pred_proba*100:.2f}%")
st.progress(float(pred_proba))
if pred_class == 1:
st.error(
f"⚠️ This customer is likely to churn.\n\nProbability: **{pred_proba*100:.2f}%**"
)
else:
st.success(
f"βœ… This customer is likely to stay.\n\nProbability of churn: **{pred_proba*100:.2f}%**"
)
with st.expander("πŸ” Debug Information"):
st.write("### Raw Input")
st.write(user_input)
bins, labels = prep["tenure_bins"]
df_in = pd.DataFrame([user_input])
df_in["tenure_bin"] = pd.cut(
df_in["tenure"],
bins=bins,
labels=labels,
include_lowest=True,
)
st.write("### Input After tenure_bin")
st.write(df_in)
df_in_enc = pd.get_dummies(df_in.drop(columns=["tenure"]), drop_first=True)
df_reindexed = df_in_enc.reindex(
columns=prep["template_columns"],
fill_value=0,
)
st.write("### Reindexed Features")
st.write(df_reindexed)
st.write("### Scaled Features (First 20)")
st.write(x_in.flatten()[:20].tolist())
st.success("Prediction Completed Successfully βœ…")
st.divider()
st.info(
"This application reproduces the same preprocessing used during model training, "
"including tenure binning, one-hot encoding (drop_first=True), and feature scaling using StandardScaler."
)
if __name__=='__main__':
main()