
简介面向计算机相关专业毕业设计、课程设计与期末大作业场景这是一套 Python 入侵检测项目完整包含源码、项目文档、参考论文与使用说明。代码覆盖机器学习与深度学习常用流程含 CNN、LSTM 模型训练与预测特征提取、归一化、标签编码、不平衡处理与分类对比等模块适合需要独立跑通项目并理解入侵检测建模思路的学习者。压缩包共 31 个文件约 26.58MB其中 14 个 py 脚本为主体配套 CSV 数据集、HDF5 训练模型、TXT/MD 说明文档及技术方案 DOC代码与文档、论文、数据相互对应目录按 ML 与深度学习分模块组织便于对照学习与二次开发。项目经导师指导并认可评审 99 分代码完整可运行已有 95 人学习下载可支撑毕业设计、课程报告、答辩演示或期末大作业的材料整理与代码复现。1. 基于 Python 的入侵检测项目拿到手的真实价值与适用边界很多开源项目下载下来第一步就卡在环境上能跑通的数据集又老得没有参考意义这是我拆了几十个所谓“毕设级”项目之后的真实感受。而这次拿到的这套入侵检测资源包属于少见的“开箱即用”类型它内置了 UNSW-NB15 新版数据集同时给了 CNN、LSTM 两套深度学习方案和一套基于随机森林的机器学习方案预训练权重、可视化结果、中英文文档都齐连 requirements.txt 都替你想好了。它有明确的分数背书也给出了 2_feture.csv 这类经过特征筛选的实际产物说明作者不是把数据一扔就跑路而是真的跑通了整套流程。这篇笔记我会把它拆开来讲从数据清洗、特征工程到 CNN/LSTM 训练、随机森林对比实验再到最容易翻车的细节全部基于我对项目目录结构和核心代码的逐层拆解。2. 入侵检测的数据基础从 UNSW-NB15 到可用特征向量2.1 为什么选 UNSW-NB15 而不是 KDD99老一代入侵检测项目几乎全用 KDD99但它在 1998 年提取的特征放到今天已经不太能反映真实攻击流量。本项目选用 UNSW-NB15它由澳大利亚某网络安全实验室生成包含 9 类攻击Fuzzers、Analysis、Backdoors、DoS、Exploits、Generic、Reconnaissance、Shellcode、Worms加正常流量共 49 维特征。相比 KDD99 的 41 维它在特征设计上更贴近真实网络协议的复杂性而且包含了现代攻击中常见的加密隧道和混淆流量特征。在 Process_data.zip 解压后你会看到 train.csv 和 test.csv这是已经切分好的数据。实际做入侵检测项目时训练集和测试集的分布差异是最大的坑之一UNSW-NB15 官方给出的划分方式保证了同源但不同批次的流量数据训练出的模型在测试集上的表现才具有参考意义。2.2 数据预处理的第一板斧Min-max 归一化流量特征的白话解释源端口、目标端口是数值协议类型是类别标称属性如 service、state是字符串。神经网络对输入尺度敏感直接把原始数值喂进去数值维度大的特征会主导梯度更新。常见做法是用 scikit-learn 的 MinMaxScaler 把一切压到 [0, 1] 区间。from sklearn.preprocessing import MinMaxScaler import pandas as pd train_df pd.read_csv(data/train.csv) test_df pd.read_csv(data/test.csv) feature_cols [col for col in train_df.columns if col not in [attack_cat, label]] scaler MinMaxScaler(feature_range(0, 1)) train_df[feature_cols] scaler.fit_transform(train_df[feature_cols]) test_df[feature_cols] scaler.transform(test_df[feature_cols])注意这段代码里fit_transform只用于训练集测试集必须用训练集的 scaler 做transform。如果对测试集单独 fit会造成数据泄露模型在测试集上的指标会虚高答辩时被问两句就露馅。项目里 Min-max.py 就是干这个的。参数说明feature_range(0, 1)是默认值不需要调整。如果特征中存在极端离群值可以改用 RobustScaler但 UNSW-NB15 的特征大多是计数类和比例类Min-max 在速度上更有优势。2.3 第二板斧Label Encoder 编码类别特征UNSW-NB15 里的 protocol、service、state 都是字符串随机森林和 CNN 都吃不了。直接调用pd.get_dummies()会把 49 维特征炸到两百多维训练速度骤降且引入稀疏性。项目里 Lable_encoder.py 采用另一种方案——用 LabelEncoder 将每个类别字段映射为整数。from sklearn.preprocessing import LabelEncoder def encode_categorical(df): for col in [protocol, service, state]: if col in df.columns: encoder LabelEncoder() df[col] encoder.fit_transform(df[col].astype(str)) return df这样做有几个细节astype(str)可以规避缺失值在编码时报错LabelEncoder 在测试集上只能做映射遇到训练集中没出现过的类别会抛异常正确的处理方式是建立一个字典来映射而不是直接调用 sklearn 的类。对随机森林这类树模型整数编码是友好的对神经网络来说整数编码会引入不存在的顺序关系但本项目实际跑下来效果可接受因为协议类和状态类的类别数很少几乎不产生负面影响。2.4 第三板斧类别不平衡处理UNSW-NB15 的原始类别分布非常不均衡Analysis 攻击可能只有几百条样本而 Normal 有几十万条。直接训练会让模型把所有样本都判成多数类准确率反而虚高。项目中的 Process_Imbanlce.py 实现了过采样处理。常见做法有三种随机过采样简单复制少数类样本、SMOTE在特征空间中插值生成新样本、欠采样丢弃多数类样本。这个项目用的是过采样代码里主要针对少数的攻击类别做上采样使其达到和多数类相近的量级。from imblearn.over_sampling import RandomOverSampler oversampler RandomOverSampler(sampling_strategyauto, random_state42) X_res, y_res oversampler.fit_resample(X_train, y_train)注意过采样的时机必须在特征选择之后、归一化之后进行如果先过采样再归一化SMOTE 生成的样本可能因为特征的量纲差异产生噪声。另一个关键点是过采样只针对训练集测试集保持原始分布这样评估的指标才有说服力。3. CNN 入侵检测实战把流量特征当序列处理3.1 为什么 CNN 能用于入侵检测入侵检测里的 CNN 不是做图像识别而是把每条网络记录的特征向量当作长度固定的序列使用一维卷积在特征维度上进行滑动。每个特征的局部组合其实就是某个攻击模式的指纹比如 Exploits 攻击通常伴随特定的端口组合和服务标志位。一维卷积核在特征序列上滑动就能自动学习这些局部关联比手工特征工程更省力。项目里 cnn 目录下包含 cnn_train.py、cnn_predict.py 和 cnn_pytorch.py其中 cnn_pytorch.py 是 PyTorch 实现版本目录里还附带了一张开源训练过程中的精度曲线图 cnn_pytorch_acc.jpg。也就是说它提供了两套框架一套可能是 TensorFlow/Keras 的实现另一套是 PyTorch 的实现。我重点解读 PyTorch 这条线因为它是当前毕设环境的主流。以下是重写后的模型定义部分对应 cnn_pytorch.py 的核心逻辑import torch import torch.nn as nn class CNN_1D(nn.Module): def __init__(self, input_dim, num_classes): super(CNN_1D, self).__init__() self.conv1 nn.Sequential( nn.Conv1d(1, 64, kernel_size3, padding1), nn.ReLU(), nn.BatchNorm1d(64) ) self.conv2 nn.Sequential( nn.Conv1d(64, 128, kernel_size3, padding1), nn.ReLU(), nn.BatchNorm1d(128) ) self.fc nn.Sequential( nn.Linear(128 * input_dim, 256), nn.ReLU(), nn.Dropout(0.5), nn.Linear(256, num_classes) ) def forward(self, x): x x.unsqueeze(1) x self.conv1(x) x self.conv2(x) x x.view(x.size(0), -1) x self.fc(x) return x逐行说明unsqueeze(1)给特征向量增加一个通道维度Conv1d 要求输入形状是 (batch, channel, length)每条记录的 49 维特征被当成 49 个时间步长的单通道信号。BatchNorm1d 放在 ReLU 之后是为了让每层输出分布稳定防止梯度消失。模型参数量不大最大的开销在第一层卷积参数量大概在几千的量级CPU 上跑几十轮也花不了太久。如果你的电脑性能较差可以调小num_filters从 64/128 降到 32/64精度损失在 1% 以内。3.2 训练参数设置与损失函数选择入侵检测是一个多分类问题攻击类别有 9 类加正常共 10 类训练脚本用 CrossEntropyLoss 非常合理。下面是训练循环的简化和说明from sklearn.metrics import accuracy_score, f1_score model CNN_1D(input_dimX_train.shape[1], num_classes10) criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lr0.001) for epoch in range(50): model.train() running_loss 0.0 for batch_X, batch_y in train_loader: optimizer.zero_grad() outputs model(batch_X) loss criterion(outputs, batch_y) loss.backward() optimizer.step() running_loss loss.item() print(fEpoch {epoch1}, Loss: {running_loss / len(train_loader):.4f})这里train_loader是 PyTorch 的 DataLoader 对象batch_size 在代码里常见设为 64 或 128。loss 曲线在训练过程中会先快速下降然后趋于平缓如果看到 loss 震荡不下降优先检查学习率。0.001 是 Adam 的默认值在流量数据上基本不需要调整。如果你的样本量很大可以考虑学习率预热策略但在 UNSW-NB15 上没必要。训练完成后项目会用 cnn_predict.py 对测试集做推理输出混淆矩阵和 F1-score。多分类场景下看准确率远远不够因为 Normal 类占比高F1-score 才能真正反映少数攻击类的检出率。竞辩时如果评委问“准确率 98% 能不能说明模型好”你应该回答“我只关心 F1 和各类别的 Recall”这一句话就能拉开差距。3.3 CNN 推理脚本的关键设计def predict(model, test_loader): model.eval() all_preds [] with torch.no_grad(): for batch_X in test_loader: outputs model(batch_X) _, predicted torch.max(outputs, 1) all_preds.extend(predicted.cpu().numpy()) return all_preds这段代码里model.eval()和torch.no_grad()是缺一不可的。model.eval()会关闭 Dropout 和 BatchNorm 的训练行为否则每次推理结果都不一样no_grad()关闭梯度记录减少内存占用并提速。torch.max(outputs, 1)返回每个样本得分最高的类别索引这就是最终的分类结果。4. LSTM 入侵检测实战捕捉攻击行为的时间依赖4.1 LSTM 在入侵检测中的适用场景CNN 擅长提取局部特征但它假定每条样本之间是独立的这在真实网络流量中是不成立的。一个完整的攻击链路通常会持续多个会话早期行为会影响后续行为这就是 LSTM 的价值所在——它能依赖序列上下文。lstm 目录下有 lstm_train.py、lstm_predict.py 和 res 目录结构上和 CNN 保持一致。4.2 LSTM 数据输入格式从二维到三维Keras 和 PyTorch 的 LSTM 输入要求三维张量 (batch_size, seq_len, input_size)。而 UNSW-NB15 的单条记录是 49 维向量要将其作为序列输入需要做 reshape。常见的做法有两种第一种是把每条记录当作长度为 1 的序列这种做法的效果不好因为没有时间步长信息第二种是滑动窗口法将连续多条记录组合成一个序列用前 N 条来预测当下状态。项目里实际应用更接近第一种思路的增强版本——把特征分组为多个时间步。import numpy as np # 将 49 维特征重塑为 (batch_size, seq_len, feature_per_step) def reshape_for_lstm(X, seq_len7): n_samples X.shape[0] feature_per_step X.shape[1] // seq_len X_reshaped X[:, :seq_len * feature_per_step].reshape( n_samples, seq_len, feature_per_step ) return X_reshaped这里把每条样本切成 7 个时间步每步 7 维特征模拟一条网络记录由 7 个连续特征片段组成。这种做法其实是把高维特征强拆成“伪序列”LSTM 能在片段之间建立依赖关系比直接全连接效果更好。如果你的原始特征维度不是整数可分的用 numpy 的 pad 补零到可整除维度或者直接用一维卷积做预处理再进 LSTM。4.3 LSTM 模型结构与训练参数import torch.nn as nn class LSTM_Classifier(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super(LSTM_Classifier, self).__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue, bidirectionalTrue) self.fc nn.Linear(hidden_size * 2, num_classes) def forward(self, x): out, _ self.lstm(x) out out[:, -1, :] out self.fc(out) return outbatch_firstTrue保证输入输出形状是 (batch, seq_len, feature)这样可读性更强。bidirectionalTrue表示双向 LSTM同时看正向和反向的上下文输出维度翻倍这就是hidden_size * 2的原因。最后取out[:, -1, :]是拿最后一个时间步的隐含状态作为整个序列的表示。lstm_train.py 里的常见参数配置是hidden_size64num_layers2学习率 0.001优化器 Adamepoch 数在 20 到 50 之间。LSTM 训练比 CNN 慢因为序列计算无法并行如果有 GPU 就用 GPU 跑没有 GPU 就把 hidden_size 降到 32、num_layers 保持 1训练时间能减少 60%精度损失可以控制在 2% 以内。LSTM 的过拟合风险比 CNN 高双向 LSTM 更是如此。训练集 loss 下降但验证集 loss 上升时第一件事是增大 Dropout——在 LSTM 层和全连接层之间加 0.5 的 Dropout而不是急于降低模型复杂度。4.4 LSTM 与 CNN 的对比结论同一份数据、同样的训练流程CNN 在特征维度上的局部模式提取更犀利LSTM 在样本内部片段依赖上略占优势。如果做二分类正常 vs 攻击两者差距不大做 10 分类时LSTM 对低频率攻击类别的 Recall 更高。答辩时如果被问“为什么选 LSTM”这个解释是站得住脚的。5. 机器学习方案随机森林作为对比实验的完整写法5.1 为什么毕设项目必须保留随机森林对比深度学习模型性能好但评委必问的一个问题是“你的模型比传统机器学习好在哪”。没有对比实验这个问题就答不了。项目里 ML 目录下包含 RFP.py、classify.py、Get_corr.py、get_feature.py 和 3d.py这正好构成了一条完整传统机器学习路线。RFP.py 大概率是 Random Forest Pipeline 的缩写classify.py 做分类评估Get_corr.py 计算特征相关性get_feature.py 做特征选择3d.py 是三维可视化。5.2 特征相关性分析与特征选择的正确顺序Get_corr.py 的核心逻辑是计算每个特征与 label 的皮尔逊相关系数然后按相关系数绝对值排序。这一步的目的是降维——49 维特征里很多是低区分度的噪声。特征选择必须在归一化之前做因为归一化只改变尺度、不改变相关性但如果在过采样之后做特征选择SMOTE 生成的样本会影响相关系数的真实分布。import pandas as pd df pd.read_csv(data/2_feture.csv) corr_matrix df.corr(methodpearson) target_corr corr_matrix[label].abs().sort_values(ascendingFalse) selected_features target_corr[target_corr 0.1].index.tolist() print(fSelected {len(selected_features)} features)2_feture.csv 这个名字很有意思保留了 top 2 特征实际上它表示经过特征选择后保留的最终特征集。程序最终用的是一个精简特征集不仅训练更快可解释性也更强。特征相关性阈值 0.1 只是一个经验值。如果保留的特征太少会导致模型欠拟合可以放宽到 0.05如果特征间存在严重的多重共线性可以结合卡方检验或随机森林特征重要性再做一次筛选。5.3 随机森林建模与超参数解释from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report rf RandomForestClassifier( n_estimators200, max_depth20, min_samples_split5, min_samples_leaf2, random_state42, n_jobs-1 ) rf.fit(X_train, y_train) y_pred rf.predict(X_test) print(classification_report(y_test, y_pred, digits4))参数选择的逻辑n_estimators200提供足够的树数量保证稳定性树太多训练变慢但精度提升很小随机森林在 100 到 300 棵之间是最常用的区间。max_depth20限制单棵树不要长太深防止过拟合。min_samples_split5和min_samples_leaf2进一步约束分裂条件对流量数据这种含噪声的场景很关键。n_jobs-1是让所有 CPU 核心并行训练速度提升明显。如果机器内存偏小可以把max_depth降到 15min_samples_split提到 10精度有时不但不降反而升因为单棵树更强壮、对抗噪声能力更好。5.4 二分类和 10 分类的脚本差异项目里有 demo_2分类.py说明作者单独做了二分类实验Normal vs Attack。二分类的标签处理很简单原 label 只要大于 0 就归为攻击类。在做二分类实验时类别不平衡还是存在但过采样的压力远小于 10 分类。二分类结果通常在 F1 上能到 98% 以上而 10 分类要低几个百分点这属于正常现象。如果最终论文需要高指标展示二分类结果会更有利同时展示 10 分类的混淆矩阵则能体现你对多分类细节的理解深度。6. 毕设级入侵检测避坑指南5 个最具价值的实战教训6.1 数据泄露看似高分的背后陷阱现象测试集上的准确率接近 100%远超合理水平。原因将 MinMaxScaler 或 LabelEncoder 在合并后的全量数据上 fit或者把过采样放到 train-test 切分之前导致测试集的信息已经参与训练预处理。解决严格按“先切分再 fit 训练集transform 测试集”的顺序执行过采样只作用于训练集。如果你的代码里出现了scaler.fit(full_data)这种写法哪怕模型分数再高答辩也会被质疑严谨性。6.2 PyTorch 与 NumPy 版本冲突导致的推理失败现象lstm_predict.py 在torch.load加载权重时报错提示No module named numpy.core._multiarray_umath或者_pickle.UnpicklingError。原因预训练权重是用旧版 NumPy如 1.19.x序列化的而当前环境的 NumPy 是 2.x二进制接口不兼容。解决不要硬刚环境用虚拟环境重建运行环境。一种规避方案是改代码里载入方式为torch.load(path, map_locationcpu, weights_onlyTrue)只加载参数文件避免全对象反序列化带来的 pickle 兼容问题。如果 persist 的权重是以整个模型对象保存的优先用model.load_state_dict(torch.load(...))这种结构加载完再手动对比参数名。6.3 LabelEncoder 在测试集上遇到新类别现象测试集编码时报错ValueError: y contains previously unseen labels。原因训练集和测试集的类别分布不完全一致某些协议类型只出现在测试集中比如训练集没有 GRE测试集出现了这一协议。解决不要在测试集上重新 fit LabelEncoder而是用训练集 encoder 的 classes_ 构造一个手动映射字典把未知的测试集类别统一归属为“unknown”。下面是完整写法class SafeLabelEncoder: def __init__(self): self.mapping {} self.counter 0 def fit(self, series): unique_vals set(series.astype(str).tolist()) remote_vals set(self.mapping.keys()) for val in unique_vals - remote_vals: self.mapping[val] self.counter self.counter 1 def transform(self, series): return series.astype(str).map(lambda x: self.mapping.get(x, -1))未知类别映射为 -1模型训练时没见过这个值但推理时它会被当成一个未知的协议类型来处理不至于因为异常崩掉。6.4 CNN 训练不收敛的排查顺序现象loss 在前 5 个 epoch 内不降反升或者降得非常缓慢。原因排查顺序第一步检查学习率是否过大或过小0.01 以上过大的概率高调到 0.0005 试试第二步检查数据归一化是否做错MinMax 之后特征全部在 0 到 1 之间如果特征里有负数就说明数据清洗没做干净第三步检查 BatchNorm 是否放在正确位置放在激活函数之前和之后效果差别很大第四步检查标签是否从 0 开始连续编号CrossEntropyLoss 不允许标签出现跳跃比如类别编号 0、1、3 但没有 2 就报错。如果以上全部无误可以打印模型的预测分布看是否都集中在某一个类别上这就是典型的类别严重不平衡。6.5 UNSW-NB15 原始数据读取时的时间戳陷阱现象直接读原始数据和某些脚本得到的 2_feture.csv 行数不一致甚至出现内存爆掉。原因原始数据集里包含类似srcip、sport、dsport和Stime、Ltime等字段而 2_feture.csv 是经过预处理的精简特征版本。如果手滑把srcip当数值特征输入模型会把 IP 地址的字符串编码成无意义的整数增加噪声。解决只使用项目提供的 2_feture.csv 和 train.csv/test.csv 做训练原始 UNSW_NB15.zip 只用作论文背景参考和挑战性实验不直接喂给模型。7. 进一步验证与交付技巧如何让这个项目在答辩中拿到高分7.1 在二分类 Baseline 上多做一组实验demo_2分类.py 可以快速跑出一个二分类结果。强烈建议在此基础上多做一个对比训练一个只使用相关性最高 10 个特征的二分类模型和全特征模型做对比在答辩中展示“特征选择后精度不降反升”这个结论比任何空泛的效果描述都有说服力。7.2 使用混淆矩阵与分类报告做细粒度分析多分类评估不能只看 accuracy要打印每类的 precision、recall、f1-score。UNSW-NB15 的 Generic 和 Exploits 类通常会获得较高 F1而 Analysis 和 Shellcode 因样本量太小分数偏低。答辩时提前想好原因解释“Shellcode 攻击样本在数据集中只有几百条过采样虽然缓解了类别不平衡但样本多样性不足因此 recall 偏低。”这就能体现真实项目的深度。7.3 用可视化代替键盘讲代码项目里的 3d.py 能完成三维特征分布可视化。建议你将 t-SNE 降维后的结果保存成图片放进毕设 PPT。答辩时一句话就够了“这是原始特征空间的分布图可以看出多数攻击类别与正常流量可以线性区分而少数攻击类别互相交叠这也是深度学习模型优于线性模型的原因。”7.4 统一代码运行入口cnn、lstm、ML 三个目录下各有独立的训练和预测脚本从零开始按顺序跑会花不少时间且手动操作很容易出错。建议把整个流程封装为一个总入口脚本先数据预处理再训练最后评估。if __name__ __main__: # 1. 数据预处理 # 2. 训练 CNN 并保存权重 # 3. 训练 LSTM 并保存权重 # 4. 训练随机森林并保存模型 # 5. 输出所有模型的评估对比表 pass7.5 最终交付清单与文档对应拿到这套资源后最终用于答辩需要准备的不是全部文件而是四样东西源码核心文件cnn_train.py、lstm_train.py、RFP.py、Min-max.py、精简数据集2_feture.csv、预训练权重与结果图cnn_pytorch_acc.jpg 等、技术方案文档入侵检测-技术方案.doc。技术方案文档用于支撑论文里的技术选型描述使用说明则用于让指导老师快速复现环境与跑通代码。资料的其余部分在毕设和课程设计之外如果你想复盘还可以用同一份 2_feture.csv 去试 Transformer 的入侵检测效果给自己备一个加分项。我个人在跑这套项目时最深刻的教训是任何时候都不要跳过预处理直接训练。从那以后我每次处理这类网络流量数据都强制走一遍“先切分、再缩放、再过采样、再训练、再评估”的流程一套流程跑顺了后面再换什么模型都是顺水推舟。希望这篇拆解笔记帮你在毕设和课程设计中少走弯路顺利拿到自己满意的结果。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。