news 2026/10/10 11:18:50

KDD Cup入侵检测三模型实战:贝叶斯+BP神经网络+KNN

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KDD Cup入侵检测三模型实战:贝叶斯+BP神经网络+KNN

简介:本资源是一套基于Python实现的入侵检测系统实战项目,面向网络安全初学者、机器学习入门者及高校相关课程实践者,聚焦于贝叶斯分类器、神经网络(BP)与K近邻(KNN)三大算法在IDS中的建模、训练与对比评估。项目采用KDD Cup 99抽样数据集(约8万条记录),完整覆盖数据预处理、模型构建、训练保存(含pkl/pth模型文件)、可视化评估(含ROC曲线、混淆矩阵、P-R图等23张png图表)及HTML性能报告生成全流程。压缩包共52个文件,含6个核心py脚本(如classify_knn.py、BP.py、bayes.py)、4个训练模型文件、9个交互式HTML分析页、23张结果可视化图及README说明文档,整体体积仅3.39MB,结构清晰、即下即用。目前已有272人学习下载,读者可直接复现三种算法的完整实验链路,获取可运行代码、多维度评估结果与模型调参参考,快速掌握入侵检测任务中传统统计方法与深度学习方法的实践差异与融合思路。

1. 入侵检测不是“跑通就行”:这份含贝叶斯、BP神经网络、KNN三模型的Python实战包,专治KDD Cup数据集上“准确率虚高、泛化崩塌”的玄学翻车

你是不是也试过:在KDD Cup 99数据集上用sklearn跑个KNN,训练集99.2%准确率,一到测试集掉到73%?或者用朴素贝叶斯训完,混淆矩阵里“normal”和“neptune”堆成一片,根本分不清是攻击还是误报?这不是你代码写错了——是原始KDD数据没清洗、特征没缩放、类别严重失衡,更关键的是:单模型硬刚8万条高维离散+连续混合特征,注定踩坑。这个编号100011338的资源包,不是教你怎么调n_neighbors=5,而是直接给你三套可复现、带完整训练日志、含5个预存模型(.pkl/.pth)、12张可视化结果图(含ROC/P-R曲线/混淆矩阵)的落地方案。它用真实抽样后的kddcup.data_10_percent_corrected_save_8w.csv(约79,999条),严格按20%测试集划分,把贝叶斯、前馈神经网络(BP)、KNN三个算法拉到同一数据、同一评估标准下硬碰硬对比。适合正在做课程设计、毕设开题、或需要快速验证IDS模型baseline的工程师——别再从零搭环境、手写数据加载、反复调试class_weight参数了,这里连dataset.py里怎么处理KDD的41维原始特征(protocol_type、service、flag等离散字段one-hot编码,duration、src_bytes等连续字段标准化)都封装好了。


2. 三模型不是并列选择:为什么贝叶斯打头阵、BP扛主力、KNN当校验器?选型逻辑与数据适配真相

2.1 贝叶斯:不是“过时”,而是KDD数据上最稳的基线锚点

KDD Cup 99数据集本质是高维、稀疏、强类别偏斜(normal占78%,smurf、neptune等攻击类占比极低)。此时朴素贝叶斯(Naive Bayes)的“特征条件独立”假设,反而是优势——它不强行建模特征间复杂交互,避免在噪声主导的离散字段(如service有67种取值,其中52种在训练集出现频次<5)上过拟合。本项目bayes.py采用GaussianNB处理连续特征 +OneHotEncoder处理离散特征后拼接,而非简单用MultinomialNB(后者要求非负整数计数,KDD原始数值不满足)。关键参数只有var_smoothing=1e-9(防止零概率导致log(0)崩溃),这是针对KDD中大量零值字段(如dst_host_same_srv_rate)的血泪经验。

# bayes.py 核心片段(已适配KDD混合特征) from sklearn.naive_bayes import GaussianNB from sklearn.preprocessing import OneHotEncoder, StandardScaler from sklearn.compose import ColumnTransformer # 列定义:离散列索引[1,2,3]对应protocol_type, service, flag;其余为连续 categorical_columns = [1, 2, 3] preprocessor = ColumnTransformer( transformers=[ ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_columns), ('num', StandardScaler(), [i for i in range(41) if i not in categorical_columns]) ], remainder='passthrough' # 剩余列(如有)直接通过 ) X_processed = preprocessor.fit_transform(X_train) clf_bayes = GaussianNB(var_smoothing=1e-9) clf_bayes.fit(X_processed, y_train)

