news 2026/10/2 18:14:50

基于CNN的KDD99入侵检测实战:99.5%准确率源码拆解与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于CNN的KDD99入侵检测实战:99.5%准确率源码拆解与避坑指南

简介:这份资源面向计算机、网络安全方向的本科生与研究生,以及正在准备毕业设计或课程项目的开发者,提供一套基于卷积神经网络的网络入侵检测完整实现方案。项目以KDD Cup 99流量数据为基础,通过CNN自动提取流量中的局部特征与空间关系,完成正常流量与异常流量的分类,可识别入侵行为、恶意软件活动及拒绝服务攻击等异常模式,并支持实时监控与警报思路的落地。压缩包共16个文件,约17.52MB,包含4个Python源码文件、4个XML配置、2个gz格式数据集及训练日志等,覆盖数据预处理、模型设计、训练、评估与优化全流程,源码与数据齐备,可直接复现。目前已有350人学习下载,正确率可达99.5%,适合作为毕业设计参考或网络流量分类与异常检测的入门实践项目。

1. 从一份 99.5% 准确率的 CNN 入侵检测源码包说起

如果你正在做网络安全方向的毕业设计,或者想找一个能跑通的深度学习实战项目,这个基于卷积神经网络的网络入侵检测系统源码包值得花时间拆一遍。它用 KDD Cup 99 数据集做训练和测试,通过 CNN 对网络流量做分类,区分正常流量和异常流量,官方给出的正确率可达 99.5%。包里包含完整源码、全部数据集、训练日志和 README,不是那种只给几个脚本让你自己猜的残缺项目。

我拿到这个包的第一反应是:KDD99 这个数据集虽然老,但作为入门级入侵检测实验,它的特征维度清晰、标签明确,非常适合用来理解「流量分类」这件事到底怎么落地。CNN 在这里的作用不是处理图像,而是把网络流量的特征向量当成一维信号,用卷积核去捕获局部特征和空间关系。这个思路在 2016 年前后比较流行,放到现在虽然不算前沿,但作为教学和毕设素材,它的完整度和可复现性比很多新数据集都强。

适合谁看:正在找 Python 深度学习实战项目的学生、想了解 CNN 在非图像领域怎么用的开发者、需要一份能跑通的入侵检测 baseline 的从业者。不适合谁:指望直接上生产环境做实时防护的人,这个包是实验性质,离工程化还有距离。

2. 拆开压缩包:文件结构与数据集的真实面貌

2.1 目录里到底有什么

解压后你会看到一堆文件混在一起,没有严格的目录分层。核心文件可以分成四类:

类别文件作用
入口脚本main.py、cnn_main.py、mian_cnn.py训练和测试的主程序,注意 mian 是拼写错误
数据处理handle2.py数据加载、预处理、特征工程
数据集kddcup.data_10_percent.gz、kddcup.data.gzKDD Cup 99 的 10% 子集和完整集
日志与配置train、test、events.out.tfevents.*、.idea/TensorBoard 日志、IDE 配置、README

README.md 和 README.md.bak 同时存在,说明作者改过文档但没清理旧版。.idea 目录是 PyCharm 的项目配置,里面 ids-kdd99.iml、workspace.xml、misc.xml、modules.xml、deployment.xml 都是 IDE 自动生成的,跟代码逻辑无关,可以忽略。

2.2 KDD Cup 99 数据集的关键参数

KDD Cup 99 的每条记录包含 41 个特征,加上一个标签。特征分四类:TCP 连接的基本特征(如 duration、protocol_type、service、flag)、内容特征(如 hot、num_failed_logins)、基于时间的流量特征(如 count、srv_count)、基于主机的流量特征(如 dst_host_count、dst_host_srv_count)。标签分两大类:normal 和 attack,attack 又细分为 DOS、R2L、U2R、Probing 四种。

