nadineshehabuni/Network-Intrusion-Detection-NSL-KDD.UPDATED
GitHub: nadineshehabuni/Network-Intrusion-Detection-NSL-KDD.UPDATED
基于 NSL-KDD 数据集的机器学习网络入侵检测系统,复现并评估了特征选择论文的方法,同时提供了防止数据泄漏的 Pipeline 设计和决策阈值权衡分析。
Stars: 0 | Forks: 0
# 基于 Machine Learning 的网络入侵检测 (NSL-KDD)
本项目使用 NSL-KDD 数据集实现了一个网络入侵检测系统。它是作为对论文《A Subset Feature Elimination Mechanism for Intrusion Detection System》(Nkiama, Said & Saidu, 2016) 中所述方法的复现和评估而开发的。
## 项目概述
网络入侵检测涉及将网络流量分类为正常或攻击。本项目遵循参考论文中提出的特征选择方法,在 NSL-KDD 数据集上训练并评估了三个 machine learning 模型——Decision Tree、Random Forest 和 Logistic Regression,并批判性地评估了论文报告的结果能在多大程度上被复现。
每个模型都在 scikit-learn `Pipeline` 中实现,因此所有预处理(nominal 特征的 one-hot encoding 和数值特征的标准化缩放)都会在每个 cross-validation 折叠中独立拟合,从而防止数据泄漏。模型使用分层 5 折 cross-validation 进行评估,该评估在每个折叠中保持正常/攻击比例——鉴于数据集的不平衡性,这一点非常重要。
除了标准的训练和评估循环之外,该项目还添加了两个进一步的分析:
- **特征比较** —— 对完整特征集和精简特征集(移除了高相关列)进行 cross-validation,因此特征消除决定是由测量的性能支持的,而不仅仅是依靠相关性热力图。训练时间与准确率一起进行了比较。
- **阈值分析** —— 将 Random Forest 的决策阈值在 19 个值(0.05 到 0.95)之间进行扫描,测量每个值下的 precision、recall、F1-score、false positives 和 false negatives,以揭示漏报攻击与误报警报之间的权衡。
## 参考论文
Nkiama, H., Said, S. M., & Saidu, M. (2016). *A Subset Feature Elimination Mechanism for Intrusion Detection System*. International Journal of Advanced Computer Science and Applications (IJACSA).
论文链接:https://thesai.org/Publications/ViewPaper?Volume=7&Issue=4&Code=ijacsa&SerialNo=45
## 数据集
**NSL-KDD Dataset** —— KDD Cup 1999 数据集的改进版本,它移除了重复记录并提供了更平衡的攻击类别集合(DoS、Probe、R2L、U2R)。
数据集链接:https://www.unb.ca/cic/datasets/nsl.html
## 参考 GitHub Repository
本项目还参考了以下项目使用的实现方法:
Cynthia Koopman 的 Network-Intrusion-Detection repository:https://github.com/CynthiaKoopman/Network-Intrusion-Detection
## Repository 结构
```
Network-Intrusion-Detection-ML/
│
├── data/
│ # NSL-KDD dataset files (KDDTrain.csv, KDDTest.csv)
│
├── notebooks/
│ └── NSL_KDD_Intrusion_Detection.ipynb # Main analysis and modeling notebook
│
├── project_outputs/ # Created at runtime by the notebook — copies of every exported file below
│
├── requirements.txt
└── README.md
```
notebook 会将其导出的文件写入其工作目录,然后将它们复制到 `project_outputs/` 中,因此这些路径是相对于 notebook 执行位置的。
## 如何运行
**1. Clone 该 repository**
```
git clone https://github.com/nadineshehabuni/Network-Intrusion-Detection-NSL-KDD.git
cd Network-Intrusion-Detection-NSL-KDD
```
**2. 安装依赖项**
```
pip install -r requirements.txt
```
**3. 添加数据集**
将 `KDDTrain.csv` 和 `KDDTest.csv` 放入 `data/` 文件夹中。
**4. 启动 Jupyter Notebook**
```
jupyter notebook
```
打开 `notebooks/NSL_KDD_Intrusion_Detection.ipynb` 并按顺序运行所有单元格。notebook 会从相对于其工作目录的 `data/KDDTrain.csv` 和 `data/KDDTest.csv` 加载数据集,因此请从 repository 根目录启动 Jupyter。
## 必需的库
| Library | 用途 |
|---|---|
| pandas | 数据操作与分析 |
| numpy | 数值计算 |
| matplotlib | 数据可视化 |
| seaborn | 统计数据可视化 |
| scikit-learn | Machine learning 模型与评估 |
| joblib | 保存训练好的 pipeline |
| jupyter | Notebook 环境 |
```
pip install pandas numpy matplotlib seaborn scikit-learn joblib jupyter
```
## 方法论
**1. 数据加载** —— 从 `data/` 加载 NSL-KDD 训练和测试文件,并根据数据集文档分配 42 个列名。
**2. 数据预处理** —— 检查特征的数据类型、缺失值、常量列和重复行。常量列 `num_outbound_cmds` 将从训练集和测试集中删除。
**3. 探索性数据分析** —— 可视化类分布(正常 vs 攻击)和攻击类别分布(DoS、Probe、R2L、U2R),汇总数值特征,使用对数比例 boxplots 检查异常值,并通过 Pearson 相关性热力图和分类 crosstabs 检查特征关系。
**4. 特征工程** —— 目标被编码为二元标签(0 = 正常,1 = 攻击)。nominal 列 `protocol_type`、`service` 和 `flag` 在此阶段被特意保留为原始字符串;它们会在 pipeline 中被编码(见第 7 步)。
**5. 特征选择** —— 冗余检查识别出相关性高于 0.9 的数值特征对。其中六个(`srv_serror_rate`、`dst_host_srv_serror_rate`、`dst_host_serror_rate`、`srv_rerror_rate`、`dst_host_srv_rerror_rate`、`num_root`)被删除以形成**精简特征集**,同时保留**完整特征集**以供比较。
**6. 模型训练** —— 训练三个分类器:Decision Tree、Random Forest 和 Logistic Regression。
**7. scikit-learn Pipeline** —— 每个模型都封装在 `Pipeline` 中,其第一步是一个 `ColumnTransformer`,对 nominal 列应用 `OneHotEncoder(handle_unknown="ignore")`,对数值列应用 `StandardScaler`。使用 one-hot encoding 而不是 label encoding 是因为这些变量是 nominal 的——整数编码会强加一种数据本身不支持的大小顺序和间距。`handle_unknown="ignore"` 可以安全地处理出现在测试集中但在训练中从未出现过的类别。
**8. 分层 Cross Validation** —— 所有模型都使用 `StratifiedKFold` 进行评估(5 折,shuffled,`random_state=42`),因此每个折叠都保持数据集的正常/攻击比例。
**9. 完整与精简特征集比较** —— 使用相同的三个 pipeline 和相同的折叠划分对两个特征集进行 cross-validation,比较平均 CV 准确率、标准差和每折平均训练时间。
**10. 阈值分析** —— 将 Random Forest 的决策阈值在 `np.arange(0.05, 1.00, 0.05)` 范围内进行扫描,记录每个值下的 precision、recall、F1-score、false positives 和 false negatives。
**11. 最终评估** —— 使用准确率、precision、recall、F1-score、MCC 和 ROC-AUC 在留出测试集上评估模型,并使用混淆矩阵、分类报告以及误差分析(按攻击类别分解误分类并检查训练集中缺失的攻击类型)。
## 使用的模型
**Decision Tree** —— 一种单一的基于树的分类器,它根据特征值拆分数据。它快速且易于解释,但它在此数据集上的预测概率几乎完全饱和在 0.0 和 1.0,因为它的叶子几乎是纯的。
**Random Forest** —— 由 decision tree 组成的 ensemble,其预测通过多数投票进行组合。对 100 棵树进行平均会产生有梯度的概率得分,这就是为什么它是用于阈值分析的模型。
**Logistic Regression** —— 一个线性基线模型,它对连接成为攻击的对数几率进行建模。包含它是为了进行比较,而不是作为预期的最佳表现者,因为此数据集中的入侵模式预期不是线性可分的。
## Cross Validation
所有预处理都在 scikit-learn `Pipeline` **内部**执行,而不是预先应用于数据集。在分层 5 折 cross-validation 期间,`ColumnTransformer` 仅在每个训练折叠上重新拟合:one-hot 词汇表以及 scaling 的均值和标准差永远不会接触到留出折叠。这可以防止数据泄漏,否则数据泄漏会夸大 cross-validation 得分,使其成为对实际泛化能力的不可靠估计。这同样适用于最终模型,其预处理仅在训练集上进行拟合。
## 结果
**测试集性能(默认 0.50 阈值,精简特征集)**
| 模型 | Accuracy | Precision | Recall | F1 Score | MCC | ROC-AUC |
|---|---|---|---|---|---|---|
| Decision Tree | 82.51% | 96.86% | 71.59% | 82.33% | 0.6873 | 0.8427 |
| Random Forest | 77.75% | 96.84% | 62.96% | 76.31% | 0.6178 | 0.9598 |
| Logistic Regression | 75.54% | 91.73% | 62.68% | 74.47% | 0.5608 | 0.8081 |
**完整与精简特征集对比(训练数据上的平均 5 折 CV 准确率)**
| 模型 | 特征集 | CV Accuracy | Std Dev |
|---|---|---|---|
| Decision Tree | 完整(所有特征) | 99.850% | 0.022% |
| Decision Tree | 精简(移除冗余) | 99.850% | 0.017% |
| Random Forest | 完整(所有特征) | 99.889% | 0.020% |
| Random Forest | 精简(移除冗余) | 99.882% | 0.016% |
| Logistic Regression | 完整(所有特征) | 97.289% | 0.158% |
| Logistic Regression | 精简(移除冗余) | 97.126% | 0.141% |
每折的平均训练时间也记录在 `feature_set_comparison.csv` 中。对于所有三个模型,使用精简特征集的训练速度始终更快,但节省的时间在每折中不到一秒,因此在此数据集大小下可以忽略不计。绝对计时取决于运行该 notebook 的机器。
**阈值分析(Random Forest,从 19 个扫描值中选取的部分阈值)**
| 阈值 | Precision | Recall | F1 Score | False Positives | False Negatives |
|---|---|---|---|---|---|
| 0.05 | 91.91% | 94.07% | 92.98% | 1063 | 761 |
| 0.15 | 95.33% | 81.34% | 87.79% | 511 | 2394 |
| 0.50(默认) | 96.84% | 63.24% | 76.52% | 265 | 4717 |
| 0.95 | 97.41% | 50.35% | 66.39% | 172 | 6371 |
跨越所有 19 个阈值的完整扫描结果导出到了 `threshold_analysis.csv`。
## 主要发现
- **基于 Pipeline 的预处理可防止数据泄漏。** One-hot encoding 和 scaling 是在每个分层 cross-validation 折叠中拟合的,而不是在整个数据集中拟合,因此报告的 CV 得分是真实的估计,而不是被夸大的。
- **Precision 很高,recall 是薄弱环节。** 在默认阈值下,所有三个模型都将 precision 保持在 91% 以上(Decision Tree 和 Random Forest 高于 96%),这意味着正常流量很少被误分类为攻击。Recall 介于 62% 和 72% 之间,因此实际攻击中有很大一部分被漏报了。
- **Logistic Regression 是最弱的模型,** 正如预期的那样,作为处理非线性可分入侵模式的线性基线——其 F1 (74.47%) 和 MCC (0.5608) 在三者中最低。
- **Decision Tree 在默认阈值下得分最高**(F1 为 82.33%,而 Random Forest 为 76.31%),尽管 Random Forest 在 cross-validation 期间的准确率略高。
- **但该排名是阈值的假象。** Random Forest 具有更好的 ROC-AUC(0.9598 对比 0.8427),它衡量的是独立于任何截断点的排名质量,并且在 0.05 阈值下,其 F1 达到了 92.98%——远高于 Decision Tree 的最佳水平。Random Forest 一直以来对连接的排名都更好;0.50 只是切分其概率的错误位置。
- **移除冗余特征没有任何代价,但也没有任何收益。** 所有三个模型的 Cross-validated 准确率实际上都没有变化(Decision Tree 完全相同,Random Forest 差异不到 0.01 个百分点,Logistic Regression 在精简集上低了 0.16 个百分点——这在其自身的折叠间方差范围之内)。因此,精简集的合理性在于其简洁性和更简单的模型,而不是性能的提升,并且运行时的节省微乎其微。
- **阈值权衡具有强烈的不对称性。** 在整个扫描过程中,recall 从 94.07% 下降到 50.35%,而 precision 仅移动了约五个百分点。将阈值从 0.50 降低到 0.05 会增加大约800 次误报,但能消除近 4,000 次漏报的攻击。由于漏报的入侵通常比误报的代价要大得多,因此 0.05–0.15 区间内的阈值是比默认值更好的操作点。需要注意的一点是:F1 在 0.05(测试的最低值)处达到峰值,因此真正的最佳点可能位于扫描范围之下。
- **Random Forest 是用于此分析的正确模型。** Decision Tree 的预测概率中只有 0.02% 严格介于 0.01 和 0.99 之间,而 Random Forest 为 33.98%,因此对单个树进行阈值扫描几乎不会改变任何决策。
- **未见过的攻击类型导致了这些错误。** 误差分析表明,很大一部分误分类来自于测试集中存在但在训练期间从未见过的攻击类型。这解释了近 99% 的 cross-validation 准确率与 75–83% 的测试准确率之间的差距,并在项目报告的“批判性评估”部分进行了详细讨论。
## 输出文件
从头到尾运行 notebook 会生成以下文件到其工作目录中,将它们复制到 `project_outputs/`,并将该文件夹归档为 `NSL_KDD_Project_Outputs.zip`。
| 文件 | 描述 |
|---|---|
| `class_distribution.png` | 正常与攻击流量对比柱状图 |
| `attack_category_distribution.png` | 攻击类别(DoS、Probe、R2L、U2R)柱状图 |
| `outlier_check.png` | 关键数值特征的对数比例 boxplots |
| `correlation_heatmap.png` | 数值特征的 Pearson 相关性热力图 |
| `confusion_matrices.png` | 所有三个模型并排的混淆矩阵 |
| `threshold_analysis.png` | Precision/Recall/F1 与阈值对比,以及 false positives 与 false negatives 对比 |
| `model_comparison.csv` | 每个模型的测试集 accuracy、precision、recall、F1、MCC 和 ROC-AUC |
| `feature_set_comparison.csv` | 完整与精简特征集:CV accuracy、std dev 和平均拟合时间 |
| `threshold_analysis.csv` | 所有 19 个扫描阈值下的 Precision、recall、F1、FP 和 FN |
| `processed_train_data.csv` | 清理后的训练数据集 |
## 参考文献
1. Nkiama, H., Said, S. M., & Saidu, M. (2016). A Subset Feature Elimination Mechanism for Intrusion Detection System. IJACSA.
2. NSL-KDD Dataset — Canadian Institute for Cybersecurity, University of New Brunswick. https://www.unb.ca/cic/datasets/nsl.html
3. Koopman, C. Network-Intrusion-Detection (参考实现). https://github.com/CynthiaKoopman/Network-Intrusion-Detection
标签:Apex, NoSQL, NSL-KDD, scikit-learn, 决策树, 机器学习, 网络安全, 逆向工具, 随机森林, 隐私保护