telco-customer-churn-predic.../app.py

80 lines
4.1 KiB
Python
Raw Normal View History

# app.py - 电信客户流失预测Streamlit交互页面
import streamlit as st
import joblib
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 基础设置(中文显示)
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 缓存模型
@st.cache_resource
def load_trained_model():
try:
model = joblib.load('telco_churn_model.pkl')
return model
except FileNotFoundError:
st.error("❌ 未找到模型文件!请先运行 src/model.py 训练模型")
return None
# 页面标题
st.set_page_config(page_title="电信客户流失预测系统", page_icon="📱", layout="wide")
st.title("📱 电信客户流失预测系统")
st.divider()
# 1. 客户信息输入
st.subheader("1. 输入客户信息")
with st.form("customer_form"):
col1, col2 = st.columns(2)
with col1:
tenure = st.number_input("在网时长(月)", min_value=0, max_value=72, value=12)
monthly_charges = st.number_input("月消费金额", min_value=18.0, max_value=120.0, value=69.99)
total_charges = st.number_input("总消费金额", min_value=18.0, max_value=8684.0, value=839.88)
with col2:
contract = st.selectbox("合约类型", ["Month-to-month月付", "One year1年", "Two year2年"])
internet_service = st.selectbox("网络服务", ["DSL宽带", "Fiber optic光纤", "No"])
payment_method = st.selectbox("支付方式", ["Electronic check电子支票", "Mailed check邮寄支票", "Bank transfer银行转账", "Credit card信用卡"])
submit_btn = st.form_submit_button("🚀 预测流失风险")
# 2. 预测结果
if submit_btn:
model = load_trained_model()
if model:
# 转换输入为模型可识别格式
contract_map = {"Month-to-month月付": "Month-to-month", "One year1年": "One year", "Two year2年": "Two year"}
internet_map = {"DSL宽带": "DSL", "Fiber optic光纤": "Fiber optic", "No": "No"}
payment_map = {"Electronic check电子支票": "Electronic check", "Mailed check邮寄支票": "Mailed check", "Bank transfer银行转账": "Bank transfer (automatic)", "Credit card信用卡": "Credit card (automatic)"}
# 构造数据
customer_data = pd.DataFrame({
'customerID': ['TEST001'], 'tenure': [tenure], 'MonthlyCharges': [monthly_charges], 'TotalCharges': [total_charges],
'Contract': [contract_map[contract]], 'InternetService': [internet_map[internet_service]], 'PaymentMethod': [payment_map[payment_method]],
'OnlineSecurity': ['No'], 'TechSupport': ['No'], 'PaperlessBilling': ['Yes'], 'gender': ['Female'],
'SeniorCitizen': [0], 'Partner': ['Yes'], 'Dependents': ['No'], 'PhoneService': ['Yes'],
'MultipleLines': ['No'], 'OnlineBackup': ['Yes'], 'DeviceProtection': ['No'], 'StreamingTV': ['Yes'], 'StreamingMovies': ['No']
})
# 添加特征组合
customer_data['tenure_monthly'] = customer_data['tenure'] * customer_data['MonthlyCharges']
customer_data['tenure_ratio'] = customer_data['tenure'] / (customer_data['TotalCharges'] + 1)
customer_data['monthly_total_ratio'] = customer_data['MonthlyCharges'] / (customer_data['TotalCharges'] + 1)
# 预测
churn_pred = model.predict(customer_data)[0]
churn_prob = model.predict_proba(customer_data)[:, 1][0]
# 展示结果
st.divider()
st.subheader("2. 流失风险预测结果")
if churn_pred == 1:
st.error(f"⚠️ 流失风险高(概率:{churn_prob:.2%}")
else:
st.success(f"✅ 流失风险低(概率:{churn_prob:.2%}")
# 3. 分析与建议
st.divider()
st.subheader("3. 流失影响因素")
st.image("特征重要性TOP10.png", caption="影响流失的TOP10因素")
st.subheader("4. 留存建议")
st.markdown("- 短在网时长+高消费:提供长期合约折扣\n- 光纤用户:优化网络稳定性\n- 电子支票支付:自动续费优惠")