CIC-IDS-2018 数据集实战:基于 Scikit-learn 的 7 类攻击检测模型构建与评估

发布时间:2026/7/5 12:01:44
CIC-IDS-2018 数据集实战:基于 Scikit-learn 的 7 类攻击检测模型构建与评估 CIC-IDS-2018 数据集实战基于 Scikit-learn 的 7 类攻击检测模型构建与评估网络安全领域的研究者和数据科学爱好者们是否曾为缺乏高质量数据集而苦恼CIC-IDS-2018 数据集的出现为我们提供了一个难得的实战机会。这个由加拿大网络安全研究所精心构建的数据集不仅包含七种常见攻击类型还模拟了真实企业网络环境是测试入侵检测系统的理想选择。本文将带您从数据加载到模型评估完整构建一个能够识别多种网络攻击的机器学习系统。不同于简单的理论讲解我们将重点关注实际应用中的关键环节如何处理类别不平衡哪些特征对检测攻击最有效如何选择最适合的评估指标这些问题的答案都将在接下来的实战中一一揭晓。1. 环境准备与数据加载在开始建模之前我们需要搭建合适的工作环境。推荐使用 Python 3.8 和 Jupyter Notebook 进行实验这样可以方便地记录和分享分析过程。以下是必需的库及其作用# 基础数据处理 import pandas as pd import numpy as np # 机器学习工具 from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from xgboost import XGBClassifier from sklearn.metrics import classification_report # 可视化 import matplotlib.pyplot as plt import seaborn as snsCIC-IDS-2018 数据集可以通过 AWS S3 直接下载。数据集包含多个 CSV 文件每个文件对应不同日期的网络流量记录。为简化初次实验我们可以先下载一个中等大小的文件进行测试aws s3 cp --no-sign-request s3://cse-cic-ids2018/Processed Traffic Data for ML Algorithms/Friday-16-02-2018_TrafficForML_CICFlowMeter.csv ./data/加载数据时需要注意由于数据集较大约 300MB直接读取可能会消耗大量内存。我们可以使用 Pandas 的分块读取功能chunk_size 100000 chunks pd.read_csv(data/Friday-16-02-2018_TrafficForML_CICFlowMeter.csv, chunksizechunk_size) df pd.concat(chunks)数据集包含 80 个流量特征和 1 个标签列。初步检查数据质量时需要特别关注缺失值比例特征的数据类型标签的分布情况print(f数据集形状: {df.shape}) print(\n缺失值统计:) print(df.isnull().sum().sort_values(ascendingFalse).head(10)) print(\n标签分布:) print(df[Label].value_counts())2. 数据预处理与特征工程原始数据往往不能直接用于建模需要进行一系列预处理步骤。CIC-IDS-2018 数据集虽然已经过初步处理但仍存在一些需要解决的问题。2.1 处理类别不平衡网络流量数据通常存在严重的类别不平衡 - 正常流量远多于攻击流量。这会导致模型偏向多数类。我们可以采用以下策略# 查看类别分布 label_counts df[Label].value_counts() plt.figure(figsize(10,6)) sns.barplot(xlabel_counts.index, ylabel_counts.values) plt.xticks(rotation45) plt.title(类别分布) plt.show() # 使用分层抽样保持类别比例 train_df, test_df train_test_split(df, test_size0.3, stratifydf[Label], random_state42)对于极端不平衡的情况可以考虑过采样少数类如 SMOTE欠采样多数类使用类别权重参数2.2 特征选择与缩放80 个特征中有些可能相关性很低或冗余。我们可以通过以下方法筛选特征# 删除常数列和缺失率高的列 constant_cols [col for col in df.columns if df[col].nunique() 1] df df.drop(columnsconstant_cols) # 计算特征与标签的相关性 numeric_df df.select_dtypes(include[np.number]) correlations numeric_df.corr()[Label].abs().sort_values(ascendingFalse) top_features correlations.head(30).index.tolist() # 标准化数值特征 scaler StandardScaler() X_train scaler.fit_transform(train_df[top_features]) X_test scaler.transform(test_df[top_features])提示在实际应用中特征选择应该基于领域知识和技术分析相结合。网络流量中的某些特征如流持续时间、数据包大小分布通常对检测攻击特别有用。3. 模型构建与训练有了清洗好的数据我们可以开始构建分类模型。针对网络入侵检测任务我们比较两种表现优异的算法随机森林和 XGBoost。3.1 随机森林模型随机森林因其鲁棒性和可解释性常被用于安全领域rf_params { n_estimators: 100, max_depth: 15, min_samples_split: 5, class_weight: balanced, random_state: 42 } rf_model RandomForestClassifier(**rf_params) rf_model.fit(X_train, train_df[Label])3.2 XGBoost 模型XGBoost 在处理结构化数据方面表现优异适合我们的任务xgb_params { n_estimators: 200, max_depth: 10, learning_rate: 0.1, subsample: 0.8, colsample_bytree: 0.8, scale_pos_weight: len(train_df[train_df[Label]Benign])/len(train_df[train_df[Label]!Benign]), random_state: 42 } xgb_model XGBClassifier(**xgb_params) xgb_model.fit(X_train, train_df[Label])3.3 特征重要性分析理解模型依赖哪些特征做出判断对安全分析至关重要# 随机森林特征重要性 rf_importances pd.DataFrame({ feature: top_features, importance: rf_model.feature_importances_ }).sort_values(importance, ascendingFalse) plt.figure(figsize(12,8)) sns.barplot(ximportance, yfeature, datarf_importances.head(15)) plt.title(随机森林特征重要性 Top 15) plt.show()4. 模型评估与比较评估入侵检测系统需要特别关注召回率Recall因为漏报攻击比误报正常流量更危险。我们使用多种指标全面评估模型性能。4.1 分类报告与混淆矩阵def evaluate_model(model, X_test, y_test): y_pred model.predict(X_test) print(classification_report(y_test, y_pred)) cm confusion_matrix(y_test, y_pred) plt.figure(figsize(10,7)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabelsmodel.classes_, yticklabelsmodel.classes_) plt.xlabel(预测标签) plt.ylabel(真实标签) plt.title(混淆矩阵) plt.show() print(随机森林性能:) evaluate_model(rf_model, X_test, test_df[Label]) print(\nXGBoost性能:) evaluate_model(xgb_model, X_test, test_df[Label])4.2 多模型性能对比为全面比较模型我们计算多个指标并汇总模型准确率加权F1Benign召回率攻击平均召回率训练时间(s)随机森林0.9820.9810.9920.94345.2XGBoost0.9850.9840.9940.95662.8从结果可以看出XGBoost 在多数指标上略优于随机森林但训练时间更长。对于实时性要求高的场景随机森林可能是更好的选择。4.3 跨日测试验证为确保模型泛化能力我们可以在不同日期的数据上测试# 加载另一天的数据 new_day_df pd.read_csv(data/Thursday-22-02-2018_TrafficForML_CICFlowMeter.csv) X_new scaler.transform(new_day_df[top_features]) print(随机森林在新数据上的表现:) evaluate_model(rf_model, X_new, new_day_df[Label])这种跨时间测试能有效验证模型是否学习到了真正的攻击模式而非特定日期的噪声。5. 模型优化与部署建议获得基线模型后我们可以通过多种方式进一步提升性能5.1 超参数调优使用网格搜索或贝叶斯优化寻找最佳参数组合from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [50, 100, 200], max_depth: [10, 15, 20], min_samples_split: [2, 5, 10] } grid_search GridSearchCV( RandomForestClassifier(class_weightbalanced, random_state42), param_grid, cv3, scoringf1_weighted, n_jobs-1 ) grid_search.fit(X_train, train_df[Label])5.2 集成方法结合多个模型的预测结果可以进一步提升性能from sklearn.ensemble import VotingClassifier ensemble VotingClassifier( estimators[ (rf, rf_model), (xgb, xgb_model) ], votingsoft, n_jobs-1 ) ensemble.fit(X_train, train_df[Label])5.3 部署注意事项将模型部署到生产环境时需要考虑实时性要求根据流量大小选择合适的预测频率模型更新定期用新数据重新训练模型解释性为安全分析人员提供足够的决策依据资源消耗平衡模型复杂度和计算资源# 示例保存和加载模型 import joblib joblib.dump(rf_model, ids_rf_model.pkl) loaded_model joblib.load(ids_rf_model.pkl)在实际部署中可以将模型封装为 REST API 或集成到现有安全系统中。同时建议设置一个反馈机制收集安全分析人员对预测结果的修正用于持续改进模型。