UNSW-NB15数据集实战:从零开始构建你的第一个网络入侵检测模型(附完整代码)

张开发
2026/6/6 7:09:25 15 分钟阅读
UNSW-NB15数据集实战:从零开始构建你的第一个网络入侵检测模型(附完整代码)
UNSW-NB15数据集实战从零开始构建你的第一个网络入侵检测模型附完整代码网络安全领域正面临前所未有的挑战每天都有数以百万计的网络攻击尝试突破防线。在这个背景下入侵检测系统IDS成为了保护网络基础设施的第一道防线。而构建一个高效的IDS离不开高质量的数据集和合理的机器学习模型选择。UNSW-NB15数据集作为近年来最受关注的网络流量数据集之一为研究人员和开发者提供了一个理想的实验平台。本文将带你从零开始完整实现一个基于UNSW-NB15数据集的网络入侵检测模型。不同于简单的理论介绍我们将重点关注实际操作中的每一个细节从数据获取、预处理到特征工程再到模型训练和评估。无论你是网络安全领域的新手还是希望将机器学习应用于安全领域的开发者都能从这篇实战指南中获得实用价值。1. 环境准备与数据获取构建入侵检测模型的第一步是搭建合适的工作环境并获取数据集。现代机器学习项目通常需要一系列工具和库的支持而UNSW-NB15数据集也需要特定的处理方式才能发挥最大价值。1.1 搭建Python工作环境推荐使用Anaconda创建独立的Python环境避免依赖冲突。以下命令可以创建一个名为ids的新环境conda create -n ids python3.8 conda activate ids安装必要的Python库pip install pandas numpy scikit-learn matplotlib seaborn xgboost对于深度学习模型可以额外安装TensorFlow或PyTorchpip install tensorflow1.2 下载与理解UNSW-NB15数据集UNSW-NB15数据集可以从新南威尔士大学官网获取。数据集包含多个文件但我们需要重点关注以下几个UNSW-NB15_training-set.csv: 训练集包含175,341条记录UNSW-NB15_testing-set.csv: 测试集包含82,332条记录NUSW-NB15_features.csv: 特征描述文件解释每个字段的含义数据集中的每条记录代表一次网络连接包含49个特征和1个标签正常或攻击。攻击类型又细分为9类FuzzersAnalysisBackdoorsDoSExploitsGenericReconnaissanceShellcodeWorms提示虽然数据集提供了多个文件但初学者可以专注于训练集和测试集其他文件主要用于深入分析。2. 数据预处理与探索性分析获得原始数据后我们需要进行一系列预处理步骤使数据适合机器学习模型的训练。这一阶段的工作往往决定了模型的最终性能。2.1 数据加载与初步检查使用Pandas加载数据集import pandas as pd train_df pd.read_csv(UNSW-NB15_training-set.csv) test_df pd.read_csv(UNSW-NB15_testing-set.csv) print(f训练集形状: {train_df.shape}) print(f测试集形状: {test_df.shape})检查数据的基本信息train_df.info()重点关注以下几个方面缺失值情况数据类型分布类别特征的唯一值数量2.2 处理缺失值与异常值UNSW-NB15数据集相对干净但仍需检查和处理可能的异常# 检查缺失值 print(train_df.isnull().sum()) # 处理缺失值示例 train_df.fillna(0, inplaceTrue)对于数值特征可以检查其分布并处理异常值import seaborn as sns import matplotlib.pyplot as plt # 绘制数值特征的分布 numeric_cols train_df.select_dtypes(include[int64, float64]).columns for col in numeric_cols[:5]: # 只展示前5个 plt.figure(figsize(8,4)) sns.boxplot(xtrain_df[col]) plt.title(fBoxplot of {col}) plt.show()2.3 特征工程UNSW-NB15数据集已经提供了丰富的特征但我们仍可以进行一些优化处理类别特征使用独热编码或标签编码特征缩放标准化或归一化数值特征特征选择移除低方差或高相关性的特征from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer # 定义数值和类别特征 numeric_features [dur, spkts, dpkts, sbytes, dbytes] categorical_features [proto, service, state] # 创建预处理管道 preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), numeric_features), (cat, OneHotEncoder(handle_unknownignore), categorical_features) ]) # 应用预处理 X_train preprocessor.fit_transform(train_df)3. 模型构建与训练有了预处理后的数据我们可以开始构建和训练入侵检测模型。考虑到网络入侵检测的特点我们将尝试几种不同的算法并比较它们的性能。3.1 基准模型随机森林随机森林因其良好的解释性和不错的性能常被用作基准模型from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report # 初始化模型 rf_model RandomForestClassifier(n_estimators100, random_state42) # 训练模型 rf_model.fit(X_train, train_df[label]) # 在测试集上评估 X_test preprocessor.transform(test_df) y_pred rf_model.predict(X_test) print(classification_report(test_df[label], y_pred))3.2 提升模型XGBoostXGBoost通常能提供更好的性能尤其是在处理不平衡数据时from xgboost import XGBClassifier # 初始化XGBoost模型 xgb_model XGBClassifier( n_estimators200, max_depth6, learning_rate0.1, subsample0.8, colsample_bytree0.8, random_state42 ) # 训练模型 xgb_model.fit(X_train, train_df[label]) # 评估 y_pred_xgb xgb_model.predict(X_test) print(classification_report(test_df[label], y_pred_xgb))3.3 深度学习模型神经网络对于更复杂的模式识别可以尝试深度学习模型from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout # 构建模型 model Sequential([ Dense(128, activationrelu, input_shape(X_train.shape[1],)), Dropout(0.3), Dense(64, activationrelu), Dropout(0.3), Dense(1, activationsigmoid) ]) # 编译模型 model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy]) # 训练模型 history model.fit( X_train, train_df[label], epochs10, batch_size256, validation_split0.2 )4. 模型评估与优化训练完模型后我们需要全面评估其性能并根据评估结果进行优化。入侵检测系统的评估有其特殊性不能仅看准确率。4.1 评估指标选择对于入侵检测系统特别重要的指标包括检测率(Recall/True Positive Rate): 正确识别的攻击占所有攻击的比例误报率(False Positive Rate): 正常流量被误判为攻击的比例F1分数: 精确率和召回率的调和平均from sklearn.metrics import confusion_matrix, roc_auc_score # 计算混淆矩阵 cm confusion_matrix(test_df[label], y_pred_xgb) print(Confusion Matrix:) print(cm) # 计算ROC AUC roc_auc roc_auc_score(test_df[label], y_pred_xgb) print(fROC AUC Score: {roc_auc:.4f})4.2 处理类别不平衡网络流量数据通常存在严重的不平衡问题正常流量远多于攻击流量。我们可以采用以下策略重采样过采样少数类或欠采样多数类类别权重在模型训练中为不同类别分配不同权重异常检测算法如One-Class SVM# 计算类别权重 from sklearn.utils.class_weight import compute_class_weight classes [0, 1] weights compute_class_weight(balanced, classesclasses, ytrain_df[label]) class_weights dict(zip(classes, weights)) # 使用类别权重重新训练XGBoost xgb_model_balanced XGBClassifier( n_estimators200, max_depth6, learning_rate0.1, scale_pos_weightweights[1]/weights[0], random_state42 ) xgb_model_balanced.fit(X_train, train_df[label])4.3 特征重要性分析理解哪些特征对检测结果影响最大有助于优化模型和解释结果# 获取特征重要性 feature_importance xgb_model.feature_importances_ # 获取特征名称考虑独热编码后的特征 feature_names numeric_features \ list(preprocessor.named_transformers_[cat].get_feature_names_out(categorical_features)) # 创建特征重要性DataFrame fi_df pd.DataFrame({feature: feature_names, importance: feature_importance}) fi_df fi_df.sort_values(importance, ascendingFalse) # 可视化前20个重要特征 plt.figure(figsize(10,8)) sns.barplot(ximportance, yfeature, datafi_df.head(20)) plt.title(Top 20 Important Features) plt.show()5. 部署与实际应用训练好的模型需要部署到实际环境中才能发挥作用。虽然完整的生产部署需要考虑更多因素但我们可以先了解基本流程。5.1 模型保存与加载将训练好的模型保存到文件便于后续使用import joblib # 保存预处理管道和模型 joblib.dump(preprocessor, preprocessor.pkl) joblib.dump(xgb_model_balanced, ids_model.pkl) # 加载模型 loaded_preprocessor joblib.load(preprocessor.pkl) loaded_model joblib.load(ids_model.pkl)5.2 构建预测API使用Flask构建简单的预测APIfrom flask import Flask, request, jsonify import pandas as pd app Flask(__name__) app.route(/predict, methods[POST]) def predict(): # 获取输入数据 input_data request.json input_df pd.DataFrame([input_data]) # 预处理 processed_data loaded_preprocessor.transform(input_df) # 预测 prediction loaded_model.predict(processed_data) probability loaded_model.predict_proba(processed_data)[:,1] # 返回结果 return jsonify({ prediction: int(prediction[0]), probability: float(probability[0]) }) if __name__ __main__: app.run(host0.0.0.0, port5000)5.3 性能监控与模型更新部署后需要持续监控模型性能记录预测结果和实际结果用于评估模型在生产环境的表现设置性能阈值当性能下降到阈值以下时触发重新训练定期重新训练使用新收集的数据更新模型# 简单的性能监控示例 def monitor_performance(y_true, y_pred, threshold0.9): from sklearn.metrics import recall_score current_recall recall_score(y_true, y_pred) if current_recall threshold: print(警告模型性能下降考虑重新训练) return False return True6. 进阶技巧与优化方向构建了基础模型后我们可以考虑一些进阶优化进一步提升系统性能。6.1 集成学习方法结合多个模型的预测结果往往能获得更好的性能from sklearn.ensemble import VotingClassifier # 定义多个基模型 from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC model1 LogisticRegression(max_iter1000, random_state42) model2 SVC(probabilityTrue, random_state42) model3 XGBClassifier(random_state42) # 创建集成模型 ensemble VotingClassifier( estimators[(lr, model1), (svc, model2), (xgb, model3)], votingsoft ) # 训练集成模型 ensemble.fit(X_train, train_df[label]) # 评估 y_pred_ens ensemble.predict(X_test) print(classification_report(test_df[label], y_pred_ens))6.2 时间序列分析网络流量具有时间相关性可以考虑时间序列特征滑动窗口统计计算最近N次连接的特征统计量时间衰减特征给近期事件更高权重序列模型如LSTM、GRU等# 示例添加简单的时间窗口特征 def add_time_window_features(df, window_size5): df df.sort_values(id) # 假设id按时间顺序递增 numeric_cols [dur, spkts, dpkts, sbytes, dbytes] for col in numeric_cols: df[f{col}_rolling_mean] df[col].rolling(windowwindow_size).mean() df[f{col}_rolling_std] df[col].rolling(windowwindow_size).std() return df train_df_time add_time_window_features(train_df)6.3 自动化机器学习使用AutoML工具自动寻找最优模型和参数from tpot import TPOTClassifier # 初始化TPOT tpot TPOTClassifier( generations5, population_size20, verbosity2, random_state42, n_jobs-1 ) # 运行AutoML注意这会花费较长时间 tpot.fit(X_train, train_df[label]) # 评估最佳管道 print(tpot.score(X_test, test_df[label]))7. 实际挑战与解决方案在实际应用中我们会遇到各种挑战。了解这些挑战及其解决方案有助于构建更健壮的系统。7.1 概念漂移问题网络攻击模式会随时间变化导致模型性能下降。解决方案包括持续学习定期用新数据更新模型漂移检测监控模型性能或数据分布变化集成新旧模型结合对新旧数据表现好的模型# 简单的概念漂移检测示例 def detect_concept_drift(new_data, old_data, threshold0.05): from scipy.stats import ks_2samp p_values [] for col in numeric_cols: _, p_value ks_2samp(old_data[col], new_data[col]) p_values.append(p_value) avg_p sum(p_values)/len(p_values) return avg_p threshold7.2 实时性要求入侵检测通常需要实时或近实时处理流式处理使用Spark Streaming或Flink处理实时数据轻量级模型选择计算效率高的算法增量学习支持在线更新的模型# 使用支持增量学习的模型 from sklearn.linear_model import SGDClassifier sgd_model SGDClassifier(losslog_loss, max_iter1000, random_state42) sgd_model.fit(X_train[:10000], train_df[label][:10000]) # 初始训练 # 增量更新 for i in range(10000, len(train_df), 1000): batch_X X_train[i:i1000] batch_y train_df[label][i:i1000] sgd_model.partial_fit(batch_X, batch_y, classes[0,1])7.3 可解释性需求安全团队需要理解模型的决策依据SHAP值分析解释每个特征对预测的贡献LIME方法局部可解释模型决策规则提取将复杂模型转化为规则集import shap # 计算SHAP值 explainer shap.TreeExplainer(xgb_model) shap_values explainer.shap_values(X_test[:100]) # 只计算前100个样本 # 可视化单个预测的解释 shap.force_plot(explainer.expected_value, shap_values[0,:], X_test[0])

更多文章