
简介这套基于机器学习的入侵检测系统源码面向网络安全研究人员与机器学习开发者针对传统IDS过度依赖规则签名、难以识别未知攻击、误报率高等痛点提供了从数据预处理、类别不平衡处理到模型训练与解释的完整实现思路。包内共30个文件包含md说明文档、sql数据库脚本、zip模块压缩包及多个png流程截图整体大小约11.21MB目录按前端、后端、模型等模块拆分便于按需查阅。系统采用SMOTE技术解决数据不平衡融合传统机器学习、集成学习、深度学习和自动机器学习构建模型并结合SHAP与DALEX增强可解释性同时基于Streamlit、Vue和Flask实现全流程自动化检测。目前已吸引175人学习下载适合需要参考完整项目结构、算法应用与可解释性落地细节的开发者。1. 传统IDS失效规则签名解决不了的攻击交给机器学习分类器在流量规模过万的真实网络环境中基于Snort或Suricata的特征匹配IDS每天产生几千条告警其中真正对应到攻击的不超过5%。多数安全团队发现规则库更新永远追不上攻击变种而把检测逻辑从“匹配特征”改为“学习行为”后误报率反而更容易压下来。这就是基于机器学习入侵检测系统的前提不定义规则用流量数据训分类器识别未知攻击。系统真正费功夫的环节集中在四个地方类别不平衡处理、多算法实验、模型解释以及把模型打包成Streamlit、Flask和Vue联动的在线服务。下面按这套路径拆解每一块的实现方式和踩坑点。2. SMOTE数据不平衡处理与入侵检测特征编码做入侵检测分类任务时最先遇到的技术障碍不是模型选型而是数据集分布。KDD Cup 1999、NSL-KDD这类公开流量集里正常流量占八成以上某些攻击类型如U2R、R2L只有几百条样本。直接把原始数据丢给模型训练决策边界会被多数类完全主导模型对少数攻击的召回率接近零系统在实战中等于形同虚设。2.1 类别不平衡让准确率指标完全失真入侵检测里最常用的评估指标是准确率但准确率在不平衡数据上极具欺骗性。一个数据集中正常流量占99%、攻击占1%模型什么都不学直接全部预测为正常准确率也能到99%。可是安全运营需要的是把攻击找出来哪怕付出少量误报的代价。所以评估这个任务时我一般只看三个指标召回率、精确率和F1-Score。召回率反映真正的攻击有多少被检出精确率反映报出来的告警里有多少是真的两者通常此消彼长。在安全场景宁可精确率略低也要优先保证召回率漏报的代价远超误报。注意入侵检测模型评估不能只看准确率必须结合混淆矩阵、F1值和AUC综合判断。2.2 SMOTE合成少数类样本的原理与实现SMOTESynthetic Minority Over-sampling Technique处理不平衡的思路是在少数类样本与其k近邻之间的连线上随机生成新样本而不是简单复制原文。合成公式是新样本 选中样本 随机比例因子 × (近邻样本 - 选中样本)。随机比例因子取0到1之间的随机数所以生成的新样本不会与原始样本完全重合能在特征空间上拓宽少数类的覆盖范围。以NSL-KDD数据集为例原始数据是CSV格式包含协议类型、服务类型、源字节数、目标主机访问频率等41个特征。预处理阶段要先把protocal_type、service、flag这几个字符型特征做编码再把标签映射为二分类正常/攻击。from imblearn.over_sampling import SMOTE from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder import pandas as pd columns [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,difficulty_level] df pd.read_csv(KDDTrain.csv, namescolumns) categorical_cols [protocol_type, service, flag] for col in categorical_cols: df[col] LabelEncoder().fit_transform(df[col]) X df.drop([label, difficulty_level], axis1) y df[label].apply(lambda x: 0 if x normal else 1) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) smote SMOTE(sampling_strategy0.5, k_neighbors5, random_state42) X_train_res, y_train_res smote.fit_resample(X_train, y_train) print(原始训练集攻击占比:, y_train.mean()) print(SMOTE之后攻击占比:, y_train_res.mean())代码逻辑分三步走第一步给NSL-KDD原始文件补上列名并做字符特征编码第二步按分层抽样划分训练集和测试集保证测试集里的攻击比例不变第三步只在训练集上拟合SMOTE。分割之后再采样是必须的如果先做SMOTE再分割合成样本和测试样本可能携带相同分布信息最终评估结果会虚高。sampling_strategy设成0.5表示合成后少数类数量达到多数类的一半不需要完全平衡完全平衡会让正常流量的多样性被削弱。k_neighbors默认是5当样本量很小时可以降到3防止在高维特征空间里生成离群点。2.3 与过采样、欠采样的对比选择不同采样方案在IDS任务上的特性差异比较明显方法核心思想优点缺点IDS场景适用性RandomOverSampler随机复制少数类实现简单训练速度快容易过拟合复制样本无新信息不推荐单独使用RandomUnderSampler随机删除多数类数据集缩小训练开销低丢失正常流量多样性不推荐SMOTE在近邻间插值生成新样本缓解过拟合保留多数类全部信息对噪声敏感可能生成类间重叠推荐默认选择ADASYN按学习难度自动分配合成数量更关注难分类的少数样本噪声样本会被放大数据噪声低时可用从实际项目经验看如果合成样本让模型F1值反而不升多半是原始数据噪声太大此时优先清洗特征而不是调整SMOTE参数。核心原则始终是一条只在训练集上做采样测试集保持真实分布否则最终报告的检测能力不是模型在新流量上的真实能力。3. 多模型对比与AutoML从逻辑回归到XGBoost的检测实验处理完数据不平衡接下来搭建多模型实验基线。这套项目覆盖四条算法路线传统机器学习、集成学习、深度学习、自动机器学习。每类方法对入侵检测问题的适应面不同验证周期也差很多。3.1 四类检测模型的选型逻辑传统机器学习模型里逻辑回归是起点输出概率值可以天然给告警排序决策树可解释性强但单棵树泛化能力有限面对高纬流量特征很容易过拟合。SVM在高维空间表现不错但训练集上万条时收敛速度会明显变慢超参数敏感我通常只在小样本场景下用。集成学习是当前IDS实验里最稳健的选择。随机森林通过多棵树投票降低方差XGBoost和LightGBM在梯度提升上做了大量工程优化对表格型流量数据的非线性关系拟合能力强。在NSL-KDD这类特征集上LightGBM和XGBoost的表现通常领先随机森林而且训练时间可控。深度学习方面DNN是最直接的尝试把特征向量输入全连接网络即可CNN可以把特征重排成二维矩阵提取局部模式LSTM适合处理带会话时序的流量数据但收敛速度慢在小流量集上收益不明显。自动机器学习AutoML方面TPOT通过遗传规划自动搜索特征处理和模型组合AutoGluon则用多层集成自动组合基础模型。AutoML能省去人工调参但搜索耗时可能长达数十小时更适合离线选型不适合在线训练。3.2 用统一评估框架对比多模型效果我习惯把模型训练封装在统一脚本里使用同一份SMOTE后的训练集做交叉验证。from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from xgboost import XGBClassifier from sklearn.model_selection import cross_val_score from sklearn.metrics import precision_recall_fscore_support import warnings warnings.filterwarnings(ignore) models { logistic: LogisticRegression(max_iter500), random_forest: RandomForestClassifier(n_estimators200, max_depth12), xgboost: XGBClassifier(n_estimators300, learning_rate0.05, max_depth6) } for name, model in models.items(): scores cross_val_score(model, X_train_res, y_train_res, cv3, scoringf1) print(f{name}: F1均值{scores.mean():.4f} 标准差{scores.std():.4f}) for name, model in models.items(): model.fit(X_train_res, y_train_res) y_pred model.predict(X_test) precision, recall, f1, _ precision_recall_fscore_support( y_test, y_pred, averagebinary) print(f{name}: Precision{precision:.4f}, Recall{recall:.4f}, F1{f1:.4f})代码里cv设成3而不是5因为SMOTE后的训练集已经有相当规模5折会显著拉长总时间。先用F1均值筛掉明显弱势的模型再用全量训练集拟合最优模型并到测试集上验证。对比输出时会发现一个规律逻辑回归往往牺牲召回率去换精确率因为它的线性边界拟合不住流量特征的非线性关系随机森林和XGBoost则能同时稳住两个指标。如果某个模型Precision高但Recall低说明攻击样本大量被漏掉如果Recall高但Precision低说明正常流量被大量误报。在线系统里我宁可选择后者漏报比误报更危险。3.3 AutoML搜索与最终模型固化用TPOT做自动化搜索时关键参数是generations和population_size。from tpot import TPOTClassifier tpot TPOTClassifier( generations5, population_size20, cv3, scoringf1, random_state42, n_jobs-1 ) tpot.fit(X_train_res, y_train_res) print(tpot.fitted_pipeline_) tpot.export(best_pipeline.py)TPOT会将最优管道导出成一个完整的Python文件里面可能包含特征缩放、降维、模型组合等步骤。使用它时有一点要留意导出的代码依赖库需要逐个确认不能直接当作纯模型文件加载。在线推理服务中我一般把TPOT选出的最优管道固化成一个sklearn Pipeline然后用joblib序列化。如果对推理延迟有硬性要求最终选择XGBoost如果更看重鲁棒性和多模型间的互补选择AutoGluon自动集成。4. SHAP与DALEX入侵检测模型的黑箱解释方法训练完模型只能说明它能用还不能说明它为什么能用。在安全运维中分析师收到告警后第一反应就是问“这条流量哪里可疑”。如果模型预测拿不出可解释的证据告警很难被采信。这正是这套项目引入SHAP和DALEX的直接原因。4.1 SHAP贡献值计算与局部特征归因SHAP的核心思想源自博弈论中的Shapley值把每个特征视为一个玩家模型预测是这些特征合作产出的结果。某个特征的贡献等于它在所有特征组合中的边际贡献加权和。相比传统特征重要性SHAP能给出每个样本内部的局部正负解释。import shap explainer shap.TreeExplainer(model) shap_values explainer.shap_values(X_test_sample) shap.summary_plot(shap_values, X_test_sample, feature_namesX.columns) shap.force_plot(explainer.expected_value, shap_values[0], X_test.iloc[0])TreeExplainer只适用于树模型家族对XGBoost、随机森林的计算速度极快。summary_plot展示两类信息散点图部分反映每个特征在所有样本上的SHAP值分布颜色表示特征值高低条形图部分输出全部特征的重要性排序。对入侵检测来说通常会发现“目标主机访问频率”“服务出现次数”这类特征排在最前面说明短时间高频访问目标主机的流量最容易被判定为攻击。force_plot用于单条样本解释红蓝色箭头分别表示特征把预测值推向攻击还是推回正常。在告警系统里我一般把base value和各个特征的贡献值序列化到告警json中随告警一同推送。4.2 DALEX模型无关解释与残差诊断DALEX是模型无关的解释框架不依赖模型内部结构适用于任意sklearn接口的模型。它的工作流是先构建explainer再调用predict_parts和model_profile做分析。import dalex as dx explainer dx.Explainer(model, X_train_res, y_train_res, labelxgboost) breakdown explainer.predict_parts(X_test.iloc[[0]], typebreak_down) breakdown.plot() profile explainer.model_profile(typepartial) profile.plot()predict_parts生成的Break Down图展示某个样本从基线预测值逐步变化到最终预测值的过程哪几个特征贡献最大一目了然。model_profile则画出单个特征变化时模型预测的响应曲线如果曲线出现不自然的锯齿状波动说明模型对该特征过度敏感需要做分箱或正则化处理。在模型更新流程中我会定期对线上版本做一次DALEX残差分布检查如果某个攻击类别的样本残差集中且偏大就说明该类别没学好需要回去检查特征工程或补充此类攻击的训练数据。4.3 SHAP与DALEX的分工实际项目中两个工具是配合使用的而不是二选一工具侧重点常用场景SHAP局部单样本归因、全局特征重要性生成单条告警的解释证据DALEX模型整体残差、特征影响曲线离线诊断模型盲区、评估新特征有效性SHAP解释结果直接参与在线告警让每条告警带上证据DALEX分析报告进入模型迭代的审计记录作为特征调整和版本上线的判断依据。这样模型可解释性就不再是论文里的图表而是安全运营能直接使用的决策信息。5. Streamlit与FlaskVue部署机器学习入侵检测系统的在线服务模型实验结束后工程价值体现在把模型变成可操作的系统。这套项目的部署结构是Flask提供核心推理服务Vue作为管理端前端Streamlit作为交互式演示页面。5.1 Flask模型推理API实现Flask服务加载固化后的模型和预处理器暴露detect接口。from flask import Flask, request, jsonify import joblib import pandas as pd app Flask(__name__) model joblib.load(models/xgboost_model.joblib) # 编码映射和特征顺序在训练时固定在线推理不重复fit categorical_maps joblib.load(models/categorical_maps.joblib) app.route(/detect, methods[POST]) def detect(): data request.get_json() for col in categorical_maps: if data.get(col) in categorical_maps[col]: data[col] categorical_maps[col][data[col]] df pd.DataFrame([data]) prob model.predict_proba(df)[0][1] label 1 if prob 0.5 else 0 return jsonify({prediction: int(label), probability: round(float(prob), 4)}) if __name__ __main__: app.run(host0.0.0.0, port5000)判定的概率阈值0.5并不适合所有场景。如果安全运营要求更高的召回率把阈值做成可配置参数从环境变量读取比改代码优雅得多。另一个工程坑是特征顺序训练时DataFrame的列顺序和客户端传来的json键顺序很可能不一致传参前必须用固定好的特征列表对齐。5.2 Streamlit交互式检测页面Streamlit适合快速搭建内部验证入口用最少代码把模型变成可视化工具。import streamlit as st import requests st.title(网络流量入侵检测) protocol st.selectbox(协议类型, [tcp, udp, icmp]) service st.selectbox(服务类型, [http, ftp, smtp, other]) src_bytes st.number_input(源字节数, min_value0, value1000) sample {protocol_type: protocol, service: service, src_bytes: src_bytes} if st.button(检测): resp requests.post(http://127.0.0.1:5000/detect, jsonsample) st.write(resp.json())Streamlit省去了前后端联调的成本适合在实验阶段验证模型效果。Vue管理端则承载资产列表、告警展示和权限控制通过代理转发到Flask服务。流量采集环节通常用tcpdump或nfacct抓包后解析成特征行再批量请求detect接口。请求侧要加上线程池和超时控制防止流量峰值把Flask服务打满。5.3 模型上线后的闭环验证技巧模型部署后不能只看在线返回结果要做闭环验证。我的做法是把每天的检测结果持久化到告警表每周拉取预测结果和人工确认结果重新计算精确率和召回率。如果召回率出现下降优先检查特征分布是否漂移比如某类服务占比突然变化导致标准化输入偏离训练分布。第二个技巧是给在线模型加一个概率缓冲带概率在0.4到0.6之间的样本不做自动判决而是交给安全分析师人工复审。这个缓冲带把模型的不确定性显性化不需要频繁调整硬阈值就能降低误报压力同时复审结论可以作为下一轮训练的高质量标注数据形成检测模型持续迭代的闭环。本文还有配套的精品资源点击获取