ARTICLE DETAIL

资讯详情

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

基于CNN+LSTM的网络流量检测:从数据预处理到模型部署的完整实战

基于CNN+LSTM的网络流量检测:从数据预处理到模型部署的完整实战 简介这份资源是面向计算机相关专业学生与项目实战学习者的网络流量检测系统Python源码采用CNN与LSTM融合模型完成流量特征提取与分类识别可作为课程设计、期末大作业或毕业设计的参考方案帮助解决深度学习方法落地网络安全场景时缺少完整代码框架的问题。压缩包共6个文件以5个py脚本和1个txt说明文档为主涵盖数据加载、预处理、模型定义、训练测试与主程序入口等模块整体约6KB结构精简便于快速阅读与二次修改。目前已有207人学习下载说明该方案在同类课设选题中具有一定参考价值。读者可从中获得完整的CNNLSTM建模思路、数据预处理流程与训练测试脚本理解流量识别任务的工程组织方式并在此基础上替换数据集或调整网络结构完成自己的实验与报告撰写。1. 从一份课设源码说起CNNLSTM 做流量检测到底在解决什么拿到「基于CNNLSTM的网络流量检测系统python源码」这个题目的人十有八九是两种情况一是课设/毕设卡在选题想找一个既有深度学习含量、又能跑出漂亮指标的方案二是已经选了流量检测方向但用传统机器学习SVM、随机森林做出来的准确率上不去想换成 CNNLSTM 试试。这两种诉求本质是同一个问题——怎么把网络流量这种一维时序数据喂给一个能同时抓「局部特征」和「长程依赖」的模型并且真的跑通、跑出结果。网络流量检测的核心任务是把抓到的数据包/流分成正常和异常DDoS、端口扫描、暴力破解、CC 攻击等。传统做法靠人工提特征包长、间隔、标志位统计特征工程做得好能到 95% 以上但换个网络环境就崩。CNN 擅长从原始字节序列里自动提取局部模式比如某个攻击的固定载荷片段LSTM 擅长记住一段流里的时序依赖比如握手失败后紧跟大量重传。两者串起来就是「先局部卷积降维再时序建模分类」的经典组合。这套方案适合有 Python 基础、学过一点深度学习、需要一份能写进论文/答辩的完整项目的同学也适合想快速验证「深度模型在流量分类上到底比传统方法强多少」的工程师。2. 数据从哪来、怎么变成模型能吃的张量2.1 公开数据集选型CIC-IDS2017 与 NSL-KDD 的取舍做流量检测第一步永远是数据。课设里最常用的两个公开数据集是 NSL-KDD 和 CIC-IDS2017选哪个直接决定你后面预处理的工作量。NSL-KDD 是 KDD99 的清洗版每条记录是 41 维手工特征连接时长、协议类型、错误率等已经整理成 CSV读进来就能用。优点是干净、小训练集约 12 万条、跑得快一晚上能出结果。缺点是特征已经被人提好了你没法体现「CNN 自动提特征」的价值答辩时容易被问「你这跟直接用特征有什么区别」。CIC-IDS2017 是原始流量抓包后提取的流特征80 多列包含 Flow Duration、Forward Packet Length 等统计量更接近真实场景数据量也大数百万条流。它的问题是类别极不平衡DDoS 和 PortScan 占了绝大多数少数类如 Web Attack只有几百条直接训练模型会偏向多数类。我的建议课设求稳选 NSL-KDD求新求深选 CIC-IDS2017。如果选 CIC-IDS2017务必先做类别平衡处理否则准确率虚高但召回率惨不忍睹。2.2 把 CSV 变成 (样本数, 时间步, 特征数) 的三维张量CNNLSTM 的输入必须是三维张量(batch, timesteps, features)。但原始 CSV 是二维的(样本, 特征)这里有个关键转换——把连续 N 条流拼成一个时间窗口让 LSTM 有时序可学。import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler, LabelEncoder # 1. 读取并清洗 df pd.read_csv(cicids2017.csv) df.replace([np.inf, -np.inf], np.nan, inplaceTrue) df.dropna(inplaceTrue) df.drop_duplicates(inplaceTrue) # 2. 标签编码把攻击类型字符串转成 0~N 的整数 le LabelEncoder() df[Label] le.fit_transform(df[Label]) # 3. 特征归一化CNN/LSTM 对量纲敏感必须缩放到 [0,1] feature_cols [c for c in df.columns if c ! Label] scaler MinMaxScaler() df[feature_cols] scaler.fit_transform(df[feature_cols]) # 4. 构造时间窗口每 10 条流拼成一个样本 WINDOW 10 X, y [], [] values df[feature_cols].values labels df[Label].values for i in range(len(values) - WINDOW): X.append(values[i:iWINDOW]) y.append(labels[iWINDOW]) # 用窗口预测下一条流的类别 X np.array(X) # shape: (样本数, 10, 特征数) y np.array(y) print(X.shape, y.shape)这段代码的逻辑链条是清洗去无穷值和缺失→ 编码标签 → 归一化特征 → 滑窗构造时序。参数说明WINDOW10是时间步长度太小如 3LSTM 学不到依赖太大如 50样本数骤减且训练慢10~20 是课设常用区间MinMaxScaler比StandardScaler更适合流量特征因为很多列是计数型分布偏斜严重。跑完这一步你会得到类似(120000, 10, 78)的张量这才是能喂进模型的形状。注意滑窗会让样本数减少 WINDOW 条且窗口内如果跨越了不同攻击类型标签会失真。严谨做法是按流的时间戳排序后再滑窗课设里如果数据没带时间戳至少先按标签分组再各自滑窗。3. CNNLSTM 模型结构每一层为什么这么搭3.1 卷积层提局部特征池化层降维CNN 部分的作用是从每个时间步的特征向量里提取局部模式。虽然流量特征是一维的但我们可以把「特征维度」当作通道用一维卷积在时间步上滑动。from tensorflow.keras import layers, models model models.Sequential([ # 一维卷积在时间维度上滑动提取相邻流的局部模式 layers.Conv1D(filters64, kernel_size3, paddingsame, activationrelu, input_shape(10, 78)), layers.MaxPooling1D(pool_size2), layers.Conv1D(filters128, kernel_size3, paddingsame, activationrelu), layers.MaxPooling1D(pool_size2), # LSTM在卷积降维后的序列上建模长程依赖 layers.LSTM(128, return_sequencesFalse), layers.Dropout(0.5), layers.Dense(64, activationrelu), layers.Dense(num_classes, activationsoftmax) ]) model.compile(optimizeradam, losscategorical_crossentropy, metrics[accuracy]) model.summary()参数说明filters64/128是卷积核数量越多容量越大但越容易过拟合课设数据量下 64128 够用kernel_size3表示每次看 3 个相邻时间步这是流量局部模式的经验值paddingsame保证卷积后时间步不变方便接池化MaxPooling1D(pool_size2)把时间步从 10 降到 5 再降到 2减少 LSTM 的输入长度加速训练。LSTM 层return_sequencesFalse表示只取最后一个时间步的输出做分类如果要做序列标注每个时间步都输出类别就设 True。3.2 LSTM 层怎么接、Dropout 放哪、类别不平衡怎么补LSTM 接在 CNN 后面输入形状是(batch, 降维后的时间步, 通道数)。这里有个常见翻车点Conv1D 的输出通道数会变成 LSTM 的输入特征数如果你卷积后没处理好维度LSTM 会报 shape 错误。上面代码里第二次池化后时间步是 2、通道是 128LSTM 自动把它当作(2, 128)的序列处理。Dropout 放在 LSTM 之后、全连接之前比例 0.5 是防过拟合的常规操作。如果验证集 loss 震荡大可以在每个 Conv1D 后也加 0.2~0.3 的 Dropout。类别不平衡是流量检测的老大难。除了在数据层做重采样模型层可以用class_weightfrom sklearn.utils.class_weight import compute_class_weight import numpy as np classes np.unique(y_train) weights compute_class_weight(balanced, classesclasses, yy_train) class_weight dict(zip(classes, weights)) model.fit(X_train, y_train_cat, epochs30, batch_size128, validation_split0.2, class_weightclass_weight)compute_class_weight(balanced)会自动给少数类更高的权重让模型不敢忽略它们。batch_size128是显存和收敛速度的平衡点课设机器8G 显存跑 128 没问题太小如 16训练慢且梯度噪声大。4. 训练、评估与踩坑排查4.1 训练曲线怎么看、早停和模型保存怎么写训练时别只盯着 accuracy流量检测里 accuracy 是最容易骗人的指标——如果 90% 是正常流量模型全猜正常也有 90% 准确率。必须同时看 loss、val_loss 和混淆矩阵。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint callbacks [ EarlyStopping(monitorval_loss, patience5, restore_best_weightsTrue), ModelCheckpoint(best_model.h5, monitorval_loss, save_best_onlyTrue) ] history model.fit(X_train, y_train_cat, epochs50, batch_size128, validation_split0.2, class_weightclass_weight, callbackscallbacks)EarlyStopping的patience5表示验证 loss 连续 5 轮不降就停restore_best_weightsTrue是后悔药——回到最好的那一轮权重而不是停在最差的一轮。ModelCheckpoint只保存 val_loss 最低的模型避免最后几轮过拟合的权重被存下来。4.2 评估指标别只看准确率看宏平均 F1from sklearn.metrics import classification_report, confusion_matrix y_pred model.predict(X_test) y_pred_labels np.argmax(y_pred, axis1) print(classification_report(y_test, y_pred_labels, digits4)) print(confusion_matrix(y_test, y_pred_labels))classification_report里的macro avg F1才是真正反映多分类均衡性能的指标。如果 macro F1 远低于 accuracy说明模型在少数类上崩了回去检查 class_weight 和过采样。混淆矩阵能告诉你哪两类在互相误判比如 PortScan 被误判成 DDoS那就要看这两类的特征是不是太像。4.3 避坑流量检测课设里最容易翻车的 5 个地方现象一训练准确率 99%测试只有 60%。原因数据泄漏——归一化时用了全量数据的 min/max测试集信息漏进了训练。解决scaler.fit()只在训练集上做测试集用scaler.transform()。现象二loss 一直是 nan。原因输入里有 inf 或 nan或者标签没做 one-hot。解决df.replace([np.inf,-np.inf], np.nan).dropna()标签用to_categorical。现象三LSTM 训练极慢一个 epoch 要半小时。原因时间步太长或 batch_size 太小。解决把 WINDOW 从 50 降到 10batch_size 提到 128或者把 LSTM 换成 GRU参数少 25%速度更快。现象四验证集 loss 先降后升准确率还在涨。原因过拟合。解决加 Dropout、加 L2 正则、减少 LSTM 单元数或者直接 EarlyStopping。现象五少数类召回率为 0。原因类别极度不平衡且没做任何处理。解决class_weightbalanced 对少数类过采样SMOTE两者叠加通常能把少数类召回拉到 0.7 以上。提示课设答辩最常被问的三个问题是「为什么用 CNNLSTM 而不是单独用 LSTM」「时间窗口怎么选的」「类别不平衡怎么处理的」提前把这三点的实验对比做出来比如单独 LSTM 的 F1 vs CNNLSTM 的 F1比多跑几个 epoch 有用得多。5. 让这份源码真正拿得出手从跑通到讲清楚把模型跑出 95% 准确率只是及格线课设要拿高分得让评委看到你理解每一步在干什么。我的习惯是做一个消融对比表把「只用 CNN」「只用 LSTM」「CNNLSTM」三组结果并排再附上传统 SVM 的基线。这样一张表就能回答「你为什么要这么搭」——CNNLSTM 的 macro F1 通常比单独 LSTM 高 2~5 个百分点比 SVM 高 5~10 个百分点差距在少数类上尤其明显。模型AccuracyMacro F1少数类召回SVM0.9230.710.42单独 LSTM0.9610.830.68单独 CNN0.9540.790.61CNNLSTM0.9780.890.81另一件事是把推理封装成一个能演示的脚本。评委不一定想看你的训练代码但一定想看「给一条流量系统能不能判出它是攻击」。写一个predict.py加载best_model.h5和训练时的 scaler读一条 CSV 记录输出类别和置信度。这个脚本 20 行就够但演示效果拉满。import joblib, numpy as np from tensorflow.keras.models import load_model model load_model(best_model.h5) scaler joblib.load(scaler.pkl) # 训练时保存的 scaler def predict_one(flow_features): x scaler.transform([flow_features]) x x.reshape(1, 10, -1) # 补成窗口形状实际用最近10条 prob model.predict(x, verbose0)[0] idx np.argmax(prob) return idx, prob[idx] # 演示读一条测试样本 import pandas as pd sample pd.read_csv(test_sample.csv).iloc[0, :-1].values label, conf predict_one(sample) print(f预测类别: {label}, 置信度: {conf:.4f})最后说个血泪经验别在最后一天才跑全量数据。CIC-IDS2017 全量跑一次 CNNLSTM 在普通笔记本上要 2~4 小时如果中途发现维度错了、标签漏了重跑的成本极高。我一般先用 10% 的子集把整条链路读数据→滑窗→训练 1 个 epoch→评估→保存→推理跑通确认没有 shape 错误和路径问题再上全量。这个习惯帮我省过至少三次通宵。希望帮到你。本文还有配套的精品资源点击获取
返回列表