Haider9786/nlp-threat-classifier
GitHub: Haider9786/nlp-threat-classifier
基于TF-IDF与经典机器学习算法的二元钓鱼邮件文本分类实践项目,提供完整的训练流程与Streamlit演示界面。
Stars: 0 | Forks: 0
# NLP 威胁情报文本分类器
**技术栈:** Python | scikit-learn | NLTK | TF-IDF | Streamlit | Docker | GitHub Actions
**领域:** 钓鱼检测 | NLP/ML | SOC 工具
## 项目概述
这是一个二元文本分类器,使用经典的 NLP 和机器学习技术将电子邮件内容标记为**钓鱼**或**安全**。作为一个实践项目而构建,旨在将文本预处理、TF-IDF 特征提取和监督模型比较应用于真实的安全用例,并提供 Streamlit 界面用于实时演示。
这是一个用于作品集/学习的项目,而不是已部署的生产系统。下方的 README 真实反映了实际构建和测量的内容——没有任何夸大或预期的数据。
## 数据集
- **来源:** Kaggle [`subhajournal/phishingemails`](https://www.kaggle.com/datasets/subhajournal/phishingemails)
- **大小:** 18,650 行原始数据 → 删除包含缺失值的行后剩余 18,634 行
- **使用的列:** `Email Text`,`Email Type`(映射为二元标签:0 = 安全,1 = 钓鱼)
- **标签分布:** 11,322 安全 / 7,312 钓鱼
## 流程
```
Raw email text (CSV)
|
v
Preprocessing
- lowercase, strip URLs
- remove non-alphabetic characters
- remove stopwords, drop tokens <= 2 chars
- Porter stemming
|
v
TF-IDF vectorization (max 5,000 features)
|
v
Train/test split (80/20, stratified)
|
v
GridSearchCV (5-fold, stratified) over:
- Multinomial Naive Bayes
- Logistic Regression
- Linear SVM
|
v
Best model selected by held-out test accuracy
|
v
Streamlit app for live classification
```
## 结果
所有三个模型都通过 `GridSearchCV` 进行了 5 折分层交叉验证的微调,然后在保留的 20% 测试集(3,726 个样本)上进行了评估。
| 模型 | 最佳参数 | 测试准确率 | 精确率 (加权) | 召回率 (加权) | F1 (加权) |
|---|---|---|---|---|---|
| Naive Bayes | alpha=1.0 | 95.81% | 0.96 | 0.96 | 0.96 |
| **Logistic Regression** | **C=10.0** | **96.75%** | **0.97** | **0.97** | **0.97** |
| Linear SVM | C=1.0 | 96.62% | 0.97 | 0.97 | 0.97 |
**Logistic Regression (C=10) 是表现最好的模型**,略微优于微调后的 SVM。这在事先有些出乎意料,因为 SVM 是 TF-IDF 文本分类中更常被提及的选择,这种情况只有在运行了交叉验证和超参数网格搜索(而不是依赖默认设置)后才变得清晰。这是一个微小但真实的例子,说明了为什么微调比想当然更重要。
混淆矩阵(Logistic Regression,测试集):
```
Predicted Safe Predicted Phishing
Actual Safe 2186 78
Actual Phishing 43 1419
```
## 项目结构
```
nlp-threat-classifier/
├── config.yaml # central config: paths, model params, CV folds
├── requirements.txt
├── setup.py # installable package (pip install -e .)
├── Dockerfile
├── .dockerignore
├── .github/
│ └── workflows/
│ └── ci.yml # runs pytest on every push/PR to main
├── data/
│ ├── Phishing_Email.csv # raw Kaggle dataset
│ └── cleaned_dataset.csv # generated by preprocess.py
├── src/
│ └── threat_classifier/
│ ├── __init__.py
│ ├── utils.py # config loader, logging setup
│ ├── preprocess.py # text cleaning pipeline
│ ├── train.py # CV + grid search + model training
│ └── app.py # Streamlit UI
├── tests/
│ ├── test_preprocess.py
│ └── test_utils.py
├── models/
│ ├── best_model.pkl
│ └── vectorizer.pkl
└── logs/
└── app.log # generated at runtime
```
## 运行说明
### 本地设置
```
git clone https://github.com/Haider9786/nlp-threat-classifier
cd nlp-threat-classifier
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txt
pip install -e .
```
### 从头运行 pipeline
```
python src\threat_classifier\preprocess.py # cleans raw data -> data/cleaned_dataset.csv
python src\threat_classifier\train.py # trains + tunes models -> models/*.pkl
streamlit run src\threat_classifier\app.py # launches the web UI
```
### 运行测试
```
pytest tests/ -v
```
### Docker
包含一个 `Dockerfile` 用于可复现的构建:
```
docker build -t threat-classifier .
docker run -p 8501:8501 threat-classifier
```
**注意:** Docker 构建尚未在此机器上进行过端到端验证——如果您遇到问题,请回退到上面的本地设置,并将此 Dockerfile 视为一个正在进行的工作。
### CI
GitHub Actions 工作流(`.github/workflows/ci.yml`)会在每次推送到 `main` 和 pull request 时自动运行测试套件。
## 工程笔记
- **配置驱动,而非硬编码。** 所有路径、模型超参数和 CV 设置都存在于 `config.yaml` 中,而不是分散在各个脚本里。
- **使用日志而非 print 语句。** 每个脚本都会将带有时间戳和级别的日志记录到控制台和 `logs/app.log` 中。
- **错误处理。** 缺失的文件、缺失的列和空输入都会被明确捕获并给出清晰的提示信息,而不是抛出原始的堆栈跟踪。
- **经过测试。** 核心预处理逻辑(URL 剥离、停用词移除、词干提取,以及 `None`/空输入等边缘情况)和配置加载均由单元测试覆盖。
- **已打包。** 代码库可安装(`pip install -e .`),因此模块可以干净地导入(`from threat_classifier.preprocess import clean_text`),而不必依赖相对路径的 hack。
## 真实的局限性
- 这是一个在单一公开数据集上训练的**二元**分类器(安全 vs 钓鱼)。它尚未针对实时/真实世界的电子邮件流量,或旨在规避基于关键字特征的对抗性钓鱼企图进行验证。
- TF-IDF + 线性模型无法捕获依赖视觉/品牌欺骗、基于附件的 payload 或发件人头异常的钓鱼行为——本项目仅查看邮件正文文本。
- 不存在 SOAR/SIEM 集成;这被列为未来可能的发展方向,而不是当前功能。
- Docker 镜像虽已定义,但尚未确认能顺利构建和运行——请参阅上方的注意说明。
## 可能的后续步骤
- 添加一个 `predict.py` CLI,用于在 Streamlit UI 之外进行脚本化/批量分类
- 验证并记录 Docker 构建过程
- 尝试使用保留的“困难样本”测试集,以探查在原始 Kaggle 分布之外的鲁棒性
- 探索轻量级 transformer 基线(例如 DistilBERT),作为 TF-IDF + 线性模型的比较基准
标签:Apex, Kubernetes, Python, scikit-learn, Streamlit, 文本分类, 无后门, 机器学习, 访问控制, 请求拦截, 逆向工具, 钓鱼检测