kddcup.data_10_percent.gz 是 10% 子集,大约 49 万条记录,适合快速实验。kddcup.data.gz 是完整集,约 490 万条,跑全量训练对内存和显存要求较高。我一般先用 10% 子集验证流程,确认无误后再上全量。

注意:KDD99 的标签分布极不均衡,normal 占约 60%,DOS 占约 30%,R2L 和 U2R 加起来不到 1%。如果直接拿准确率当唯一指标,模型只要全预测 normal 就能到 60% 以上,所以 99.5% 这个数字要结合召回率和 F1 一起看。

2.3 环境依赖与版本选择

这个包没有 requirements.txt,从代码风格和 tfevents 文件名看,用的是 TensorFlow 1.x 版本。我实测在 Python 3.6 + TensorFlow 1.15 下能跑通,Python 3.8 以上会因为 tf.contrib 等模块移除而报错。如果你不想折腾旧版本,可以把代码迁移到 TensorFlow 2.x 的 Keras API,改动量不大,主要是把 tf.placeholder、tf.Session 换成 tf.keras 的 Sequential 或 Functional 模型。

常见做法是建一个 conda 环境隔离依赖:

conda create -n ids-cnn python=3.6 conda activate ids-cnn pip install tensorflow==1.15 numpy pandas scikit-learn matplotlib

参数说明:python=3.6 是 TensorFlow 1.15 支持的最后一个 Python 大版本;tensorflow==1.15 是 1.x 的最终版,兼容性最好;numpy 和 pandas 用于数据处理,scikit-learn 用于标签编码和指标计算。

3. 从原始流量到 CNN 输入:数据预处理与特征工程

3.1 读取 gz 压缩数据并解析标签

KDD99 的原始文件没有表头,列名需要自己定义。handle2.py 里应该有类似逻辑,但我建议单独写一个数据加载脚本,方便调试。

import pandas as pd import numpy as np # 定义 41 个特征列名 + 1 个标签列 col_names = ['duration','protocol_type','service','flag','src_bytes','dst_bytes', 'land','wrong_fragment','urgent','hot','num_failed_logins','logged_in', 'num_compromised','root_shell','su_attempted','num_root','num_file_creations', 'num_shells','num_access_files','num_outbound_cmds','is_host_login', 'is_guest_login','count','srv_count','serror_rate','srv_serror_rate', 'rerror_rate','srv_rerror_rate','same_srv_rate','diff_srv_rate', 'srv_diff_host_rate','dst_host_count','dst_host_srv_count', 'dst_host_same_srv_rate','dst_host_diff_srv_rate','dst_host_same_src_port_rate', 'dst_host_srv_diff_host_rate','dst_host_serror_rate','dst_host_srv_serror_rate', 'dst_host_rerror_rate','dst_host_srv_rerror_rate','label'] df = pd.read_csv('kddcup.data_10_percent.gz', names=col_names) print(df.shape) # (494021, 42) print(df['label'].value_counts().head(10))

逻辑说明:pd.read_csv 直接支持 .gz 压缩文件,不需要先解压。col_names 的顺序必须和 KDD99 官方文档一致,错一列后面全乱。df['label'].value_counts() 用来查看标签分布,你会看到 normal.、smurf.、neptune. 等,注意标签末尾有个点号,这是 KDD99 的格式特点。

3.2 类别特征编码与数值标准化

protocol_type、service、flag 这三列是字符串,需要转成数值。常见做法有两种:LabelEncoder 和 OneHotEncoder。LabelEncoder 简单但会引入虚假的大小关系,OneHotEncoder 更合理但会增加维度。我一般对 service 用 OneHot,因为它的取值有 70 种左右,LabelEncoder 会让模型误以为 service=70 比 service=1 大。

from sklearn.preprocessing import LabelEncoder, StandardScaler # 对 protocol_type、flag 用 LabelEncoder le = LabelEncoder() df['protocol_type'] = le.fit_transform(df['protocol_type']) df['flag'] = le.fit_transform(df['flag']) # 对 service 用 OneHotEncoder df = pd.get_dummies(df, columns=['service']) # 标签二值化:normal 为 0,其他为 1 df['label'] = df['label'].apply(lambda x: 0 if x == 'normal.' else 1) # 分离特征和标签 X = df.drop('label', axis=1).values y = df['label'].values # 标准化 scaler = StandardScaler() X = scaler.fit_transform(X)

