简介:这是一份面向计算机相关专业学生与初学者的机器学习实践资源,聚焦于使用UNSW-NB15基准数据集进行网络攻击检测。项目源自个人课程设计与毕业设计,代码已经测试通过,能够直接部署运行,适合用于毕设、课设、大作业或初期项目演示。压缩包共4个文件,包括3个Python源代码文件和1个README说明文档,整体仅12KB,结构轻量、易于阅读。数据集包含多种攻击类型,可验证算法在异常检测场景下的表现;源码实现了逻辑回归二分类、KNN分类器等经典机器学习算法,并提供决策树等模型的相关实现,方便读者对照比较不同算法在入侵检测任务中的分类效果。说明文档对各文件的作用与运行方式进行了简要说明,降低了上手门槛,也便于在此基础上修改扩展,实现其他功能。目前已有143人学习浏览,适合希望快速获得可运行参考实现、理解网络攻击检测建模流程的在校学生与开发者下载使用。 做毕业设计选到这个题目的同学,十有八九是被“UNSW-NB15 数据集”和“机器学习算法”这两个关键词吸引的。这个题目确实很经典:既有网络安全方向的应用背景,又有算法模型可以展开讲,哪怕之前完全没接触过安全领域,只要代码能跑通、指标能出来、答辩能讲清楚,就是一套很稳的毕设方案。项目配套的源码和教程,基本做到了“简单部署即可运行”,功能覆盖数据预处理、特征编码、模型训练、指标评估和可视化,适合网络空间安全、计算机科学与技术等专业的本科毕业设计,也适合刚接触安全AI方向的开发者快速入门。
我会从项目设计思路、数据与特征处理、核心代码实操、常见问题排查四个方面,把这个项目完整拆解一遍,把我在实际跑这类项目时踩过的坑和总结的经验一并写出来。
1. 项目整体设计与思路拆解
1.1 为什么选 UNSW-NB15 而不是 KDD99
很多同学在选题时会纠结数据集选哪个。说实话,UNSW-NB15 是目前做入侵检测方向最合适的选择之一,原因并不复杂:它足够新、足够真实、有权威出处,而且分类粒度细。
UNSW-NB15 由澳大利亚新南威尔士大学网络安全中心(ACCS)发布,通过 IXIA PerfectStorm 工具采集真实网络流量,并融合了合成攻击流量,总共包含约 250 万条记录。训练集大约 175 万条,测试集约 82 万条,覆盖九类攻击:Fuzzers、Analysis、Backdoors、DoS、Exploits、Generic、Reconnaissance、Shellcode、Worms。
拿它和早期的 KDD99 / NSL-KDD 对比一下,优势很明显。下面这个表基本能回答“为什么选它”:
| 数据集 | 发布时间 | 背景环境 | 攻击类型 | 现代代表性 | 适合场景 |
|---|---|---|---|---|---|
| KDD99 | 1999年 | 模拟军事网络,仿真环境 | 4类 | 较差,特征老旧 | 只能做入门演示 |
| NSL-KDD | 2009年 | 基于 KDD99 处理冗余后得到 | 4类 | 消除了冗余,但本质仍是老数据 | 算法对比实验 |
| UNSW-NB15 | 2015年 | 真实网络流量 + 现代攻击工具生成 | 9类 | 强,特征设计更接近真实环境 | 毕设、论文、实战项目 |
所以,如果你在开题阶段还在纠结数据集,直接选 UNSW-NB15 就对了。它既有二分类的“正常/攻击”标签(Label),也有多分类的“攻击具体类型”标签(attack_cat),一个数据集能同时支持两种实验设计,做毕设内容非常划算。
1.2 为什么用传统机器学习,而不是直接上深度学习
既然都做“检测网络攻击的机器学习算法”了,为什么不直接堆 LSTM、Transformer?这个问题答辩老师大概率会问,我自己做的时候也认真想过。
核心原因是:传统机器学习在这个题目上有不可替代的优势,尤其是可解释性。毕业设计需要你把“为什么这么做”讲明白,决策树和随机森林可以直接输出特征重要性,逻辑回归有明确的权重系数,这些都能在答辩 PPT 里直观展示。反观深度学习模型,参数动辄百万级,调一次训练半天,答辩时被问到“你这个模型为什么效果好”很容易被问住。
另外,从工程角度看,传统机器学习方案在 CPU 环境下就能跑完整个实验流程。scikit-learn 训练一个随机森林,在抽样后的数据集上几分钟内就能出结果;而同样的时间,深度学习连数据预处理可能都没跑完。
当然,UNSW-NB15 数据集也完全可以作为深度学习的输入,做毕设时如果学有余力,在传统机器学习方法的基础上加一个“CNN/RNN 对比实验”是很加分的扩展,但核心方案用传统机器学习是完全合理且安全的选择。
1.3 项目整体流程与架构
整个项目的核心流程可以概括为一条数据管道:
CSV 加载 → 数据清洗(缺失值 / INFINITE)→ 类别特征编码 → 特征标准化 → 训练/测试划分 → 模型训练 → 指标评估 → 可视化源码的组织思路也按照这条链路拆。每个环节都是独立的函数或脚本,这样做的最大好处是:你可以单独替换任意一环而不影响整体。比如今天想试试 XGBoost,只需要在“模型训练”函数里加一个新模型对象;想换一套特征组合,只改“特征选择”处的代码就行。
我建议拿到源码之后不要急着全量跑,先按流程理解数据管道,再逐步跑通,这样后面调参、扩展都会顺手很多。
2. 核心细节解析:数据和特征处理是关键
2.1 数据集字段结构:49 列分别是什么
UNSW-NB15 的每条数据有 49 列,其中 45 列是特征,最后几列是标签信息。常见的几个核心字段如下:
| 字段分类 | 字段名 | 含义说明 |
|---|---|---|
| 流基础信息 | srcip、sport、dstip、dsport | 源/目的 IP 和端口 |
| 协议状态 | proto、state、service | 协议类型、连接状态、应用层服务 |
| 时间特征 | dur、spkts、dpkts | 连接时长、源/目的包数 |
| 负载流量 | sbytes、dbytes、sttl、dttl | 字节数、TTL 等信息 |
| 统计特征 | ct_srv_src、ct_dst_sport_ltm 等 | 连接计数、并发连接数 |
第 47 列是Label(二分类标签,0 正常 / 1 攻击),这是我们做二分类实验的预测目标。第 48 列是attack_cat(攻击类别标注,9 类攻击加 Normal 共 10 个值),这是做多分类实验的预测目标。
做实验时一个最常见的误操作,是把 49 列全部当成特征丢进模型。如果 attack_cat 被当成了输入特征,模型准确率会虚高到 99% 以上,这在论文里叫“标签泄露”(label leakage),是非常严重的错误。正确做法是:特征列只取前 45 列(或根据需求剔除部分列),标签列单独切片。
2.2 数据清洗:处理 INFINITE 和缺失值的正确姿势
拿到原始 CSV 直接跑训练,十有八九会报错,原因就藏在数据本身。UNSW-NB15 里的某些字段(尤其是一些计数类字段)存在INFINITE字符串,pandas 读进来之后默认变成 object 类型,直接喂给机器学习模型必然类型报错。
标准处理流程是:加载数据后先统一替换异常值,再检查缺失量。可以这样做:
import pandas as pd import numpy as np df = pd.read_csv('UNSW_NB15_training-set.csv', low_memory=False) # 把 INFINITE 替换为 NaN,再看每列缺失情况 df.replace('INFINITE', np.nan, inplace=True) missing = df.isnull().sum() print(missing[missing > 0])处理缺失值一般就三种策略:缺失率较低的直接删除行;缺失率中等且对结果影响小的用均值/中位数填充;缺失率很高且是干扰特征的直接删列。做毕设时不用纠结,优先用“删除行 + 数值列中位数填充”的组合,稳定省事。
2.3 特征编码和标准化:新手最容易忽略的一步
UNSW-NB15 里proto、service、state这几个字段是字符串类别特征,标签编码(LabelEncoder)是把它们变成数字的方法。这里有个不少新手会踩的坑:LabelEncoder 只是给字符串分配了一个编号,比如把 0、1、2 分配给不同协议,这个编号本身没有大小含义。如果把这个编码后的结果直接当数值特征用,模型可能会学到错误的“顺序关系”。
所以更稳妥的做法是:类别特征用独热编码(One-Hot Encoding),或者至少要多留一个心眼,确认编码后的特征没有被模型当成连续值。毕设场景下不要求绝对最优,但用了独热编码,答辩被问到时答起来更顺。
标准化这一步同样关键。UNSW-NB15 特征的量纲差异巨大,有的特征在 0~1 之间,有的是几千几万。如果不做标准化,SVM 和 KNN 这类距离敏感的算法会被数值范围大的特征彻底主导。标准做法是用StandardScaler,先把训练集 fit 再 transform,测试集只做 transform。这里千万注意:标准化是先在训练集上拟合,再应用到测试集,不能把整个数据集一起 fit,否则会引入测试集信息,导致评估结果虚高。
3. 实操过程与核心环节实现
3.1 环境准备与依赖
拿到源码后第一件事不是改代码,而是先把环境搭好。项目依赖非常标准,都是 Python 生态里的老熟脸:
pip install pandas numpy scikit-learn matplotlib seaborn如果你打算扩展试验,可以再加一个xgboost,后面我会讲它在毕设中的加分用法。Python 版本建议 3.8 以上,scikit-learn 别装太老,1.0 以上版本在 API 上更友好。
核心模块功能如下:
| 模块/脚本 | 负责功能 |
|---|---|
| 数据处理 | 加载 CSV、清洗异常值、标签编码、标准化 |
| 模型训练 | 定义多个分类器、训练与测试集划分 |
| 评估可视化 | 生成准确率、F1、召回率、混淆矩阵、特征重要性 |
| 主入口 | 串联整个流程,一键运行 |
3.2 核心代码骨架与说明
整个源码的“灵魂”可以浓缩成下面这段代码逻辑。拿到项目后,优先理解这段链路,后面改参数、加功能都是在它上面做文章。
from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder, StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix, accuracy_score import pandas as pd # 1. 加载数据(以训练集为例) df = pd.read_csv('UNSW_NB15_training-set.csv', low_memory=False) df.replace('INFINITE', pd.NA, inplace=True) df = df.dropna() # 2. 构造特征矩阵 X 和标签 y:只取特征列 + Label 列 X = df.iloc[:, :45].copy() y = df['Label'].values # 3. 将类别特征做标签编码 cate_cols = X.select_dtypes(include=['object']).columns for col in cate_cols: le = LabelEncoder() X[col] = le.fit_transform(X[col].astype(str)) # 4. 标准化(先划分,再 fit/transform,避免数据泄露) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y ) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 5. 训练随机森林 rf = RandomForestClassifier(n_estimators=60, random_state=42, n_jobs=-1) rf.fit(X_train_scaled, y_train) y_pred = rf.predict(X_test_scaled) # 6. 输出指标 print("Accuracy:", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred))这段代码虽然短,但已经完成了“加载→清洗→编码→标准化→训练→评估”的全流程。有一点需要特别提一下:代码里用了stratify=y,也就是分层抽样划分数据集,目的是保证训练集和测试集里正常流量/攻击流量的比例与原始数据一致。在类别不平衡的入侵检测场景中,分层抽样是必须的,否则随机划分很容易让测试集里某一类样本比例失衡,指标波动会很大。
3.3 各模型参数怎么调:先跑通,再优化
源码默认可能包含逻辑回归、决策树、KNN、随机森林、SVM 等常见模型,实际使用时我建议按下面的优先级来做:
| 模型 | 推荐参数范围 | 毕设定位 |
|---|---|---|
| 逻辑回归 | C=0.1~10 | 基线对比,训练最快 |
| 决策树 | max_depth=10~30 | 最易解释,出图好看 |
| 随机森林 | n_estimators=50~200, max_features='sqrt' | 主推模型,效果稳定 |
| KNN | k=5~20 | 能体现标准化重要性 |
| SVM | C=1~10, kernel='rbf' | 小样本可用,太大跑不动 |
| XGBoost | n_estimators=100, learning_rate=0.1 | 追求精度时可以加 |
以随机森林为例,n_estimators是我个人最常调的参数。它在 60 到 100 之间能取得不错的性能和速度平衡,超过 200 之后收益很小,而训练时间明显增加。max_depth建议从默认值往下调,因为攻击检测数据里存在大量复杂非线性关系,深度过大容易过拟合训练噪声。
SVM 是我特别想提醒的:UNSW-NB15 全量数据太大,直接用 RBF 核 SVM 训练非常慢,可能要跑几个小时。源码里如果带了 SVM,大概率是在抽样子集上跑的。毕设里使用 SVM 时,我的建议是:要么做随机抽样 5~10 万条数据再训练,要么干脆把 SVM 定位成“小样本对比实验”,别让它拖慢整体节奏。
3.4 结果呈现:别只贴准确率
做毕设最容易踩的另一个坑,是只输出一个准确率。UNSW-NB15 数据集中正常流量和攻击流量不是完全均衡的,准确率高不一定代表模型好。正确做法是至少展示下面三项:
- 分类报告:Precision、Recall、F1-score,重点看攻击类别的召回率,因为漏报攻击的代价远高于误报正常流量。
- 混淆矩阵:用 seaborn 画热力图,能直观看到哪类攻击被漏掉了。这在答辩演示时非常加分。
- ROC-AUC:画出 ROC 曲线并计算 AUC 值,体现模型在不同阈值下的检测能力。
画混淆矩阵的核心代码很固定:
import matplotlib.pyplot as plt import seaborn as sns cm = confusion_matrix(y_test, y_pred) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('Predicted') plt.ylabel('Actual') plt.show()可视化不一定要多炫,但逻辑要清晰。比如既然数据集支持多分类标签,就可以在二分类结果之后,再用attack_cat做一次九分类实验,画一张多分类混淆矩阵热力图,这会让整个项目内容立刻丰富一截。
4. 常见问题与排查技巧实录
这部分内容是我实际跑类似项目时踩过坑之后沉淀下来的,遇到问题可以直接对照排查。
4.1 内存不足,加载数据卡死
UNSW-NB15 训练集 CSV 文件比较大,如果电脑配置一般,直接用 pandas 读全量数据可能内存占用到 90% 以上。解决办法有三个:一是读数据时根据实际需求只保留用得到的列,用usecols参数指定;二是先对数据做随机抽样,比如取 30~50 万条做实验,训练结果仍然很有代表性;三是确认不再需要某些中间 DataFrame 后及时del释放内存。我在自己机器上跑的时候,抽样 40 万条数据,随机森林 60 棵树的训练时间基本在 1~3 分钟内,完全可靠。
4.2 特征处理顺序错误导致结果虚高
这是我见过最多的问题。有同学先对整个数据集做标准化,再划分训练测试集,导致测试集的信息在训练时就已经被模型“见过”,最终准确率高到不真实,答辩时一被追问就露馅。正确顺序永远是:先划分 train/test,再在训练集上 fit 预处理器,最后用同一个预处理器 transform 测试集。
4.3 准确率高但召回率低,模型全被偏置带跑了
如果发现准确率 90% 以上,但攻击类别的召回率只有 60%,基本是类别不平衡或者特征泄漏之外的“偏置问题”。这时优先做的三件事是:调整类别权重,在随机森林里设置class_weight='balanced';使用分层抽样划分数据集;观察混淆矩阵,确认是哪一类攻击被大量误判。被误判的往往是小样本攻击类型比如 Shellcode、Worms,这类攻击记录数少,模型很难学到特征,可以在论文中诚实地分析这一点,这反而是加分项。
4.4 关于答辩:抓住三个必答点
做这个题目,答辩时一定会被问到的三个问题是:
- 为什么选这些特征?回答思路:结合 45 个特征的含义,从“连接基础属性、流量负载、连接历史统计”三个维度解释,并说明利用了随机森林的特征重要性排序做了筛选。
- 为什么选这几个模型?回答思路:对比逻辑回归(线性基线与可解释性)、决策树/随机森林(集成学习、特征重要性分析)、SVM(高维分类能力),说明是为了覆盖不同类别的算法思想。
- 这套方案在真实环境中能用吗?回答思路:强调本项目是研究性验证,真实场景需要处理在线流量采集、实时特征提取、模型更新等问题。承认局限,再加一句“后续可以结合流式处理框架做扩展”,这个回答很稳妥。
最后分享一个实操中的小经验:实验的随机种子一定要固定。训练测试集划分、模型初始化都设置random_state=42,固定一个可复现的种子。否则每次跑出来的结果都不一样,不仅自己调试时容易慌,被要求复现实验时更是大麻烦。我见过有同学答辩前一天调参跑出一个很好的准确率,第二天想复现,结果不固定种子,换了随机划分后结果掉了一大截,那种情况非常狼狈。固定住随机种子,整体实验数据就稳住了,后续怎么改特征和参数,对比起来才有可信度。
这个题目扩展空间也很大,后续想加内容的话,可以从多分类攻击识别、特征选择优化、实时流量检测这些方向入手,能做的方向很多。先把现有的二分类主流程跑透,把指标和图表整理好,这套毕设项目就已经非常扎实了。
本文还有配套的精品资源,点击获取