# 客户情感预测与风险分析系统 > **机器学习 (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` 配置校验。 - 部署与监控:容器化部署、资源优化(并行/向量化);加上指标监控与告警、模型版本管理与回滚策略。