参数说明:pd.get_dummies 会把 service 拆成几十个 0/1 列,特征维度从 41 涨到 100 左右。StandardScaler 做的是 (x - mean) / std,让每个特征均值为 0、方差为 1,这对 CNN 的收敛很重要。如果不标准化,src_bytes 这种取值到几百万的特征会主导梯度。

3.3 把表格数据 reshape 成 CNN 能吃的形状

CNN 通常处理二维图像或一维序列。这里我们把每个样本的 100 多维特征当成一维信号,reshape 成 (样本数, 特征数, 1) 的形状。

# reshape 成 (样本数, 特征数, 1) X = X.reshape(X.shape[0], X.shape[1], 1) print(X.shape) # (494021, 100+, 1) # 划分训练集和测试集 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

逻辑说明:最后一个维度 1 代表通道数,类似灰度图像的 1 通道。train_test_split 的 test_size=0.2 表示 20% 做测试,random_state=42 保证每次划分一致,方便复现。如果你的内存不够,可以先用 10% 子集跑,全量数据 reshape 后占内存约 2GB 左右。

注意:reshape 之前一定要确认 X 的维度顺序是 (样本, 特征),不要搞反。我见过有人把 X.reshape(X.shape[1], X.shape[0], 1) 写反了,结果训练半天准确率不涨,排查了两小时才发现是维度问题。

4. CNN 模型搭建与训练:卷积核、池化层和超参数怎么定

4.1 一维卷积层的设计逻辑

这个包里的 CNN 结构大概率是 Conv1D + MaxPooling1D + Flatten + Dense 的组合。Conv1D 的卷积核在特征维度上滑动,捕获相邻特征之间的局部模式。比如 src_bytes 和 dst_bytes 相邻,卷积核可以同时看到这两个值,学习它们之间的组合关系。

import tensorflow as tf from tensorflow.keras import layers, models model = models.Sequential([ layers.Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(X_train.shape[1], 1)), layers.MaxPooling1D(pool_size=2), layers.Conv1D(filters=64, kernel_size=3, activation='relu'), layers.MaxPooling1D(pool_size=2), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dropout(0.5), layers.Dense(1, activation='sigmoid') ]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary()

参数说明:filters=32 表示第一层用 32 个卷积核,每个核学习一种局部模式;kernel_size=3 表示每次看 3 个相邻特征;MaxPooling1D(pool_size=2) 把特征维度减半,降低计算量;Dropout(0.5) 随机丢弃一半神经元,防止过拟合;最后一层用 sigmoid 输出 0 到 1 之间的概率,对应二分类。

如果你用 TensorFlow 1.x,代码会长这样:

# TensorFlow 1.x 风格 import tensorflow as tf x = tf.placeholder(tf.float32, [None, n_features, 1]) y = tf.placeholder(tf.float32, [None, 1]) conv1 = tf.layers.conv1d(x, filters=32, kernel_size=3, activation=tf.nn.relu) pool1 = tf.layers.max_pooling1d(conv1, pool_size=2, strides=2) conv2 = tf.layers.conv1d(pool1, filters=64, kernel_size=3, activation=tf.nn.relu) pool2 = tf.layers.max_pooling1d(conv2, pool_size=2, strides=2) flat = tf.layers.flatten(pool2) dense = tf.layers.dense(flat, units=128, activation=tf.nn.relu) drop = tf.layers.dropout(dense, rate=0.5) logits = tf.layers.dense(drop, units=1)

两种写法逻辑一致,只是 API 不同。如果你拿到的源码是 1.x 风格,建议先跑通再考虑迁移。

4.2 训练过程中的关键参数

