msburns24/amazon-sentiment-ml-eng
GitHub: msburns24/amazon-sentiment-ml-eng
一个基于 Amazon 评论数据的生产级情感分类系统,展示了从 notebook 原型到可部署 ML 系统的工程模式,涵盖回退链、漂移检测与可观测性。
Stars: 0 | Forks: 0
# amazon-sentiment-ml-eng
一个基于 [Amazon Customer Reviews 2023](https://huggingface.co/datasets/McAuley-Lab/Amazon-Reviews-2023) 数据集构建的生产级情感分类器。它展示了介于 notebook 原型与部署系统之间的机器学习工程模式:结构化错误处理、三级回退链、漂移检测、FastAPI 服务层以及 Streamlit 可观测性仪表板。
该项目最初是 DATA 789 (UNC MADS) 关于需求工程的作业,后来被扩展为一个完整的端到端系统。
## 项目结构
```
amazon-sentiment-ml-eng/
├── src/amazon_sentiment/
│ ├── classifier.py # DistilBERT inference, input validation, OOV detection
│ ├── fallback.py # Three-tier fallback chain
│ ├── drift.py # Drift report (OOV rate, KS test, JS divergence)
│ ├── api.py # FastAPI app (/predict, /health, /metrics)
│ └── dashboard.py # Streamlit observability dashboard
├── scripts/
│ ├── download.py # Download Amazon Reviews dataset from HuggingFace
│ ├── preprocess.py # Derive sentiment labels from star ratings
│ ├── split_windows.py # Partition data into early/late time windows
│ ├── train.py # Fine-tune DistilBERT on the training window
│ └── simulate_drift.py # Compare windows and produce a drift report
├── reports/
│ └── drift.json # Drift simulation output
├── tests/
│ ├── unit/ # Classifier, fallback, resource guard unit tests
│ ├── integration/ # End-to-end with real DistilBERT checkpoint
│ ├── drift/ # Drift detection unit and scenario tests
│ └── api/ # FastAPI endpoint tests
├── HW1/ # Original homework artifacts (archived)
│ ├── sentiment_classifier.py
│ ├── fallback_system.py
│ ├── requirements.md
│ └── assumptions.md
├── blog/
│ └── notebook-to-production.md # Full blog post draft
└── pyproject.toml
```
## 快速开始
### 环境配置
```
python -m venv .venv
# Windows
.venv\Scripts\Activate.ps1
# macOS/Linux
source .venv/bin/activate
pip install -e .
```
### 运行分类器
```
from amazon_sentiment.classifier import classify
result = classify("This product is absolutely fantastic!")
# {'label': 'positive', 'confidence': 0.93, 'status': 'ok', 'reason': ''}
```
每次调用都会返回包含相同四个键的字典 —— `label`、`confidence`、`status`、`reason` —— 并且永远不会向调用方抛出异常。`status` 字段会告诉你响应来自哪一层:`"ok"`(模型)、`"fallback"`(基于规则或人工队列)或 `"rejected"`(输入验证失败)。
### 运行 API 服务器
```
uvicorn amazon_sentiment.api:app --reload
```
```
# 对评论进行分类
curl -X POST http://localhost:8000/predict \
-H "Content-Type: application/json" \
-d '{"text": "Great quality and fast shipping."}'
# 健康检查
curl http://localhost:8000/health
# 滚动指标
curl http://localhost:8000/metrics
```
### 运行可观测性仪表板
```
streamlit run src/amazon_sentiment/dashboard.py
```
侧边栏提供了一个 **生成演示数据** 按钮,可以填充模拟的预测日志,这样你无需依赖实时 API 即可探索所有面板。
### 模拟漂移
```
# 将 drift report 打印到 stdout
python scripts/simulate_drift.py
# 为 dashboard 的 Drift Report 标签页保存 JSON
python scripts/simulate_drift.py --output-json reports/drift.json
```
### 运行测试
```
# Unit + drift + API 测试(unit/drift 不需要下载模型)
pytest tests/unit/ tests/drift/ tests/api/
# 包含 integration tests 的完整套件
pytest
```
## 训练你的专属模型
数据流水线是一个包含四个步骤的脚本序列。每个步骤都会读取和写入 `data/` 目录:
```
# 1. 下载原始 Amazon Reviews 数据集
python scripts/download.py
# 2. 根据星级评分推导情感标签(1–2 → negative,3 → neutral,4–5 → positive)
python scripts/preprocess.py
# 3. 划分为早期/晚期时间窗口以进行 drift 模拟
python scripts/split_windows.py
# 4. 在早期窗口上 fine-tune DistilBERT(写入到 models/amazon-sentiment/)
python scripts/train.py
```
仓库中已经包含了一个预训练的 checkpoint,位于 `models/amazon-sentiment/`。如果你只想复现漂移模拟,可以直接跳到第 3 或第 4 步。
## 关键设计决策
### 分类器:微调的 3 分类 DistilBERT
`distilbert-base-uncased` 直接在 Amazon Reviews 上进行微调,具有三个原生输出类别:`positive`、`negative`、`neutral`。在 18,851 个样本上训练了 2 个 epoch;在留出验证集上达到了 **91.4% 的准确率**。
从星级评定中推导标签是一种有据可查的权衡 —— 3 星评价是中性情感的嘈杂代理指标。有关各类别的 precision/recall 目标及其业务合理性,请参阅 `HW1/requirements.md`。
此仓库中不包含模型 checkpoint(对于 git 来说太大)。请运行下方的训练流水线来生成它,或者将 `classifier.py` 中的 `MODEL_NAME` 指向任何兼容 HuggingFace 的 checkpoint。如果未找到本地 checkpoint,`classifier.py` 会回退到 `distilbert-base-uncased-finetuned-sst-2-english`(SST-2 二分类),将低置信度预测(score < 0.75)映射为 neutral。
### 回退链:三级,同一契约
每个输入 —— 无论是否有效 —— 都会产生相同的响应结构。回退链确保了这一点:
```
Input → Validation → Resource check
→ Tier 1: DistilBERT (confidence ≥ 0.6)
→ Tier 2: Keyword heuristics (no match or tie → next)
→ Tier 3: Human review queue (always structured response)
```
### 漂移检测:三个信号
`compute_drift_report(early_df, late_df)` 比较两个 DataFrame 并报告以下情况:
| 信号 | 方法 | 默认阈值 | Amazon 数据上的结果 |
|---|---|---|---|
| OOV 率 | 均值差值 | > 5% | **无漂移** —— 差值为 3.3% |
| 文本长度 | Kolmogorov-Smirnov p 值 | < 0.05 | **漂移** —— 均值从 438 变为 514 字符,p ≈ 0 |
| 标签分布 | Jensen-Shannon 散度 | > 0.05 | **漂移** —— JS 散度为 0.184 |
标签偏移是最显著的信号:在后期时间窗口中,正面评价从 34% 骤降至 13%,负面评价从 61% 激增至 83% —— 这与恶意差评轰炸的模式一致。系统检测到了整体漂移。
所有阈值均可配置。模拟脚本支持 `--oov-threshold`、`--length-pvalue` 和 `--js-threshold` 参数。
## 需求与假设
`HW1/` 目录包含了最初的需求和假设文档,它们指导了生产环境的设计:
- **`requirements.md`** —— 业务指标(90天内流失率降低 15%)、系统性能(p95 < 200 ms,持续 50 req/s)、模型质量(macro F1 ≥ 85%)以及数据质量要求
- **`assumptions.md`** —— 世界与机器(World-vs-Machine)框架:系统控制什么与它对其环境所做的假设,以及当每个假设被违背时会发生什么
## 博客文章
`blog/notebook-to-production.md` 是一篇关于从 notebook 到生产环境之间鸿沟的实战文章,以本项目为案例研究。章节包括:
1. notebook 准确率与生产环境就绪度之间的差距
2. 需求文档解读
3. Amazon 数据集触发的故障模式
4. 三级回退链
5. 漂移模拟结果
6. 下一步计划(微调、容器化、重训练循环)
标签:AV绕过, DistilBERT, FastAPI, Kubernetes, 安全规则引擎, 情感分析, 机器学习工程, 概念漂移检测, 模型服务, 逆向工具