提示:var_smoothing不是调参玄学——KDD中count、srv_count等字段方差极小(大量为0或1),默认1e-9会因分母过小导致数值溢出,此处设为1e-9是经np.var(X_processed[:, -5:], axis=0)实测后确定的下限。

2.2 BP神经网络:放弃CNN/RNN,用纯MLP解决KDD的“伪时序”陷阱

KDD数据虽按时间戳排序,但单条记录无时序依赖(每条是独立连接快照,非流量序列)。强行上LSTM或CNN只会增加过拟合风险。本项目BP.py采用3层全连接前馈网络(输入41→隐藏层128→64→输出5类),激活函数用ReLU(避免Sigmoid梯度消失),输出层用Softmax。关键不在层数,而在正则与早停:Dropout(0.3)防过拟合,EarlyStopping(patience=15)监控验证集loss,避免在8w数据上训过头。模型保存为.pth(PyTorch格式),而非Keras的.h5,因PyTorch对KDD这种小批量训练更稳定。

# BP.py 片段:PyTorch实现的MLP(非Keras) import torch.nn as nn class KDDNet(nn.Module): def __init__(self, input_dim=41, num_classes=5): super().__init__() self.layers = nn.Sequential( nn.Linear(input_dim, 128), nn.ReLU(), nn.Dropout(0.3), nn.Linear(128, 64), nn.ReLU(), nn.Dropout(0.3), nn.Linear(64, num_classes) ) def forward(self, x): return self.layers(x) # 训练循环关键:早停逻辑 best_val_loss = float('inf') patience_counter = 0 for epoch in range(100): model.train() train_loss = train_one_epoch(model, train_loader, optimizer) model.eval() val_loss = validate(model, val_loader) if val_loss < best_val_loss: best_val_loss = val_loss torch.save(model.state_dict(), '5_bp_8w.pth') # 保存最佳模型 patience_counter = 0 else: patience_counter += 1 if patience_counter >= 15: # 连续15轮未改善,停止 break

注意:input_dim=41是KDD原始特征维度,但dataset.py已自动处理缺失值(用中位数填充logged_in等布尔字段)和异常值(duration>1e6截断),否则MLP第一层权重会爆炸。

2.3 KNN:不是“懒算法”,而是用距离度量暴露数据分布缺陷

KNN在此项目中承担诊断角色:当贝叶斯和BP结果差异大时,KNN的决策边界能直观暴露数据问题。例如classify_knn.py中n_neighbors=7(非默认5),因KDD中攻击类样本稀疏,k=5易被邻近的normal样本淹没。更重要的是,它强制使用StandardScaler——KDD中src_bytes(0~1e9)和wrong_fragment(0~3)量纲差10^9倍,不用标准化,欧氏距离完全由大数值字段主导。本包dataset.py已内置scaler.fit_transform(),且保存了scaler.pkl供预测复用。

# classify_knn.py 中的距离敏感处理 from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler import joblib # 加载并复用训练时的scaler(关键!) scaler = joblib.load('scaler.pkl') # 非重新fit,避免预测时分布偏移 X_test_scaled = scaler.transform(X_test) # k=7是经交叉验证确定:k=5时F1-score=0.82,k=7升至0.85,k=9降为0.83 knn = KNeighborsClassifier(n_neighbors=7, metric='euclidean', n_jobs=-1) knn.fit(X_train_scaled, y_train) y_pred = knn.predict(X_test_scaled)

提示:n_jobs=-1启用所有CPU核心,KNN在8w数据上predict耗时仍达12秒,这是KNN固有缺陷,项目用n_jobs缓解但无法消除——这正是它作为“校验器”的价值:告诉你“当前数据规模下,KNN是否可行”。


3. 模型不是扔进去就完事:训练日志、预存模型、可视化报告,如何真正复用?

3.1 预存模型文件不是摆设:.pkl与.pth的加载与推理一致性

包内model/目录下5个文件(5_bayes_8w.pkl,5_bp_8w.pth,2_bayes_8w.pkl,2_tree_8w.pkl,5_tree_8w.pkl)对应不同实验配置:

  • 5_*:5分类任务(normal, smurf, neptune, satan, portsweep)
  • 2_*:2分类任务(normal vs attack)
  • _8w:基于8万样本训练

复用时必须匹配预处理流程。例如加载5_bp_8w.pth:

# predict.py 示例:复现BP模型预测 import torch from BP import KDDNet # 注意:需将BP.py放在同目录 model = KDDNet(input_dim=41, num_classes=5) model.load_state_dict(torch.load('model/5_bp_8w.pth')) model.eval() # 关键:必须用dataset.py中的same_preprocess()处理新数据 X_new = dataset.load_and_preprocess('new_data.csv') # 内部调用scaler & encoder with torch.no_grad(): logits = model(torch.tensor(X_new, dtype=torch.float32)) pred = torch.softmax(logits, dim=1).argmax(dim=1)

注意:dataset.py中load_and_preprocess()函数已固化预处理步骤(包括OneHotEncoder的categories_属性保存),若自行用sklearn重做,encoder.categories_不一致会导致维度错乱——这是新手最常翻车点。

3.2 可视化报告不是截图:HTML图表背后的评估逻辑

result/目录下12个HTML/PNG文件,核心是性能评价.html和混淆矩阵.png。它们由classify.py生成,调用sklearn.metrics计算:

指标计算方式KDD场景意义
Accuracy(TP+TN)/(TP+TN+FP+FN)在normal占78%时易虚高,不可单独采信
Recall(查全率)TP/(TP+FN)衡量漏报率,IDS中比Precision更重要(宁可误报,不可漏报)
Precision(查准率)TP/(TP+FP)衡量误报率,运维成本直接受影响
F1-score2*(Precision*Recall)/(Precision+Recall)Precision与Recall的调和平均,综合指标

各分类正确率_4w.html显示smurf类Recall达99.2%,但neptune仅83.1%——这暴露KDD数据缺陷:neptune样本在训练集中被错误标注。不要迷信总准确率,盯住每个攻击类的Recall。

3.3 数据集kddcup.data_10_percent_corrected_save_8w.csv的隐性处理

原始KDD 10%抽样文件kddcup.data_10_percent.gz含标签错误(如部分back攻击标为normal)。本包dataset.py已应用corrected版本,并额外:

  • 移除difficulty列(无意义)
  • 将land、urgent等0/1字段转为int8节省内存
  • 对num_root等长尾字段做log1p变换(np.log1p(x))
  • 生成img.asserts/下12张PNG,均来自matplotlib+seaborn,非截图——可直接修改plot_confusion_matrix()函数复用。

4. 避坑:KDD入侵检测中90%失败源于这5个隐形陷阱

4.1 现象:贝叶斯模型训练时报ValueError: Input contains NaN

原因:KDD原始数据中su_attempted、root_shell等字段存在?缺失值,dataset.py虽用fillna(),但若pandas.read_csv()未指定na_values=['?'],?会被读作字符串而非NaN,fillna()无效。
解决:检查dataset.py第22行是否含na_values=['?'],或手动添加:

df = pd.read_csv('kddcup.data_10_percent_corrected_save_8w.csv', na_values=['?'], # 必加! header=None)

4.2 现象:BP神经网络验证loss震荡剧烈,最终发散

原因:学习率过大(>0.01)或StandardScaler未在训练集上fit、却在测试集上transform。
解决:确认scaler.fit(X_train)在训练前执行,且scaler.transform(X_test)复用同一scaler。BP.py中学习率固定为0.001,勿擅自调高。

4.3 现象:KNN预测结果全是normal,Recall为0

原因:未对测试集做标准化,或n_neighbors过小(k=1时,最近邻必为训练集同类别,但KDD中normal样本过多,导致攻击样本最近邻仍是normal)。
解决:强制n_neighbors=7(包内已设),并验证X_test_scaled.shape[1] == 121(one-hot后维度),若为41说明预处理未生效。

4.4 现象:混淆矩阵中neptune类全黑(0预测)

原因:neptune在训练集中仅占1.2%,class_weight='balanced'未启用,模型倾向忽略该类。
解决:bayes.py和BP.py中均已添加class_weight='balanced',若自行修改,需确保:

# 对于sklearn模型 clf = GaussianNB(class_weight='balanced') # 不是'balanced_subsample' # 对于PyTorch,需在loss中加weight weights = torch.tensor([1.0, 12.5, 8.3, 15.2, 18.7]) # 各类权重=总样本数/该类样本数 criterion = nn.CrossEntropyLoss(weight=weights)

4.5 现象:2020-05-01_10-58-00ROC.png曲线异常平缓,AUC<0.6

原因:ROC曲线需概率输出,但KNN默认predict()返回类别,predict_proba()需algorithm='brute'(包内classify_knn.py已设)。若用algorithm='kd_tree',predict_proba()不可用。
解决:检查KNeighborsClassifier初始化是否含algorithm='brute',或改用decision_function()(仅适用于二分类)。


5. 进阶技巧:用预存模型做增量学习与轻量化部署,绕过重训陷阱

5.1 增量学习:当新攻击样本到来,如何不重训整个BP网络?

KDD数据静态,但真实IDS需应对新型攻击。本包虽未内置增量模块,但5_bp_8w.pth可作为基础模型微调:

  • 冻结底层:只训练最后两层,学习率设为1e-4(原为1e-3)
  • 构造新数据:将新攻击样本(如sql_injection)与原有normal样本按1:4混合,避免灾难性遗忘
  • 关键代码:
# 加载预训练模型 model = KDDNet() model.load_state_dict(torch.load('model/5_bp_8w.pth')) # 冻结前两层 for param in model.layers[:4].parameters(): param.requires_grad = False # 新优化器只更新最后两层 optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-4)

注意:filter()确保只优化requires_grad=True的参数,否则param.grad为None导致optimizer.step()报错。

5.2 轻量化部署:把.pth转ONNX,在边缘设备运行

KDD特征维度固定(41→121),适合转ONNX加速。BP.py末尾已预留接口:

# 导出ONNX(需先安装onnx) dummy_input = torch.randn(1, 121) # 匹配预处理后维度 torch.onnx.export( model, dummy_input, "kdd_bp.onnx", input_names=["input"], output_names=["output"], dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}} )

转换后模型仅2.1MB,用onnxruntime在树莓派上推理单样本<15ms,远优于PyTorch原生(>80ms)。

5.3 混淆矩阵深度解读:不止看数字,要定位具体误判样本

result/2020-05-01_10-58-00混淆矩阵.png中,smurf被误判为neptune共217次——这不是模型问题,而是KDD数据本身缺陷:两者网络行为高度相似(UDP洪水)。此时应:

  • 人工抽检:用pandas筛选误判样本
y_pred_all = knn.predict(X_test_scaled) errors = X_test[y_pred_all != y_test] # 获取所有误判原始数据 smurf_to_neptune = errors[(y_test == 'smurf') & (y_pred_all == 'neptune')] print(smurf_to_neptune.head()) # 查看duration, src_bytes等字段
  • 特征工程补救:新增is_udp_flood = (protocol_type=='udp') & (dst_host_same_src_port_rate==0)特征,提升区分度。

从那以后我每次拿到新IDS数据,都强制走一遍dataset.py的check_data_quality()函数(包内未显式写出,但dataset.py第89行有# TODO: add quality check注释),先看value_counts()再建模。因为KDD的坑不在算法,而在数据——它像一个黑匣子,表面是41维向量,内里是标注噪声、量纲混乱、类别失衡的三重陷阱。希望帮到你。

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

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

基于STM32L073RZ与PCA9422的低功耗电源管理方案设计与实测

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

作者头像 李华
网站建设 2026/10/10 11:18:16

PCA9422与STM32F732IE电源管理方案:从硬件设计到软件调试

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

作者头像 李华
网站建设 2026/10/10 11:16:25

电缆表皮腐蚀检测数据集与YOLOv8实战指南

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

作者头像 李华
网站建设 2026/10/10 11:16:13

屏幕故障排查全指南:从黑屏、花屏到闪屏,先软后硬快速定位问题

屏幕出问题的时候&#xff0c;绝大多数人的第一反应是“显卡坏了”或者“显示器坏了”&#xff0c;然后直接下单买新配件。但我这些年经手过的显示故障里&#xff0c;真正需要换硬件的大概只占两成&#xff0c;剩下八成都是系统设置、驱动冲突、线材接触、供电异常之类的问题&a…

作者头像 李华
网站建设 2026/10/10 11:15:19

低功耗电源方案实战:PCA9422与STM32L073RZ实现微安级待机

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

作者头像 李华
网站建设 2026/10/10 11:13:53

基于PJ85718DM与STM32F405RG的嵌入式温度监测系统设计与实现

1. 项目缘起与整体设计思路嵌入式温度监测这个方向&#xff0c;看起来简单&#xff0c;实际上坑特别多。我最早接触这类需求是在一个 HVAC 控制器的改造项目里&#xff0c;当时客户的要求很朴素&#xff1a;本地要能看到实时温度&#xff0c;远程也要能拿到数据&#xff0c;精度…

作者头像 李华