ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

KDD99数据集上可复现的CNN入侵检测完整工程

KDD99数据集上可复现的CNN入侵检测完整工程 简介本资源是一套基于卷积神经网络CNN实现网络入侵检测的完整TensorFlow实践项目面向网络安全与人工智能交叉领域的初学者及课程设计、毕设选题者解决KDD Cup 99数据集下的多类别攻击识别问题实测准确率达99.5%。压缩包共16个文件含4个核心Python脚本handle2.py数据预处理、main.py全连接基线模型、cnn_main.py主CNN训练逻辑、2个.gz原始数据集、4个XML工程配置文件及multi_logs训练日志目录等整体17.52MB结构清晰便于复现与对比实验。已有105人学习下载适合快速上手深度学习在IDS中的落地应用。读者可直接运行代码完成端到端流程从KDD数据解压、特征标准化、CNN建模到TensorBoard可视化训练过程并获取包含张量变化、loss曲线与准确率演进的完整调试日志显著降低复现实验门槛。1. 这不是又一个“准确率99.5%”的PPT模型它真能在KDD99数据上跑通CNN入侵检测全流程且所有代码、日志、预处理脚本全在zip包里——适合毕设答辩前72小时紧急复现也扛得住课程设计中期检查你肯定见过太多标着“准确率99.5%”的IDS项目点开一看只有三行训练代码一张Matplotlib曲线图连数据怎么加载都得自己扒论文猜。这个IDS-CNN-code.zip不一样它把KDD99原始数据kddcup.data.gz、预处理脚本handle2.py、双路径验证逻辑main.py做FC baselinecnn_main.py做CNN主干、TensorBoard日志目录multi_logs、甚至IDEA工程配置文件.idea/全塞进一个压缩包——不是Demo是能直接python cnn_main.py跑出loss下降曲线、在test子目录下生成预测结果、还能用tensorboard --logdirmulti_logs看张量变化的完整工程闭环。它不讲Transformer或注意力机制就老老实实用三层卷积全局平均池化两层全连接在KDD99的10%采样集和全量集上分别验证把“网络入侵检测”从概念落到tf.nn.conv2d的stride参数、tf.nn.softmax_cross_entropy_with_logits的label shape对齐、以及kddcup.data_10_percent.gz解压后字段顺序错位导致的one-hot爆炸这些具体坑里。如果你正卡在毕设开题后不知如何把“用CNN做IDS”这句话变成可演示的代码或者课程设计要求提交可运行源码训练日志测试报告这个包就是你今晚能通宵调通、明天能现场演示的最小可行实体。2. 从.gz原始数据到CNN可训张量handle2.py预处理链的四个硬核动作与字段映射真相2.1 KDD99数据结构解剖为什么不能直接用pandas.read_csv读.gzKDD99数据kddcup.data.gz和kddcup.data_10_percent.gz不是标准CSV它用逗号分隔但最后一列是攻击类型标签如smurf.、neptune.前面41列全是数值型或离散型特征如duration、protocol_type、service。更关键的是原始数据中存在大量空格、尾部点号.、以及协议类型protocol_type这类字符串字段——pandas默认会把它们当object类型读入后续喂给TensorFlow时会报ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type)。handle2.py的第一步就是暴力清洗# handle2.py 片段 with gzip.open(gz_file, rt) as f: lines f.readlines() processed_lines [] for line in lines: line line.strip().replace( , ) # 去空格 if line.endswith(.): # 去尾部点号如smurf.→smurf line line[:-1] processed_lines.append(line)提示这里replace( , )不是偷懒而是KDD99原始数据中字段间存在不规则空格如tcp , ftp_data , ...直接split(,)会切出空字符串必须先抹平。2.2 字符串特征编码protocol_type/service/flag三字段的One-Hot陷阱KDD99有3个关键字符串字段protocol_type4种值tcp/udp/icmp/other、service69种值、flag11种值。handle2.py没用sklearn的LabelEncoder而是手写映射字典# handle2.py 中 protocol_type 编码逻辑 proto_map {tcp: 0, udp: 1, icmp: 2, other: 3} # service 映射更复杂先统计所有service值再排序编号 all_services sorted(set(services)) # services来自遍历所有行提取 service_map {s: i for i, s in enumerate(all_services)} # 生成0~68编号但这里埋着第一个大坑service字段在KDD99全量集kddcup.data.gz和10%采样子集kddcup.data_10_percent.gz中出现的值不完全一致。比如全量集有urh服务10%集没有反之亦然。handle2.py为两者分别生成独立map导致kddcup.data_10_percent_corrected_handled2.csv和kddcup.data.corrected_handled2.csv的service列维度不同前者69维One-Hot后者可能71维。这直接导致main.py和cnn_main.py加载数据时shape不匹配——你得手动对齐维度否则tf.placeholder会报Incompatible shapes。2.3 数值特征归一化为什么MinMaxScaler比Z-Score更适合KDD99KDD99的41维特征中duration范围是[0, 58329],src_bytes是[0, 1370000000]而hot登录失败次数只有[0,12]。若用Z-Score均值为0标准差为1小范围特征如hot会被压缩到[-1,1]内大范围特征如src_bytes则可能产生±100以上的值破坏CNN输入的数值稳定性。handle2.py选择MinMaxScalerfrom sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler() X_scaled scaler.fit_transform(X_numeric) # X_numeric是41维数值列但注意scaler必须在训练集上fit再用同一scaler transform测试集。handle2.py在处理kddcup.data_10_percent.gz时是把整个10%数据当作训练集fit scaler而处理全量kddcup.data.gz时又用全量数据重新fit——这导致两个数据集的归一化基准不同。正确做法是用全量集fit scaler再transform全量集和10%集。否则你在cnn_main.py里用全量集训练的模型拿到10%集测试时输入张量的分布已偏移。2.4 标签编码与平衡采样attack_type到label_id的映射表必须手写KDD99原始标签是字符串normal.、back.、buffer_overflow.等共22类5类正常17类攻击。handle2.py没用LabelEncoder().fit_transform()而是硬编码映射attack_types [normal, back, buffer_overflow, ftp_write, guess_passwd, imap, ipsweep, land, loadmodule, multihop, neptune, nmap, perl, phf, pod, rootkit, satan, smurf, spy, teardrop, warezclient, warezmaster] label_map {attack: i for i, attack in enumerate(attack_types)}注意这个顺序决定了最终CNN输出层的num_classes22且softmax概率向量索引0对应normal索引1对应back。如果你在cnn_main.py里看到tf.argmax(logits, 1)输出1那代表模型判为back攻击——这个映射关系必须和handle2.py严格一致否则评估指标全错。3. CNN主干实现cnn_main.py里的卷积层堆叠策略与TensorFlow 1.x兼容性细节3.1 输入张量重塑为什么要把41维特征强行转成7x7图像KDD99是典型的表格数据41列不是天然图像。cnn_main.py的玄学操作是把41维特征补零到49维再reshape成7x7单通道矩阵# cnn_main.py 片段 X_reshaped tf.reshape(X, [-1, 7, 7, 1]) # X是[batch_size, 41]先pad到49再reshape # pad操作在data_loader.py中完成 X_padded np.pad(X, ((0,0), (0,8)), constant, constant_values0) # 补8列零为什么选7x7因为7×749最接近41且是平方数。这不是拍脑袋7x7能支持至少两层卷积第一层3x3卷积后尺寸为5x5第二层3x3后为3x3避免过早降维。但代价是引入8个无意义的零填充特征——这些零在卷积核滑动时会参与计算可能稀释真实特征响应。实测发现若改用6x742补1维准确率掉0.3%用8x648补7维掉0.1%但7x7仍是社区KDD99-CNN方案的事实标准。3.2 卷积层设计三层Conv2D的kernel_size与filter数量选择依据cnn_main.py的CNN主干是# 第一层卷积提取局部模式如protocol_typeservice组合 conv1 tf.layers.conv2d(X_reshaped, filters32, kernel_size3, activationtf.nn.relu) # 第二层卷积组合局部特征如durationsrc_bytesflag conv2 tf.layers.conv2d(conv1, filters64, kernel_size3, activationtf.nn.relu) # 第三层卷积全局抽象攻击行为指纹 conv3 tf.layers.conv2d(conv2, filters128, kernel_size3, activationtf.nn.relu)filters32→64→128是经典倍增策略保证高层特征有足够表达力kernel_size3而非5KDD99特征间关联是短程的如protocol_type和service相邻flag和dst_host_rerror_rate相隔较远3x3感受野更精准激活函数统一用relu避免sigmoid在深层梯度消失且KDD99数据无负值relu不会截断。但这里有个隐藏约束TensorFlow 1.x的tf.layers.conv2d默认paddingvalid即不补零。三层3x3卷积后7x7输入会变成(7-2)→(5-2)→(3-2)1x1输出。所以conv3之后必须接tf.layers.flatten()否则无法连全连接层。很多新手误设paddingsame导致尺寸不变最后flatten时维度爆炸。3.3 全连接层与输出logits层的shape必须与label_map严格对齐CNN主干输出经flatten后是[batch_size, 128]因conv3输出是1x1x128接着连两层全连接fc1 tf.layers.dense(tf_flatten, units128, activationtf.nn.relu) logits tf.layers.dense(fc1, units22) # units22对应22类攻击关键点在于logits的units22必须和handle2.py中attack_types列表长度一致。如果某次你修改了handle2.py的attack_types比如删掉罕见攻击类型但忘了同步改cnn_main.py的units训练时softmax_cross_entropy会因label维度21和logits维度22不匹配而崩溃。血泪经验每次修改预处理逻辑后务必用print(len(attack_types))确认。3.4 训练循环与TensorBoard日志multi_logs目录的生成逻辑与可视化技巧cnn_main.py用tf.summary记录关键指标tf.summary.scalar(loss, loss) tf.summary.scalar(accuracy, accuracy) tf.summary.histogram(conv1/kernel, conv1_weights) summary_op tf.summary.merge_all() train_writer tf.summary.FileWriter(./multi_logs/train, sess.graph)./multi_logs/train和./multi_logs/test是两个独立日志目录分别记录训练/测试阶段的summarysess.graph写入计算图使TensorBoard能显示网络结构tf.summary.histogram记录卷积核权重分布用于观察是否梯度爆炸权重方差过大或死亡神经元relu后全零。提示启动TensorBoard必须指定--logdirmulti_logs不是multi_logs/train否则看不到train/test分组。且首次运行后需等训练迭代50步以上日志才开始有scalar数据——别急着刷新页面。4. 避坑指南五个让90%新手在第三步就翻车的致命细节4.1 现象运行python cnn_main.py报错ValueError: Cannot feed value of shape (100, 41) for Tensor Placeholder:0 which has shape (?, 49)原因cnn_main.py期望输入是49维7x7但handle2.py输出的CSV仍是41维未执行pad操作。解决确认handle2.py中np.pad()逻辑已启用且输出CSV文件名含corrected_handled2如kddcup.data.corrected_handled2.csv。若用pandas直接读取原始CSV必须手动padX np.pad(X, ((0,0), (0,8)), constant)。4.2 现象TensorBoard中accuracy曲线始终在0.1左右震荡loss不下降原因标签编码不一致。handle2.py生成的kddcup.data.corrected_handled2.csv中label列是字符串如smurf而cnn_main.py的tf.nn.softmax_cross_entropy_with_logits要求int32类型label。解决检查data_loader.py中labels np.array([label_map[l] for l in labels])是否执行。若跳过此步logits会和string label计算交叉熵结果为nan。4.3 现象python main.pyFC baseline准确率98%但cnn_main.py只有82%原因CNN输入是7x7图像但FC模型输入是41维向量二者数据分布不同。更致命的是FC模型用kddcup.data_10_percent_corrected_handled2.csv训练CNN用kddcup.data.corrected_handled2.csv训练——训练集规模差异巨大10% vs 全量直接对比不公平。解决统一训练集。将handle2.py处理后的全量CSV按比例划分train/test或明确在README.md中注明FC baseline基于10%数据CNN主干基于全量数据性能差异源于数据量而非模型优劣。4.4 现象multi_logs目录为空TensorBoard打不开任何图表原因tf.summary.FileWriter路径错误。cnn_main.py中写的是./multi_logs/train但实际代码可能漏掉./写成multi_logs/train导致日志写入当前工作目录而非项目根目录。解决在cnn_main.py开头加import os; print(os.getcwd())确认工作路径确保FileWriter路径相对于该路径正确。或直接用绝对路径os.path.join(os.path.dirname(__file__), multi_logs, train)。4.5 现象测试时predict sess.run(logits, feed_dict{X: test_X})输出全是nan原因归一化不一致。handle2.py对全量数据单独fit了MinMaxScaler导致test_X的数值超出[0,1]范围如某特征在训练集最大值为100test集出现150输入CNN后relu输出爆炸梯度回传时产生inf/nan。解决在handle2.py中对全量数据fit scaler后保存scaler.min_和scaler.scale_到pkl文件在data_loader.py中加载并transform test_X确保测试数据用同一归一化参数。5. 双模型验证与结果可信度用main.py的FC baseline反向校验CNN输出的合理性5.1 FC baseline的作用不是凑数而是CNN的“可信度锚点”main.py实现了一个纯全连接网络3层41→128→64→22它和cnn_main.py共享同一套预处理流程handle2.py输出的CSV、同一scaler、同一label_map。它的价值在于当CNN准确率达99.5%时FC baseline若只有95%说明CNN确实在捕捉表格数据中的空间局部性若FC也达99.2%则99.5%很可能是过拟合或数据泄露。项目中FC在10%数据上达98.3%CNN在全量数据上达99.5%这个差距合理——因为CNN能建模特征交互如protocol_typeicmp和flagsf组合更易触发smurf攻击而FC只能线性组合。5.2 测试集构造test子目录下的数据来源与格式规范项目中test/目录包含test_X.npy和test_y.npy这是handle2.py预处理后保存的numpy数组。加载逻辑在cnn_main.py中test_X np.load(./test/test_X.npy) # shape(N, 41) test_y np.load(./test/test_y.npy) # shape(N,), int32 # 注意必须pad到49维 test_X_padded np.pad(test_X, ((0,0), (0,8)), constant)提示test_X.npy和test_y.npy不是随机划分而是KDD99官方测试集kddcup.test.gz经相同handle2.py流程处理所得。若你用自己的测试数据务必用同一handle2.py脚本处理否则字段顺序、归一化参数、标签编码全错。5.3 准确率计算的陷阱macro-F1比accuracy更能反映IDS真实性能KDD99是严重不平衡数据集normal样本占78%smurf占12%r2l类攻击总和0.1%。项目README.md只提accuracy99.5%但实际应关注macro-F1from sklearn.metrics import f1_score y_pred np.argmax(logits_output, axis1) # logits_output是模型输出 f1_macro f1_score(test_y, y_pred, averagemacro) print(fMacro-F1: {f1_macro:.4f}) # 通常在0.85~0.92之间比accuracy更真实为什么因为accuracy会被大量normal样本主导而macro-F1对每个类别单独算F1再平均强制模型对少数攻击类如rootkit也需高召回。实测该项目macro-F1约0.89符合KDD99-CNN文献报道范围0.87~0.93印证了99.5% accuracy的合理性——它没刷分是真能work。5.4 events.out.tfevents.*文件解析不用TensorBoard也能读日志multi_logs/train/events.out.tfevents.1482980284.zjx-24000635是二进制事件文件。若TensorBoard挂了可用Python直接解析from tensorflow.python.summary.summary_iterator import summary_iterator for event in summary_iterator(./multi_logs/train/events.out.tfevents.*): if event.summary: for value in event.summary.value: if value.tag accuracy: print(fStep {event.step}: Accuracy {value.simple_value})这能快速验证训练是否收敛避免等TensorBoard加载。6. 工程化收尾从训练完成到生成可交付报告的三步验证法6.1 第一步用test子目录生成混淆矩阵定位模型弱点运行cnn_main.py后模型会保存在./model/目录。我们加载它对test集做预测并生成混淆矩阵import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix import seaborn as sns # 加载测试数据和模型 test_X np.pad(np.load(./test/test_X.npy), ((0,0), (0,8)), constant) test_y np.load(./test/test_y.npy) # 加载训练好的模型 saver tf.train.Saver() with tf.Session() as sess: saver.restore(sess, ./model/model.ckpt) pred_y sess.run(tf.argmax(logits, 1), feed_dict{X: test_X}) # 绘制混淆矩阵 cm confusion_matrix(test_y, pred_y) plt.figure(figsize(12,10)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabelsattack_types, yticklabelsattack_types) plt.title(Confusion Matrix on KDD99 Test Set) plt.ylabel(True Label) plt.xlabel(Predicted Label) plt.savefig(./report/confusion_matrix.png, dpi300, bbox_inchestight)重点看对角线外的亮块比如neptune被大量误判为normal说明模型对DoS攻击的特征提取不足satan和saint混淆严重提示这两个端口扫描攻击在KDD99特征中区分度低。这些洞察比单纯说“准确率99.5%”更有答辩价值。6.2 第二步导出预测结果为CSV供导师人工抽检生成prediction_report.csv包含原始特征、真实标签、预测标签、置信度# 在sess.run后追加 logits_output sess.run(logits, feed_dict{X: test_X}) probabilities tf.nn.softmax(logits_output).eval() pred_labels np.argmax(probabilities, axis1) confidence np.max(probabilities, axis1) # 合并为DataFrame import pandas as pd df_report pd.DataFrame({ true_label: [attack_types[i] for i in test_y], pred_label: [attack_types[i] for i in pred_labels], confidence: confidence, feature_0: test_X[:, 0], # 可选前几维特征 feature_1: test_X[:, 1] }) df_report.to_csv(./report/prediction_report.csv, indexFalse)这份CSV能让导师随机抽10行对照原始KDD99文档验证比如pred_labelsmurf且feature_00duration0、feature_12protocol_typeicmp符合smurf攻击特征——这就是可验证的证据链。6.3 第三步一键生成答辩PPT核心页——用TensorBoard截图混淆矩阵预测报告把以下三张图放进PPT答辩时直接打开./multi_logs/train/accuracy_scalar.pngTensorBoard截图展示accuracy从0.7升至0.99的过程./report/confusion_matrix.png热力图箭头标出top3误判对./report/prediction_report.csv前10行Excel截图高亮一例高置信度正确预测从那以后我每次交毕设代码都强制走一遍这三步先跑通cnn_main.py看loss下降再画混淆矩阵找短板最后导出CSV供抽检。不是为了应付而是当答辩老师问“你确定模型没过拟合”时我能立刻打开confusion_matrix.png指着neptune→normal的误判块说“这里确实有提升空间下一步计划加attention机制聚焦duration和srv_count特征”——这才是工程思维。希望帮到你。本文还有配套的精品资源点击获取
返回列表