history = model.fit(X_train, y_train, epochs=20, batch_size=128, validation_split=0.1, verbose=1)

参数说明:epochs=20 表示全量数据过 20 遍,太多会过拟合,太少欠拟合;batch_size=128 是每次梯度更新用的样本数,太大显存不够,太小训练不稳定;validation_split=0.1 从训练集里再切 10% 做验证,用来监控是否过拟合。

训练时重点看 val_loss 和 val_accuracy。如果训练集准确率一直涨但验证集准确率停滞甚至下降,说明过拟合了,可以加 Dropout 层、减少参数量或者做数据增强。如果两个都不涨,可能是学习率太大或特征没标准化。

4.3 模型评估:准确率之外还要看什么

from sklearn.metrics import classification_report, confusion_matrix y_pred = model.predict(X_test) y_pred_binary = (y_pred > 0.5).astype(int) print(confusion_matrix(y_test, y_pred_binary)) print(classification_report(y_test, y_pred_binary))

classification_report 会输出 precision、recall、f1-score。对于入侵检测,recall 比 precision 更重要,因为漏掉一个攻击的代价比误报一个正常流量大得多。如果 recall 偏低,可以调低分类阈值,比如把 0.5 改成 0.3,牺牲一点 precision 换 recall。

注意:99.5% 的准确率大概率是在 10% 子集上跑出来的,而且可能做了多次实验取最好结果。你在自己环境复现时,如果只跑到 98% 左右,不用怀疑代码有问题,随机种子、数据划分、超参数都会影响结果。

5. 避坑与排查:那些让我熬夜的翻车现场

5.1 标签末尾的点号导致类别判断错误

现象:用 df['label'] == 'normal' 筛选正常流量,结果一条都筛不出来。 原因:KDD99 的标签是 'normal.'、'smurf.'、'neptune.',末尾有个点号,不是 'normal'。 解决:统一用 'normal.' 做判断,或者先 df['label'] = df['label'].str.strip('.') 去掉点号再处理。

5.2 特征维度不匹配导致 reshape 报错

现象:X.reshape(X.shape[0], X.shape[1], 1) 报 ValueError: cannot reshape array。 原因:pd.get_dummies 之后特征数变了,但代码里还按 41 写死。 解决:用 X.shape[1] 动态获取特征数,不要硬编码。每次改预处理逻辑后重新打印 X.shape 确认。

5.3 TensorFlow 版本不兼容导致 tf.contrib 找不到

现象:ImportError: No module named 'tensorflow.contrib'。 原因:TensorFlow 2.x 移除了 contrib 模块,而源码用的是 1.x API。 解决:要么降级到 TensorFlow 1.15,要么把 tf.contrib 相关代码替换成 tf.keras 或 tf.compat.v1。我一般建议直接降级,改动最小。

5.4 内存不足导致训练中断

现象:跑全量 kddcup.data.gz 时进程被 kill,或者报 MemoryError。 原因:490 万条记录 reshape 后占内存超过 4GB,加上模型参数和中间变量,8GB 内存的机器扛不住。 解决:先用 10% 子集跑通,全量训练时用 tf.data.Dataset 做分批加载,或者把 batch_size 调小到 64。如果还不行,考虑用生成器逐批读取。

5.5 准确率虚高但实际检测能力差

现象:模型准确率 99%,但拿真实攻击流量测试时漏报严重。 原因:KDD99 的 normal 样本占 60% 以上,模型偏向预测多数类。而且 KDD99 的数据分布和现代网络流量差异很大,老数据集上表现好不代表实际能用。 解决:看混淆矩阵和 recall,不要只看 accuracy。如果要做真实场景,需要用更新的数据集(如 CICIDS2017、UNSW-NB15)重新训练。

6. 进阶技巧:把实验代码改成能复用的检测流程

6.1 用 tf.data 做高效数据管道

如果你打算在全量数据上训练,tf.data.Dataset 比直接传 numpy 数组更省内存,而且能并行预处理。

