commit 2926e89cb6cea604216e10017ff5b8ea531ae1fe Author: st2311020204 <352587714@qq.com> Date: Thu Jan 15 13:13:27 2026 +0800 上传文件至 / diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..0e16b94 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# DeepSeek API Key +DEEPSEEK_API_KEY=sk-xxxx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a4d53d --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# ===== 环境变量(绝对不能提交!)===== +.env + +# ===== Python 虚拟环境 ===== +.venv/ +venv/ +__pycache__/ +*.pyc +*.pyo +.pytest_cache/ + +# ===== IDE 配置 ===== +.vscode/ +.idea/ +*.swp + +# ===== macOS 系统文件 ===== +.DS_Store + +# ===== Jupyter ===== +.ipynb_checkpoints/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/README.md b/README.md new file mode 100644 index 0000000..622f1c1 --- /dev/null +++ b/README.md @@ -0,0 +1,212 @@ +# 电信客户流失预测系统 + +> **机器学习 (Python) 课程设计** + +## 👥 团队成员 + +| 姓名 | 学号 | 贡献 | +|------|------|------| +| 陈思坤 | 2311020204 | 数据处理、模型训练 | +| (请填写) | (请填写) | Agent 开发、Streamlit | +| (请填写) | (请填写) | 测试、文档撰写 | + +## 📝 项目简介 + +本项目基于 Telco Customer Churn 数据集,构建了一个完整的客户流失预测与挽留建议系统。系统包含三个核心能力: + +1. **传统机器学习**:使用 LightGBM 模型预测客户流失概率 +2. **LLM 集成**:使用 DeepSeek 生成个性化挽留建议 +3. **Agent 工具调用**:通过 pydantic-ai 实现 ML 预测 + 风险分析的工具链 + +## 🚀 快速开始 + +```bash +# 克隆仓库 +git clone http://hblu.top:3000/MachineLearning2025/GXX-TelcoChurn.git +cd GXX-TelcoChurn + +# 安装依赖 +uv sync + +# 配置环境变量 +cp .env.example .env +# 编辑 .env 填入 API Key + +# 训练模型 +uv run python src/train.py + +# 运行 Demo +uv run streamlit run src/streamlit_app.py +``` + +--- + +## 1️⃣ 问题定义与数据 + +### 1.1 任务描述 + +- **任务类型**:二分类 +- **业务目标**:预测电信客户是否会流失,并给出针对性的挽留建议 +- **输入**:客户基本信息、服务订阅情况、账户信息 +- **输出**:流失概率、风险等级、挽留行动计划 + +### 1.2 数据来源 + +| 项目 | 说明 | +|------|------| +| 数据集名称 | Telco Customer Churn | +| 数据链接 | [Kaggle](https://www.kaggle.com/datasets/blastchar/telco-customer-churn) | +| 样本量 | 7,043 条 | +| 特征数 | 20 个 | +| 流失率 | ~26.5% | + +### 1.3 数据切分与防泄漏 + +- **切分策略**:80% 训练集,20% 测试集 +- **分层采样**:使用 `stratify=y` 确保训练集和测试集的流失率一致 +- **随机种子**:固定 `random_state=42` 确保可复现 +- **防泄漏措施**: + - 不使用 customerID 作为特征 + - TotalCharges 与 tenure 存在相关性,但保留两者因为业务含义不同 + - 所有特征工程在训练集上拟合,在测试集上转换 + +--- + +## 2️⃣ 机器学习流水线 + +### 2.1 数据预处理 + +使用 Polars 进行高性能数据处理: + +```python +# 使用 Polars Lazy API +df = pl.read_csv("data/WA_Fn-UseC_-Telco-Customer-Churn.csv") +df_clean = preprocess_data(df) # 删除缺失值、转换类型 +``` + +使用 Pandera 进行 Schema 校验: + +```python +class CleanTelcoSchema(pa.DataFrameModel): + tenure: int = pa.Field(ge=0, nullable=False) + MonthlyCharges: float = pa.Field(ge=0, nullable=False) + Churn: int = pa.Field(isin=[0, 1], nullable=False) +``` + +### 2.2 基线模型 + +| 模型 | F1 Score | ROC-AUC | +|------|----------|---------| +| Logistic Regression | ~0.58 | ~0.84 | + +### 2.3 进阶模型 + +| 模型 | F1 Score | ROC-AUC | +|------|----------|---------| +| LightGBM | ~0.60 | ~0.85 | + +### 2.4 误差分析 + +模型在以下样本上表现不佳: + +1. **边界客户**:流失概率在 0.4-0.6 之间的客户,模型难以准确判断 +2. **长期客户突然流失**:任期较长但突然流失的客户,可能受到外部因素影响 +3. **低费用客户**:月费较低的客户,特征区分度不够 + +**改进方向**: +- 引入更多行为特征(如投诉记录、服务使用频率) +- 考虑时序特征(如近期费用变化趋势) + +--- + +## 3️⃣ Agent 实现 + +### 3.1 工具定义 + +| 工具名 | 功能 | 输入 | 输出 | +|--------|------|------|------| +| `predict_churn_probability` | 调用 ML 模型预测流失概率 | CustomerFeatures | float | +| `get_model_explanation` | 获取模型特征重要性 | - | str | +| `analyze_risk_factors` | 分析客户具体风险因素 | CustomerFeatures | list[str] | + +### 3.2 决策流程 + +``` +用户输入客户信息 + ↓ +Agent 调用 predict_churn_probability → 获取流失概率 + ↓ +Agent 调用 get_model_explanation → 获取特征重要性 + ↓ +Agent 调用 analyze_risk_factors → 获取具体风险因素 + ↓ +Agent 生成结构化输出 (ChurnPrediction) + ↓ +返回:流失概率 + 风险等级 + 关键因素 + 行动计划 + 依据说明 +``` + +### 3.3 案例展示 + +**输入**: +``` +客户信息:任期 2 个月,月费 $89.99,月付合同,光纤服务,电子支票支付 +``` + +**输出**: +```json +{ + "churn_probability": 0.82, + "risk_level": "高风险", + "key_factors": [ + "新客户(任期仅2个月),流失风险较高", + "月付合同,无长期绑定,容易流失", + "使用电子支票支付,该支付方式用户流失率最高" + ], + "action_plan": [ + {"action": "提供首年合同升级优惠(8折)", "priority": "高"}, + {"action": "赠送 3 个月在线安全服务", "priority": "高"}, + {"action": "引导切换为自动银行转账支付", "priority": "中"} + ], + "rationale": "该客户为新客户且使用月付合同,根据模型分析,合同类型和客户任期是最重要的流失预测因素..." +} +``` + +--- + +## 4️⃣ 开发心得 + +### 4.1 主要困难与解决方案 + +1. **数据类型处理**:TotalCharges 字段在原始数据中是字符串,包含空值 + - 解决:使用 Polars 的条件表达式处理空字符串 + +2. **类别不平衡**:流失客户仅占 26.5% + - 解决:使用 `class_weight="balanced"` 参数 + +3. **Agent 输出稳定性**:LLM 有时不按要求调用工具 + - 解决:在 instructions 中明确规定必须调用的工具顺序 + +### 4.2 对 AI 辅助编程的感受 + +- **有帮助的场景**:代码框架搭建、API 文档查询、错误调试 +- **需要注意的地方**:AI 生成的代码需要仔细审查,特别是边界条件处理 + +### 4.3 局限与未来改进 + +1. 可以引入更多特征(如客户投诉记录、服务使用频率) +2. 可以实现阈值策略,针对不同风险等级采取不同挽留措施 +3. 可以添加相似案例检索功能,提供历史成功挽留案例参考 + +--- + +## 📋 Checklist(提交前自检) + +- [x] 使用 `uv sync` 安装依赖,无需手动创建虚拟环境 +- [x] `.gitignore` 包含 `.env`、`__pycache__`、大文件 +- [x] 在干净环境下可以复现(`git clone && uv sync && uv run`) +- [x] 没有提交 API Key 或敏感信息 +- [x] 使用 Polars 进行数据处理 +- [x] 使用 Pydantic 定义特征和输出模型 +- [x] Agent 至少有 2 个 tool(含 1 个 ML 工具) +- [x] README.md 说明了数据切分策略 +- [x] Demo 可以正常运行 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..83716d3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,46 @@ +[project] +name = "telco-churn-predictor" +version = "0.1.0" +description = "电信客户流失预测系统 - 机器学习 × LLM × Agent 课程设计" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "pydantic>=2.10", + "pandera>=0.21", + "pydantic-ai>=0.7", + "polars>=1.0", + "pandas>=2.2", + "scikit-learn>=1.5", + "lightgbm>=4.5", + "seaborn>=0.13", + "joblib>=1.4", + "python-dotenv>=1.0", + "streamlit>=1.40", +] + +[[tool.uv.index]] +url = "https://mirrors.aliyun.com/pypi/simple/" +default = true + +[dependency-groups] +dev = [ + "pytest>=8.0", + "pytest-asyncio>=1.3", + "ruff>=0.8", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src"] + +[tool.ruff] +line-length = 100 + +[tool.ruff.lint] +select = ["E", "F", "I"] + +[tool.pytest.ini_options] +testpaths = ["tests"]