208 lines
11 KiB
Markdown
208 lines
11 KiB
Markdown
|
|
# 客户情感预测与风险分析系统
|
|||
|
|
|
|||
|
|
> **机器学习 (Python) 课程设计**
|
|||
|
|
|
|||
|
|
## 👥 团队成员
|
|||
|
|
|
|||
|
|
| 姓名 | 学号 | 贡献 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 于洋 | 2311020129 | 数据处理、模型训练 |
|
|||
|
|
| 张洁 | 2311020131 | Agent 开发、提交 |
|
|||
|
|
| 杨艺瑶 | 2311020127 | streamlit,汇报 |
|
|||
|
|
|
|||
|
|
## 📝 项目简介
|
|||
|
|
|
|||
|
|
本项目旨在构建一个端到端的客户情感分析与风险预警系统。通过对包含2.5万条记录的客户评论数据集(Customer Sentiment Dataset)进行挖掘,结合交易属性(如响应时间、解决状态、购买渠道等)与评论文本,利用机器学习算法自动识别客户的情感倾向(Positive/Negative/Neutral)。
|
|||
|
|
|
|||
|
|
系统不仅实现了高精度的情感分类模型(Logistic Regression 与 LightGBM),还进一步集成了“预测 → 分析 → 建议”的智能 Agent 流程。最终通过 Streamlit 搭建了交互式仪表盘,支持实时输入客户特征,输出情感风险评分、关键影响因子解释以及针对性的运营建议,帮助企业及时挽留高风险客户,提升服务质量。
|
|||
|
|
|
|||
|
|
## 1️⃣ 问题定义与数据
|
|||
|
|
|
|||
|
|
### 1.1 任务描述
|
|||
|
|
|
|||
|
|
**任务类型**:多分类任务 (Multi-class Classification)
|
|||
|
|
**业务目标**:基于客户的评论文本 (`review_text`) 及相关交易属性(如评分、产品类别、平台等),预测客户的情感倾向 (`sentiment`)。该模型旨在帮助企业自动化监控客户反馈,及时识别负面评价并采取行动,从而提升客户满意度和留存率。
|
|||
|
|
|
|||
|
|
### 1.2 数据来源
|
|||
|
|
|
|||
|
|
| 项目 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| 数据集名称 | Customer Sentiment Dataset |
|
|||
|
|
| 数据链接 | 本地文件 (data/Customer_Sentiment.csv) |
|
|||
|
|
| 样本量 | 25,000 条 |
|
|||
|
|
| 特征数 | 11 个 (不含 ID 和标签) |
|
|||
|
|
|
|||
|
|
### 1.3 数据切分与防泄漏
|
|||
|
|
|
|||
|
|
**数据切分**:
|
|||
|
|
- 采用 **随机切分** (Random Split) 策略。
|
|||
|
|
- **训练集 : 验证集 : 测试集 = 8 : 1 : 1** (或 70% : 15% : 15%)。
|
|||
|
|
- 设定固定的 `random_state` 以确保实验可复现。
|
|||
|
|
|
|||
|
|
**防泄漏措施**:
|
|||
|
|
1. **ID 剔除**:移除 `customer_id`,防止模型记忆特定用户。
|
|||
|
|
2. **特征筛选**:剔除 `customer_rating`(客户评分),因为评分与情感倾向高度相关,直接使用会导致数据泄漏,使任务失去预测意义。
|
|||
|
|
3. **时间穿越**:虽然数据集包含 `response_time_hours` 和 `issue_resolved`,但在预测“评论发布时”的情感时,这些可能是未来信息。若业务场景为“收到评论即时预测”,应排除这些特征;若为“事后归因分析”,则可保留。本项目暂作为特征处理,但需注意其业务含义。
|
|||
|
|
4. **预处理隔离**:所有统计特征(如文本向量化的词汇表、数值归一化的均值/方差)仅在 **训练集** 上计算,严禁利用验证集或测试集信息。
|
|||
|
|
|
|||
|
|
## 🚀 快速开始
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 克隆仓库
|
|||
|
|
git clone http://hblu.top:3000/MachineLearning2025/GXX-Customer_Sentiment_Analysis.git
|
|||
|
|
cd GXX-Customer_Sentiment_Analysis
|
|||
|
|
|
|||
|
|
# 安装依赖
|
|||
|
|
uv sync
|
|||
|
|
|
|||
|
|
# 配置环境变量
|
|||
|
|
cp .env.example .env
|
|||
|
|
# 编辑 .env 填入 API Key
|
|||
|
|
|
|||
|
|
# 运行 Demo
|
|||
|
|
uv run streamlit run src/streamlit_app.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2️⃣ 机器学习流水线
|
|||
|
|
|
|||
|
|
### 2.1 基线模型
|
|||
|
|
|
|||
|
|
| 模型 | 指标 | 结果 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| Logistic Regression | ROC-AUC | 1.0000 |
|
|||
|
|
|
|||
|
|
### 2.2 进阶模型
|
|||
|
|
|
|||
|
|
| 模型 | 指标 | 结果 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| LightGBM | ROC-AUC | 1.0000 |
|
|||
|
|
|
|||
|
|
### 2.3 误差分析
|
|||
|
|
|
|||
|
|
(模型在哪些样本上表现不佳?为什么?)
|
|||
|
|
|
|||
|
|
**结果分析**:
|
|||
|
|
- 模型在测试集上取得了完美的分类效果 (ROC-AUC = 1.0, Accuracy = 100%)。
|
|||
|
|
- **原因推测**:数据集可能是合成数据,且不同情感类别(Positive, Neutral, Negative)对应的评论文本模式非常固定且区分度极高(例如 "very disappointed" 总是对应 Negative,"excellent product" 总是对应 Positive)。此外,剔除了强相关特征 `customer_rating` 后,文本特征依然提供了足够的信息进行完美分类。
|
|||
|
|
- **潜在问题**:虽然模型在当前数据集上表现完美,但在真实世界的复杂评论数据上可能无法泛化。建议引入更多样化、含噪声的真实评论数据进行进一步测试。
|
|||
|
|
- **错误样本**:无(0/5000 错误)。
|
|||
|
|
|
|||
|
|
### 2.4 阈值策略与代价敏感分析(加分项)
|
|||
|
|
- 业务代价设定:假阴性(负面未拦截)成本 `C_FN = 10`,假阳性(误拦截)成本 `C_FP = 1`。
|
|||
|
|
- 风险阈值:为降低期望代价,采用分级策略:
|
|||
|
|
- 高风险:`risk ≥ 0.7` → 立即升级处理、客服介入、补偿策略评估
|
|||
|
|
- 中风险:`0.4 ≤ risk < 0.7` → 标记与复核,优先排队
|
|||
|
|
- 低风险:`risk < 0.4` → 常规监控
|
|||
|
|
- 证据:结合 `explain_features` 的线性贡献因子,定位行动点(如高频负面词、长响应时间、未解决状态)。
|
|||
|
|
|
|||
|
|
## 数据处理(必做)
|
|||
|
|
|
|||
|
|
- 使用 **Polars** 完成可复现的数据清洗流水线,脚本位置:`src/data_processing.py`
|
|||
|
|
- 定义 Schema:`define_schema`(`pandera.polars`)在 `src/data_processing.py:5`。
|
|||
|
|
- 清洗流程:`clean_data` 在 `src/data_processing.py:23`(字段标准化、布尔化、类别转换)。
|
|||
|
|
- 探索与保存:`load_and_inspect` 在 `src/data_processing.py:52`(校验→清洗→概览→保存至 `data/Cleaned_Customer_Sentiment.csv`)。
|
|||
|
|
- 运行命令:`py src/data_processing.py`
|
|||
|
|
|
|||
|
|
### 清洗操作(Polars + Pandera)
|
|||
|
|
- Schema 校验:
|
|||
|
|
- `customer_id > 0`;`gender ∈ {male,female,other}`;`age_group ∈ {18-25,26-35,36-45,46-60,60+}`;
|
|||
|
|
- `region ∈ {north,south,east,west,central}`;`purchase_channel ∈ {online,offline}`;
|
|||
|
|
- `customer_rating ∈ [1,5]`;`sentiment ∈ {positive,negative,neutral}`;`response_time_hours ≥ 0`;
|
|||
|
|
- `issue_resolved, complaint_registered ∈ {yes,no}`。
|
|||
|
|
- 值标准化与类型转换:
|
|||
|
|
- 将 `issue_resolved`, `complaint_registered` 从 `yes/no` 转为 `bool`。
|
|||
|
|
- 将 `product_category`, `platform`, `review_text` 统一为小写。
|
|||
|
|
- 将类别列(`gender, age_group, region, product_category, purchase_channel, platform, sentiment`)转换为分类类型。
|
|||
|
|
- 去除泄漏相关特征:在训练阶段剔除 `customer_rating`。
|
|||
|
|
- 数据探索输出:
|
|||
|
|
- 类别列的频次统计(略过长文本列)。
|
|||
|
|
- 清洗后数据示例与 Schema 打印。
|
|||
|
|
- 落盘:
|
|||
|
|
- 结果保存到 `data/Cleaned_Customer_Sentiment.csv`,供训练与 Demo 使用。
|
|||
|
|
|
|||
|
|
### 清洗结果(核心指标)
|
|||
|
|
- 总行数:`25,000`
|
|||
|
|
- 空值计数:所有列空值为 `0`
|
|||
|
|
- 情感分布:
|
|||
|
|
- positive: `9,978`
|
|||
|
|
- negative: `9,937`
|
|||
|
|
- neutral: `5,085`
|
|||
|
|
- 性别分布:
|
|||
|
|
- male: `8,385`,female: `8,356`,other: `8,259`
|
|||
|
|
- 渠道分布:
|
|||
|
|
- `purchase_channel = online`(`25,000`)
|
|||
|
|
- 业务状态:
|
|||
|
|
- `issue_resolved=True` 比例:`66.372%`
|
|||
|
|
- `complaint_registered=True` 比例:`39.748%`
|
|||
|
|
- 响应时长(按情感均值,小时):
|
|||
|
|
- neutral: `36.0869`,negative: `36.0222`,positive: `35.9924`
|
|||
|
|
- Top 平台(前 5):
|
|||
|
|
- nykaa (`1,301`), snapdeal (`1,289`), others (`1,286`), reliance digital (`1,279`), zepto (`1,278`)
|
|||
|
|
- Top 产品品类(前 5):
|
|||
|
|
- groceries (`2,858`), automobile (`2,833`), books (`2,812`), travel (`2,811`), fashion (`2,782`)
|
|||
|
|
|
|||
|
|
## 机器学习(必做)
|
|||
|
|
|
|||
|
|
- 至少 2 个模型对比:已实现 **Logistic Regression** 与 **LightGBM**(见 `src/train_models.py`)。
|
|||
|
|
- 指标达标:`ROC-AUC = 1.0000 ≥ 0.75`(分类报告亦为满分,满足 `F1 ≥ 0.70` 要求)。
|
|||
|
|
- 工件持久化:流水线与标签编码器保存到 `artifacts/`,便于 Agent 复用(`src/train_models.py:137-146` 与持久化 `src/train_models.py:145-149`)。
|
|||
|
|
|
|||
|
|
## 3️⃣ Agent 实现
|
|||
|
|
|
|||
|
|
### 3.1 工具定义
|
|||
|
|
|
|||
|
|
| 工具名 | 功能 | 输入 | 输出 |
|
|||
|
|
|--------|------|------|------|
|
|||
|
|
| `predict_risk` | 调用 ML 模型预测 | CustomerFeatures | float |
|
|||
|
|
| `explain_features` | 解释特征影响 | CustomerFeatures | list[str] |
|
|||
|
|
|
|||
|
|
CustomerFeatures 字段:
|
|||
|
|
`gender`, `age_group`, `region`, `product_category`, `purchase_channel`, `platform`, `response_time_hours`, `issue_resolved`, `complaint_registered`, `review_text`
|
|||
|
|
(不包含 `customer_rating` 与 `customer_id`)
|
|||
|
|
|
|||
|
|
实现位置:`src/agent.py`
|
|||
|
|
模型与预处理加载自:`artifacts/`(含 `lgb_pipeline.joblib`, `lr_pipeline.joblib`, `label_encoder.joblib`)
|
|||
|
|
|
|||
|
|
### 3.2 决策流程
|
|||
|
|
|
|||
|
|
- 预测:`predict_risk(features)` 使用 LightGBM 流水线输出负面情感概率(risk,0.0~1.0)。
|
|||
|
|
- 解释:`explain_features(features)` 通过 Logistic 回归的线性贡献,返回若干条影响说明(包含方向与权重)。
|
|||
|
|
- 建议:基于 `risk` 与解释结果,产品可进一步生成运营建议(如:优先处理高风险投诉、优化长响应时间、针对高频负面词优化客服话术)。
|
|||
|
|
|
|||
|
|
### Agent(必做)符合项
|
|||
|
|
|
|||
|
|
- 使用 **Pydantic** 定义输入与输出模型:
|
|||
|
|
- `CustomerFeatures` 输入模型(`src/agent.py:11-21`,包含枚举与边界约束)
|
|||
|
|
- `RiskOutput` 与 `ExplanationOutput` 输出模型(`src/agent.py:23-27`)
|
|||
|
|
- 至少 2 个工具:
|
|||
|
|
- `predict_risk`(ML 预测工具,`src/agent.py:47-52`)
|
|||
|
|
- `explain_features`(特征影响解释,`src/agent.py:57-73`)
|
|||
|
|
|
|||
|
|
## 4️⃣ 开发心得
|
|||
|
|
|
|||
|
|
### 4.1 主要困难与解决方案
|
|||
|
|
|
|||
|
|
- 依赖安装与网络:`polars`, `pandera`, `scikit-learn`, `lightgbm`, `pyarrow` 等包在国内网络下安装不稳定。
|
|||
|
|
解决:配置清华镜像(如 `pip -i https://pypi.tuna.tsinghua.edu.cn/simple`、设置 `UV_INDEX_URL`),分步安装缺失依赖(如 `pyarrow` 用于 `polars.to_pandas()`)。
|
|||
|
|
- 项目初始化命名问题:中文目录名导致 `uv init` 的包名无效。
|
|||
|
|
解决:使用 `uv init --name customer-sentiment-analysis` 指定合法英文包名。
|
|||
|
|
- 模型参数兼容性:`LogisticRegression` 版本差异导致 `multi_class` 参数报错。
|
|||
|
|
解决:移除不兼容参数,使用默认自动模式。
|
|||
|
|
- 数据泄漏与指标异常:出现近乎完美的指标,初步判断评分与文本标签高度相关。
|
|||
|
|
解决:剔除 `customer_rating` 特征,保留文本与业务属性;同时在文档明确风险与解释原因。
|
|||
|
|
- 工件持久化与推理:训练后需在推理端复用预处理与模型。
|
|||
|
|
解决:将流水线与标签编码器持久化至 `artifacts/`,在 `src/agent.py` 统一加载与推理。
|
|||
|
|
|
|||
|
|
### 4.2 对 AI 辅助编程的感受
|
|||
|
|
|
|||
|
|
- 明显提升效率:快速生成数据流水线、模型训练与解释模块、结构化文档,排查错误栈更高效。
|
|||
|
|
- 需要严格验证:对自动生成的代码进行运行验证与指标审查,关注版本兼容与数据泄漏。
|
|||
|
|
- 最佳实践:固定 `random_state`、将预处理封装进 `Pipeline`、仅在训练集拟合、保存可复用工件、在 README 清晰记录假设与风险。
|
|||
|
|
|
|||
|
|
### 4.3 局限与未来改进
|
|||
|
|
|
|||
|
|
- 数据与评估:引入更真实、含噪声的评论数据;采用交叉验证与时间切分;增加宏平均 F1、精细化错误聚类。
|
|||
|
|
- 解释与可用性:引入 SHAP/LIME 等更稳健的解释方法;将解释结果转为面向运营的建议话术。
|
|||
|
|
- 系统与工程:将 `agent.py` 封装为服务/API,集成 Streamlit 交互;完善单元测试、CI、类型检查与 lint;健全 `.env` 配置校验。
|
|||
|
|
- 部署与监控:容器化部署、资源优化(并行/向量化);加上指标监控与告警、模型版本管理与回滚策略。
|