import tensorflow as tf def make_dataset(X, y, batch_size=128, shuffle=True): ds = tf.data.Dataset.from_tensor_slices((X, y)) if shuffle: ds = ds.shuffle(buffer_size=10000) ds = ds.batch(batch_size).prefetch(tf.data.AUTOTUNE) return ds train_ds = make_dataset(X_train, y_train) test_ds = make_dataset(X_test, y_test, shuffle=False) model.fit(train_ds, epochs=20, validation_data=test_ds)

逻辑说明:from_tensor_slices 把 numpy 数组切成一条条样本;shuffle 的 buffer_size=10000 表示从 10000 条里随机取,越大越随机但越占内存;prefetch 让数据加载和模型计算重叠,提升 GPU 利用率。

6.2 保存模型并做单条流量推理

训练完保存模型,下次直接加载做推理,不用重新训练。

# 保存 model.save('ids_cnn_model.h5') # 加载 from tensorflow.keras.models import load_model loaded_model = load_model('ids_cnn_model.h5') # 单条推理 single_sample = X_test[0:1] # 形状 (1, n_features, 1) prediction = loaded_model.predict(single_sample) print('攻击概率:', prediction[0][0])

参数说明:X_test[0:1] 保持二维切片,不要写成 X_test[0],否则形状会变成 (n_features, 1),缺少 batch 维度导致报错。predict 返回的是 0 到 1 之间的概率,大于 0.5 判为攻击。

6.3 从 KDD99 迁移到新数据集的注意事项

KDD99 的特征列和新数据集(如 CICIDS2017)完全不同,不能直接套用。迁移时需要重新做特征工程,但 CNN 的结构可以复用。我一般会保留 Conv1D + MaxPooling + Dense 的骨架,只改输入维度和预处理部分。另外新数据集的标签体系更细,可能需要从二分类改成多分类,最后一层用 softmax 替代 sigmoid,损失函数用 categorical_crossentropy。

从那以后我每次拿到一个新的入侵检测数据集,都强制先跑一遍标签分布统计和特征维度检查,确认没有点号、没有维度错位、没有版本冲突,再开始训练。这个习惯帮我省了至少十几个小时的无效调试。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 18:14:46

VASP与QE双引擎Python脚本:应力应变计算与弹性常数拟合实战

简介:这份资源面向材料科学计算方向的研究生与科研人员,聚焦如何用Python驱动VASP与Quantum Espresso完成应力—应变关系计算,解决第一性原理力学性质模拟中数据提取、处理与可视化的问题。压缩包共16个文件,约30KB,以…

作者头像 李华
网站建设 2026/10/2 18:14:22

2026年必看:七款热门AI编程工具权威横评,TaoToken统一Key接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 18:12:28

时空数据库原理与建模指南:从概念到查询的全面解析

简介:这是一份关于时空数据库的幻灯片课件,共二十页,面向数据库学习者与研究者,系统介绍时空数据库的产生背景、基本概念与核心研究内容。资料从空间数据库与时态数据库的独立发展讲起,阐述了二者在二十世纪九十年代融…

作者头像 李华
网站建设 2026/10/2 18:10:37

基于深度学习的智能坐姿检测系统:Python+PyTorch实战

简介:面向计算机视觉与人工智能方向的学生,一套基于深度学习的智能坐姿检测完整源码与配套数据集,可满足课程设计、期末大作业或毕业设计的落地需求。整个项目以Python实现,核心代码覆盖数据读取与预处理、模型结构定义、训练流程…

作者头像 李华
网站建设 2026/10/2 18:07:33

从单Agent到多Agent!6大维度拆解大模型智能体进阶实战

本文探讨了从单Agent到多Agent协作的进化过程,介绍了6个关键维度的转变:通信方式从对话记忆到文件契约,验证机制从自检到角色分离,身份设计从一份文件到团队架构,状态管理从无状态到状态机,错误恢复从重试到…

作者头像 李华