首页 / 资讯中心 / 文章详情

入侵检测源码复现:KDD99数据集与CNN模型评估指南

入侵检测源码复现:KDD99数据集与CNN模型评估指南 ★ FEATURED ARTICLE
简介这份基于Python机器学习的网络入侵检测系统源码源自个人毕业设计项目评审分达到98分所有代码均经过严格调试可正常运行主要面向计算机、自动化等相关专业的学生或从业者尤其适合用作期末课程设计、课程大作业或毕业设计参考也适合对入侵检测感兴趣的开发者学习。压缩包共16个文件大小17.52MB包含Python脚本main.py、cnn_main.py、handle2.py等、KDDCUP入侵检测数据集kddcup.data.gz等、项目配置文件xml、iml及说明文档md整体目录结构清晰便于快速定位与学习。系统基于机器学习算法对网络入侵行为进行分类识别测试正确率可达99.5%具备较强的实用性和借鉴价值。目前已有826人学习下载获得一定认可。通过源码可系统掌握数据预处理、特征选择、模型训练与评估等完整流程内置数据集可直接运行复现实验基础扎实的读者还可在此基础上修改调整实现类似功能。1. 拿到99.5%正确率的入侵检测源码先确认这个数字的来路一份标着“正确率可达99.5%”的基于python机器学习的网络入侵检测系统源码拆包后第一件事不是复现而是确认这个数字在什么评估口径下算出来的。答案是KDD Cup 1999——入侵检测领域被引用最多、也最经典的公开基准数据集。这份源码真正值钱的地方是它把数据预处理、CNN训练、TensorBoard日志串成了一条可完整运行的链路而不是那一个准确率数字本身。它适合正在做毕设、课程大作业、期末设计的学生也适合想快速了解入侵检测分类流程的从业者。不适合想直接拿它上生产的人——KDD99的数据分布是二十多年前的现实流量比它复杂得多。2. 数据与模型选型KDD99四组特征和三条代码主线怎么分工2.1 KDD99的特征结构41列里藏着四组信息KDD99的每一条记录都是一个网络连接的统计摘要共42列前41列是特征最后一列是标签。别小看这41个特征它们的语义分四组9个基本连接特征描述协议类型、服务端口、连接时长这类最原始的信息13个内容特征记录登录失败次数、是否root、文件创建次数等还有18个统计特征分为9个基于时间的窗口统计和9个基于主机的窗口统计。后两组是数据集的作者提前算好的这也是KDD99在当年很超前的地方——它把“流量特征工程”也一起交付了。标签列分normal和攻击两大类攻击又可以粗分四小类DoS拒绝服务、Probe扫描探测、R2L远程非法访问本地、U2R本地提权。真实分布很不均衡DoS在数量上占绝对大头而U2R整个10%子集里只有几十条。这个不均衡直接决定了后面我说的“99.5%正确率的真相”——大类好分小类极难准确率却几乎不受小类影响。打开包里的两个数据文件可以先用命令行感受一下规模gunzip -c kddcup.data_10_percent.gz | wc -l gunzip -c kddcup.data.gz | wc -l第一个文件大约49万行第二个大约490万行正好差十倍。10%子集是KDD99官方发布的精简训练集全量是最初的完整训练集。毕设场景下49万行已经完全够用全量文件更像是一个“作者留给你冲击更高指标”的备选项。另外我要提醒一句官方还有一个测试集文件corrected.gz但这份源码包里没有包里的train、test目录应该是作者自己从原始数据里切出来的。2.2 模型分工handle2.py做地基main.py和cnn_main.py各管一条线看文件列表就知道这是个典型的PyCharm工程.idea目录和ids-kdd99.iml就是证据。代码文件里我第一眼注意到的是handle2.py。这个脚本非常容易被忽视但整个项目的正确率地基其实是它打的KDD99里有三列是纯字符串——protocol_type、service、flag模型根本吃不了字符串必须映射成数字字符串转数字之后还要做归一化、把多类标签映射成二分类最后把处理结果存成模型能直接读的中间文件。这一步做得干净后面训练就顺这一步偷懒后面所有模型都跟着翻车。main.py和cnn_main.py还有个拼写手滑的mian_cnn.py是main的笔误别被我误导是两条训练主线的入口。毕设里最常见的做法是一条传统机器学习基线加一条深度学习主线main.py负责前者cnn_main.py负责后者。如果你打开main.py发现它也是个神经网络也别慌把它当成入口脚本把cnn_main.py当成对比实验就行。multi_logs目录则是TensorBoard的日志目录里面那个events.out.tfevents开头的文件是作者之前训练留下的实打实的记录。再补一个选型层面的理解为什么KDD99这种表格数据能用CNN常见做法是把41维特征reshape成(41, 1)的列向量用Conv1D做一维卷积。特征与特征之间没有像素一样的邻域关系所以一维卷积足够强行上2D卷积反而要费劲地重排特征网格效果通常不会更好。至于LSTM、Attention这类序列模型在这个场景下意义不大因为KDD99的窗口统计是数据集作者提前算好的连接记录本身不是严格的时间序列。作者选CNN是深度模型里性价比最高的那一条路。2.3 先跑10%子集还是全量时间成本差十倍训练时间这个账做毕设的人一定要算清楚。同样一个CNN模型49万行的10%子集跑一个epoch跟490万行的全量比耗时差接近十倍。很多人的毕设进度是被“全量训练一夜没出结果”拖垮的完全没必要。正确率的边际收益也是递减的对KDD99二分类任务来说10%子集跑出来的正确率跟全量差距通常不到一个百分点但时间成本差好几个小时。我一般会这样安排第一次跑通代码、验证环境、调模型结构全程只用10%子集等模型结构稳定了再决定要不要上全量刷新一次最终数字。这个思路也符合这份源码本身的意图——它两种数据都放进来就是在等你自己做这个取舍。数据侧还有一个KDD99特有的坑答辩时特别容易被问到官方测试集里含有训练集从未出现过的攻击类型大概十几类。也就是说你在训练集上把模型训得再好遇到那种“新攻击”表现大概率是漏报。这是数据集本身的设计不是模型缺陷。懂这个的人答辩讲到“检测能力边界”时会主动提它这反而是加分项。3. 从解压到跑通环境配置、文件职责和第一次10%子集训练3.1 读代码顺序README.md.bak、handle2.py再到CNN主脚本拿到这个包我建议你按这个顺序读代码先看README.md.bak再看handle2.py最后看main.py和cnn_main.py。README.md.bak是原README的备份作者改过之后留下的里面大概率有他当时跑通的环境信息和数据说明这是整个包里最便宜的“说明书”。文件职责先大概摸一遍我再列个表给你文件/目录职责kddcup.data.gz、kddcup.data_10_percent.gzKDD99原始训练数据handle2.py数据预处理字符映射、归一化、标签转换main.py入口脚本或传统机器学习基线cnn_main.py / mian_cnn.pyCNN训练主脚本multi_logsTensorBoard训练日志目录events.out.tfevents.*作者之前训练留下的事件文件README.md.bakREADME文档备份.idea、ids-kdd99.imlPyCharm工程配置注意目录里的train、test它们是作者自己切分的数据你复现时不要直接假设里面文件一定齐全先ls一下确认。用PyCharm打开项目后点的顺序就是上面表格的顺序README - handle2 - 模型脚本。这样你会在跑代码之前就对“谁处理数据、谁训练、谁出图”有完整认知而不是瞎点运行。3.2 环境准备TensorFlow 1.x兼容层和依赖清单这个项目的训练日志是TensorFlow 1.x时代留下的所以环境版本是第一个坎。我的建议是用conda单独建一个环境避免污染你现有的开发环境conda create -n ids python3.7 -y conda activate ids pip install numpy1.19.5 pandas1.2.4 scikit-learn0.24.2 matplotlib3.3.4 pip install tensorflow1.15.0解释一下为什么这么选Python 3.7对TensorFlow 1.15支持最稳scikit-learn 0.24.x的API和旧代码兼容性最好。如果你机器上已经装了TensorFlow 2.x也不想换环境可以在代码开头加一段兼容层让1.x的Session、placeholder这类老API重新可用import tensorflow.compat.v1 as tf tf.disable_v2_behavior()这段代码的意思是把TensorFlow 2.x切回1.x的图执行模式。但注意这只在部分脚本里有效如果代码里用了tf.keras以外的1.x API仍有报错风险。所以我的态度很明确别跟版本较劲老老实实装1.15这是最省时间的方案。依赖的用途也顺带说清楚numpy和pandas负责数据读写scikit-learn提供标签编码和评估指标tensorflow负责模型训练matplotlib画图。3.3 第一个可运行目标用10%子集把CNN训练拉起来环境配好之后先别急着直接跑训练脚本先用一段Python确认数据文件能正常读、能看清结构import pandas as pd cols [fcol_{i} for i in range(41)] [label] df pd.read_csv(kddcup.data_10_percent.gz, compressiongzip, headerNone, namescols) print(df.shape) print(df.dtypes.value_counts())这段代码读入10%子集先打印形状确认行数再打印每列的数据类型分布。你会在输出里看到protocol_type、service、flag三列是object类型这就是后面handle2.py要处理的对象。这一步的意义是让你建立“原始数据长什么样”的直观印象而不是直接面对训练脚本的报错。确认数据能读之后按顺序执行三个脚本python handle2.py python main.py python cnn_main.py如果代码里没有接收命令行参数的逻辑直接在脚本顶部找超参数常量修改。常见的是这样一段配置区# cnn_main.py 顶部常见的超参数配置区 EPOCHS 30 BATCH_SIZE 256 LEARNING_RATE 1e-3训练拉起来的标志是终端出现epoch进度条loss在下降accuracy逐步升到0.9以上multi_logs目录下出现新的events.out.tfevents文件。如果loss纹丝不动或者直接NaN优先去看第5章的避坑清单。第一次训练用10%子集、30个epoch单卡CPU大概十几分钟到半小时能跑完GPU会更快这个时间成本是完全可以接受的。4. 复现99.5%正确率数据切分、CNN参数和混淆矩阵验证4.1 训练/验证/测试三层切分stratify参数必须用KDD99原始训练集没有给你官方划分的验证集所以作者大概率是自己切的。复现时最重要的一个细节是切分必须保持类别分布不变。这就要用到stratify参数from sklearn.model_selection import train_test_split X_train, X_val, y_train, y_val train_test_split( X, y, test_size0.2, stratifyy, random_state42 )stratifyy的含义是按y的类别比例进行分层抽样。如果不加这个参数随机切分时DoS这类大类可能占了验证集的大半而u2r这种几十条的小类在一刀切下去后可能全被切进训练集验证集里一条都没有评估结果自然虚高。random_state固定随机种子保证每次运行结果一致这个习惯做毕设时一定要有。切分完之后还有一个动作把原始的字符串标签映射成二分类的0和1。正常记录是0任何攻击类型都是1。这一步在handle2.py里应该已经做了但你要能自己讲清楚df[binary_label] df[label].apply( lambda x: 0 if x normal. else 1 )注意KDD99标签末尾带点号实际是normal.而不是normal这是数据集格式的细节忘了去掉点号会导致所有标签都映射错直接带崩正确率。4.2 CNN关键参数先看loss降不降再谈准确率超参数不是玄学但要有顺序地调。我复现这类项目常用的初始参数表如下参数常见初始值调整方向EPOCHS30~60验证集loss不再降时提前停止BATCH_SIZE128~256内存或显存不够时调小LEARNING_RATE1e-3收敛慢就调小到1e-4但不建议更大DROPOUT0.5训练集正确率远高于验证集时加大Conv1D filters64效果不够时翻倍到128kernel_size3或5影响感受野一般3够用调参的第一步永远是看loss曲线不是看准确率。loss在降说明模型在学loss不降先调学习率训练集准确率高但验证集上不去加dropout两边都低才考虑加大模型容量。这个顺序比盲目堆层有效得多。还有一处容易被忽视KDD99的数值特征量纲差异很大duration从0到几万而flag类的枚举值是0到10。如果handle2.py里没有做标准化模型训练会非常不稳定loss像过山车。检查一下归一化用的是StandardScaler还是MinMaxScaler二者在这个场景下差别不大但必须做且要在切分之前fit。4.3 验证99.5%的完整视角准确率、分类报告和混淆矩阵复现出99.5%之后别急着截图存证。先用完整评估口径验证一次我一般会跑这段代码from sklearn.metrics import classification_report, confusion_matrix, accuracy_score y_pred model.predict(X_test) y_pred (y_pred 0.5).astype(int) print(accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred, target_names[normal, attack], digits4)) print(confusion_matrix(y_test, y_pred))分类报告会打出精确率、召回率、F1每一类一行的明细混淆矩阵能标出到底哪些攻击被漏报。在这个数据集上你会看到一个典型现象normal和DoS这两大类的precision和recall都非常高但u2r、r2l的recall可能低到零点几甚至全部漏报。这就是99.5%正确率的真相数据里98%以上的样本是容易被识别的大类几十条u2r即使全漏对正确率的影响也只有万分之几。所以“正确率可达99.5%”这个说法本身没问题但如果答辩只报一个准确率数字评委会认为你根本没看数据分布。正确姿势是准确率报出来分类报告和混淆矩阵也摆出来主动说明小样本攻击的漏报是KDD99已知难点然后在改进方向里提一句重采样或加权重这就把缺陷变成了研究深度。5. 避坑指南从预处理到训练评估的五个翻车点5.1 坑一字符串特征没编码直接进模型现象训练刚跑第一轮就报错错误信息类似could not convert string to float: http程序的指向是模型输入的数据里混进了字符串。原因protocol_type、service、flag三列是对象类型模型只能吃数值没做编码。解决在handle2.py里找到三列做标签编码from sklearn.preprocessing import LabelEncoder for col in [protocol_type, service, flag]: df[col] LabelEncoder().fit_transform(df[col])要注意的是严格做法应该在训练集上fit编码器再transform测试集防止测试集信息泄漏到训练过程。毕设代码里直接对整列fit_transform是省事写法能跑通但答辩被问到“数据泄漏”时你要能接住话。5.2 坑二TensorFlow 2.x跑1.x源码Session直接报错现象import tensorflow后执行tf.Session()或tf.placeholder时报AttributeError说当前模块里没有Session或placeholder。原因TensorFlow 2.0删掉了1.x的静态图API。事件文件的命名方式已经暴露这是1.x时代训练的源码。解决最省事的是装TensorFlow 1.15其次是在代码开头加tf.compat.v1兼容层和disable_v2_behavior()。我实测过兼容层对大多数1.x代码有效但如果你用的是tf.contrib里的函数它会直接消失没有兼容余地必须手动替换或删掉。5.3 坑三全量数据一次性读入内存先崩了现象运行脚本后进程被杀或者Windows直接弹内存不足光标卡死。原因490万行的全量数据再加上pandas读入和特征膨胀内存开销能上好几个GB。如果你还同时打开了PyCharm、浏览器和一堆应用内存直接顶不住。解决第一次训练坚决只用10%子集这是最省事的解法。如果你想跑全量用pd.read_csv的chunksize分块读取或者考虑特征选择剔除那些方差接近0的无信息列。全量数据带来的正确率提升通常不到0.5个百分点不值得为它把机器搞死。5.4 坑四归一化放在切分之前验证集信息泄漏现象验证集正确率异常高高到0.998但你换一批手工构造的数据测正确率立刻崩掉。原因StandardScaler在train_test_split之前对着全量数据fit均值和标准差里混进了验证集和测试集的信息。这相当于考试前看了答案。解决先切分再fit。正确的顺序是切分X_train/X_test然后在X_train上fit归一化器再transform X_train和X_test。sklearn的Pipeline可以把这串动作串起来减少人为失误。判断有没有泄漏的一个笨办法看验证集正确率是否比训练集高出一大截如果是多半是预处理顺序出了问题。5.5 坑五只报一个accuracy答辩追问时翻车现象答辩演示时只说了正确率99.5%评委追问“u2r和r2l这两类攻击检出率多少”的时候当场答不上来。原因没跑分类报告也没看过混淆矩阵对模型在少数类上的表现完全没概念。这在KDD99场景下基本等于送命题。解决提前把classification_report结果打印出来把每一类的precision、recall、F1记在心里。同时准备一张凑数的思路表对u2r、r2l这种小样本类常见补救方向是SMOTE过采样、损失函数加类别权重、或者用小样本类做专门二分类。答辩时主动讲这部分比被动等提问体面得多。6. 让项目站得住TensorBoard可视化、多分类扩展和答辩演示6.1 复现之外的加分动作可视化、多分类和答辩演示项目能跑通、指标能复现这只能保证及格。想拿高分或者让同行认可我建议你追加三个动作。第一个动作是把训练曲线拉出来看。multi_logs目录里已经有作者之前的TensorBoard事件文件你自己跑完也会生成新的。在项目根目录执行tensorboard --logdirmulti_logs浏览器打开后会看到loss和accuracy曲线。这里有个演示技巧不同实验把日志分别写到multi_logs下的不同子目录TensorBoard会用不同颜色同时展示可以直接对比调参前后的差异。答辩现场点开这条曲线比任何截图都有说服力。第二个动作是把二分类扩展成多分类。KDD99的标签粗分是四类攻击加正常不做二分类而是五分类准确率一般会掉到95%甚至更低但这恰恰是深度学习NetIDS研究里更被接受的做法。改动其实不大输出层从sigmoid改成softmaxloss从binary_crossentropy换成categorical_crossentropy评估指标从accuracy换成macro-F1。这个改动把项目的技术含量从“能用CNN分类”提升到“能处理不均衡多分类”边界感知立刻不一样。第三个动作是答辩演示的顺序安排。我建议你按四步走第一句说数据集——KDD99有41维特征、四组语义、存在小样本攻击第二句说预处理——字符串列如何编码、归一化、切分第三句说模型——为何选Conv1D处理表格特征第四句说验证——准确率之外重点讲混淆矩阵和u2r漏报问题。这个顺序把每个环节的技术决策都交代清楚了评委基本没有死角可问。最后说句掏心窝的话。我拆这个包时最大的教训就是第一次跑通后我只看了一眼accuracy觉得99.5%已经完美直到我打印出classification_report看到u2r那条recall是0.00才明白自己被单一指标骗了。从那以后我拿到任何带准确率声明的源码第一件事不是复现数字而是先把它的评估口径和混淆矩阵钉死再看那个数字还有没有意义。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站