基于机器学习的网络入侵检测与特征选择及随机森林分类器性能评估(NSL-KDD数据集)

简介

本文将详细介绍如何利用Python和相关机器学习库对NSL-KDD数据集进行预处理,特征选择,并通过随机森林算法构建网络入侵检测模型。同时,还将展示如何计算并可视化模型的ROC曲线以评估其性能。

首先,我们导入了必要的库,如pandas、seaborn、numpy以及scikit-learn等,并加载了KDDTrain+和KDDTest+两个数据集。通过对数据集进行初步探索,我们将列名重置为实际含义,并将标签(attack_type)以及其他类别型特征进行了编码转换。

在特征工程阶段,我们分析了攻击类型特征的相关性,通过找出与攻击类型关联最小的10个特征以及标准差较小的5个特征,确定了一组待删除的冗余特征。通过剔除这些特征,我们得到了精简后的数据集combined_data_reduced,并进一步将其划分为特征矩阵X和目标向量y。

接下来,我们使用随机森林分类器作为模型,设置了参数n_estimators为10,criterion为’entropy’,max_features为’auto’,bootstrap设置为True,以便训练模型并对测试集进行预测。获取模型在测试集上的得分,并输出了特征重要性。

为了更深入地评估模型的性能,我们还绘制了ROC曲线。ROC曲线是一种用于二分类问题中直观展示模型性能的工具,它展示了假正率(False Positive Rate, FPR)与真正率(True Positive Rate, TPR)之间的权衡关系。这里我们生成了一个示例数据集,并使用同样的随机森林模型计算出其ROC曲线。最后,我们在图表中添加了“无技能”基准线(即随机猜测的结果),并与模型的实际ROC曲线进行了对比。

总结来说,本篇文章展示了从原始数据预处理到特征选择,再到建立随机森林模型并评估其性能的全过程,为我们提供了在网络入侵检测领域运用机器学习技术的一个实践案例。

步骤

  1. 数据加载与初步预处理:读取KDDTrain+和KDDTest+两个CSV文件,合并为一个数据集,并重新命名列名。
  2. 特征工程:对类别型特征如攻击类型、协议类型等进行标签编码,分析特征与目标变量之间的相关性,基于相关性和标准差筛选出最不相关的特征予以删除,优化特征空间。
  3. 数据划分:将精简后的数据集划分为特征矩阵X和目标向量y,并进一步划分为训练集和测试集。
  4. 模型建立与训练:使用随机森林分类器进行训练,设置参数优化模型性能。
  5. 模型评估:计算模型在测试集上的准确率,并提取特征重要性;此外,还通过生成二分类示例数据集,展示了模型的ROC曲线,以更全面地评估模型在区分正常流量与攻击流量时的性能。

代码实现

导入必要的库

# 配置IPython自动补全为贪心模式
%config IPCompleter.greedy=True
# 导入数据处理和可视化库
import pandas as pd
import seaborn as sns
import numpy as np
import re
import sklearn# 忽略警告信息
import warnings
warnings.filterwarnings("ignore")# 导入绘图库及其配置
import matplotlib.pyplot as plt
import matplotlib as matplot
%matplotlib inline# 设置IPython交互模式为全节点
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"# 导入数据集划分工具
from sklearn.model_selection import train_test_split

数据加载及预处理

从指定路径读取NSL-KDD99数据集的训练集和测试集;
重置训练集和测试集的列名,以便后续处理;
将训练集和测试集合并为一个大的数据集,以便进行统一的分析和处理;
调整数据集的列名,以符合特征的实际情况;
删除不需要的特征列,以简化数据集。

# 导入训练集和测试集
train = pd.read_csv('/kaggle/input/nsl-kdd99-dataset/KDDTrain+.txt')
test = pd.read_csv('/kaggle/input/nsl-kdd99-dataset/KDDTest+.txt')# 获取训练集和测试集的形状(行数和列数)
train.shape
test.shape # 重命名训练集和测试集的列,使用列的序号作为列名
train.columns = range(train.shape[1])
test.columns = range(test.shape[1])# 定义标签列表,对应数据集中的特征含义
labels = ['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', 'attack_type', 'difficulty_level']# subclass - > attack_type# 将训练集和测试集合并为一个数据集
combined_data = pd.concat([train, test])# 获取合并后数据集的形状
combined_data.shape# 显示合并后数据集的前5行
combined_data.head(5)# 将合并后数据集的列名替换为定义的标签列表
combined_data.columns = labels# 删除合并后数据集中的'difficulty_level'列
combined_data = combined_data.drop('difficulty_level', 1)# 显示处理后的合并数据集的前3行
combined_data.head(3)
0123456789...33343536373839404142
00udpotherSF14600000...0.000.600.880.000.000.000.00.00normal15
10tcpprivateS0000000...0.100.050.000.001.001.000.00.00neptune19
20tcphttpSF23281530000...1.000.000.030.040.030.010.00.01normal21
30tcphttpSF1994200000...1.000.000.000.000.000.000.00.00normal21
40tcpprivateREJ000000...0.070.070.000.000.000.001.01.00neptune21

5 rows × 43 columns

durationprotocol_typeserviceflagsrc_bytesdst_byteslandwrong_fragmenturgenthot...dst_host_srv_countdst_host_same_srv_ratedst_host_diff_srv_ratedst_host_same_src_port_ratedst_host_srv_diff_host_ratedst_host_serror_ratedst_host_srv_serror_ratedst_host_rerror_ratedst_host_srv_rerror_rateattack_type
00udpotherSF14600000...10.00.600.880.000.000.000.00.00normal
10tcpprivateS0000000...260.10.050.000.001.001.000.00.00neptune
20tcphttpSF23281530000...2551.00.000.030.040.030.010.00.01normal

3 rows × 42 columns

数据编码

from sklearn import preprocessing
# 导入预处理模块le = preprocessing.LabelEncoder()
# 创建标签编码器对象# 打印攻击类型集合,以查看原始值
print(set(list(combined_data['attack_type']))) # 对数据集中的'attack_type''protocol_type''service''flag'列进行标签编码
combined_data['attack_type'] = le.fit_transform(combined_data['attack_type'])
combined_data['protocol_type'] = le.fit_transform(combined_data['protocol_type'])
combined_data['service'] = le.fit_transform(combined_data['service'])
combined_data['flag'] = le.fit_transform(combined_data['flag'])# 描述编码后的攻击类型数据
print('\nDescribing attack_type: ')
print("min", combined_data['attack_type'].min()) # 最小值
print("max", combined_data['attack_type'].max()) # 最大值
print("mean", combined_data['attack_type'].mean()) # 平均值
print("mode", combined_data['attack_type'].mode()) # 模式,即出现频率最高的值
print("looks like 16 is 'normal' ")
# 根据编码结果推断,16可能代表'normal'攻击类型

特征消除和数据集分割

根据攻击类型与其他特征的相关性以及特征的标准差,进行特征选择和消除

# 计算特征之间的相关性矩阵,并按'attack_type'的绝对相关性值进行排序
corr_matrix = combined_data.corr().abs().sort_values('attack_type')# 选择与'attack_type'相关性最低的前10个特征
leastCorrelated = corr_matrix['attack_type'].nsmallest(10)
leastCorrelated = list(leastCorrelated.index)# 选择标准差最低的前5个特征
leastSTD =  combined_data.std().to_frame().nsmallest(5, columns=0)
leastSTD = list(leastSTD.transpose().columns)# 结合相关性和标准差,得到需要消除的特征集合
featureElimination = set(leastCorrelated + leastSTD)
len(featureElimination)
featureElimination# 根据特征集合,从数据集中删除选定的特征
combined_data_reduced = combined_data.drop(featureElimination,axis=1)# 分离特征和标签,并将数据集划分为训练集和测试集
data_x = combined_data_reduced.drop('attack_type', axis=1)
data_y = combined_data_reduced.loc[:,['attack_type']]
X_train, X_test, y_train, y_test = train_test_split(data_x, data_y, test_size=.5, random_state=42)  # 待完成:说明train_test_split的具体作用和参数意义

{‘dst_bytes’,
‘is_host_login’,
‘land’,
‘logged_in’,
‘num_access_files’,
‘num_compromised’,
‘num_file_creations’,
‘num_outbound_cmds’,
‘num_root’,
‘num_shells’,
‘root_shell’,
‘srv_rerror_rate’,
‘su_attempted’,
‘urgent’}

训练随机森林分类器模型

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from itertools import cyclefrom sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import roc_auc_score
from sklearn import metricsfrom sklearn import linear_modelfrom sklearn.ensemble import VotingClassifierfrom sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import IsolationForestfrom sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifierimport gc 
gc.collect()# 初始化随机森林分类器
RF = RandomForestClassifier(n_estimators=10, criterion='entropy', max_features='auto', bootstrap=True)# 训练模型
RF.fit(X_train, y_train)
# 获取特征重要性
RF_feature = RF.feature_importances_# 在测试集上评估模型性能
rf_score = RF.score(X_test, y_test)
print('RandomForestClassifier processing ,,,')# 多类别问题的二进制化处理
y = preprocessing.label_binarize(y_train, classes=[0, 1, 2, 3])
n_classes = y.shape[1]# 示例:绘制预测模型的ROC曲线
# 生成二分类数据集
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve
from matplotlib import pyplotX, y = make_classification(n_samples=1000, n_classes=2, random_state=1)
# 划分训练集和测试集
trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2)
# 训练模型
model = RandomForestClassifier()
model.fit(trainX, trainy)
# 预测概率
yhat = model.predict_proba(testX)
# 获取正类的概率
pos_probs = yhat[:, 1]
# 绘制无技能的ROC曲线
pyplot.plot([0, 1], [0, 1], linestyle='--', label='No Skill')
# 计算模型的ROC曲线
fpr, tpr, _ = roc_curve(testy, pos_probs)
# 绘制模型的ROC曲线
pyplot.plot(fpr, tpr, marker='_', label='RFC_Performance')
# 添加轴标签
pyplot.xlabel('False Positive Rate')
pyplot.ylabel('True Positive Rate')
# 显示图例
pyplot.legend()
# 显示图形
pyplot.show()

在这里插入图片描述
在这里插入图片描述

优化建议

  1. 特征选择方面,可以尝试更多的特征选择方法,如递归特征消除(RFE)、基于树的特征重要性排序等,寻找最优特征子集。
  2. 超参数调优:针对随机森林分类器,可以通过网格搜索或随机搜索等方式调整n_estimators、max_depth、min_samples_split等超参数,寻找最佳模型配置。
  3. 类别不平衡问题处理:由于实际场景中正常流量可能远大于异常流量,可考虑引入过采样、欠采样或SMOTE等技术平衡各类别样本。
  4. 模型集成:结合AdaBoostClassifier、GradientBoostingClassifier等多种分类器进行集成学习,提高整体预测性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/732604.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity 让角色动起来(动画控制器)

下载素材: 导入后,找到预制体和动画。 新建动画控制器,拖动到预制体的新版动画组件上。 建立动画关系 创建脚本,挂载到预制体上。 using System.Collections; using System.Collections.Generic; using UnityEngine;public c…

Swift SwiftUI 学习笔记 2024

Swift SwiftUI 学习笔记 2024 一、资源 视频资源 StanfordUnivercity 公开课 2023: https://cs193p.sites.stanford.edu/2023 教程 Swift 初识:基础语法:https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour/…

工地安全反光衣穿戴监测报警摄像机

工地安全反光衣穿戴监测报警摄像机是为了提高工地施工人员的安全意识和监管效率而设计的。这种设备结合了反光衣、监测系统和报警摄像机的功能,可以有效减少工地事故的发生。 首先,工地安全反光衣是一种具有高度可见度的服装,能够使穿戴者在夜…

程序如何知道mqtt设备是否在线

在做物联网设备的时候经常会碰到设备的在线与掉线 问题:emqx如何来实现这个在线与掉线 实现:添加一个规则,程序监控这个规则 1、SELECT * FROM "$events/client_connected", "$events/client_disconnected" 2、添加一…

离散数学——(4)

目录 1.主析取范式 2.大项 3.主合区范式 4.范式的求法 真值表法 5.推理理论 直接证法 1.主析取范式 2.大项 3.主合区范式 4.范式的求法 真值表法 5.推理理论 直接证法

【C++】手把手教你模拟实现 vector

目录 一、构造/析构/拷贝 1、构造函数 1️⃣无参的构造函数 2️⃣带参的构造函数 3️⃣类模板的构造函数 2、析构函数 3、拷贝构造 二、修改操作 1、reserve 【错误版本】 🌟【解答】正确版本 2、resize 3、push_back 4、pop_back 5、insert 6、era…

pytorch(六、七)多维特征数据的输入、加载数据集的类

文章目录 多维特征数据的输入代码 加载数据集概念np.loadtxt()读取数据dataloadertorchvision获取数据集代码 三种梯度下降批量梯度下降BGD随机梯度下降SGD小批量随机梯度下降MBGD代码 多维特征数据的输入 对于一个多维数据,其行表示一个样本,列表示样本…

基于Java的社区买菜系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 数据中心模块2.1.2 菜品分类模块2.1.3 菜品档案模块2.1.4 菜品订单模块2.1.5 菜品收藏模块2.1.6 收货地址模块 2.2 可行性分析2.3 用例分析2.4 实体类设计2.4.1 菜品分类模块2.4.2 菜品档案模块2.4.3…

Linux内存映射

目录 背景 一、什么是内存映射? 二、mman函数 1.权限问题 2.总线错误 3.内存权限 4.读文件内容 5.映射与文件 6.非法参数错误 7.偏移量大小 8.映射内存大小 8.1 申请6k,访问5k 8.2 申请2k,访问3k 8.3 返回值检查 三、内存映射实现 四…

SSH移植到BusyBox

手动编译SSH安装挺麻烦的,本文主要是我大量借鉴和实践总结出来的流程,一步一按照做不会有太大问题。 移植平台:IMX6UL(迅为开发板) 根文件系统:BusyBox 所有操作都建议不要在root账户下运行,并且make install的安装路…

【Python】专栏文章索引

为了方便 快速定位 和 便于文章间的相互引用等 作为一个快速准确的导航工具 Python 目录: (一)装饰器函数 (二)牛客网—软件开发-Python专项练习 (三)装饰器函数 (四&#xff0…

【深度学习】自动求导中有时为什么要先sum()再backward()

创作日志: 在看李沐学深度学习,“深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和”,对这句话一知半解,自己动手推导一下。 一、理解 在深度学习中,被求导的对…

CSS的盒子模型:掌握网页设计的基石!

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux的进程调度实现

经常被问到进程的调度算法有哪些,什么先进先出、短进程优先、时间片轮转、多级反馈多列等等算法能说一大堆?那具体的,linux内核使用了什么样的算法,且来探究一下。 本文所引用源码基于linux内核2.6.34版本。 目录 调度器类 从 s…

探索 PostgreSQL 的高级数据类型 - 第 1 部分

数组和枚举 PostgreSQL 因其可扩展性和多功能性而备受欢迎,除了传统的整数和字符串之外,它还提供了多种数据类型。其中,包括数组和枚举,其为开发者提供了高级的数据建模能力。本文中,我们将深入研究这些复杂的数据类型…

Unity中PICO实现 隔空取物 和 接触抓取物体

文章目录 前言一、隔空取物1、XR Grab Interactable2、调节扔出去时的相关系数3、用手柄射线指向需要抓取的物体后,按下侧边扳机键即可抓取 二、接触抓取物体1、替换手柄上抓取物体的脚本2、在手柄上添加 接触抓取物体的脚本3、在手柄上添加碰撞盒触发器4、在需要抓…

PHAMB: 病毒数据分箱

Genome binning of viral entities from bulk metagenomics data | Nature Communications 安装 ### New dependencies *Recommended* conda install -c conda-forge mamba mamba create -n phamb python3.9 conda activate phamb mamba install -c conda-forge -c biocond…

IOS降级后从高版本到低版本恢复备份

IOS降级后从高版本到低版本恢复备份 此方法只适用于小版本还原,比如17.4->17.3,未验证大版本恢复可行性手机型号:iphone 13pro 系统版本:17.4 降级版本:17.3.1 步骤 通过itunes或者MacOS系统下对当前版本进行备份…

基于ThinkPHP框架的校园一卡通系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 框架技术 3 1.1.1 Bootstrap 3 1.1.2 ThinkPHP框架 3 1.2 前端技术 4 1.2.1 JavaScript 4 1.2.2 ECharts 4 1.3 B/S架构 4 1.4 数据库技术 5 1.4.1 MySQL 5 1.5 本章小结 6 2 系统分析 7 2.1 功能需求分析 7 2.2 非功能需…

202441读书笔记|《笠翁对韵》—— 金菡萏,玉芙蓉,酒晕微酡琼杏颊,香尘浅印玉莲双

202441读书笔记|《笠翁对韵》——金菡萏,玉芙蓉,酒晕微酡琼杏颊,香尘浅印玉莲双 《作家榜名著:笠翁对韵》作者李渔,霍俊明。是所有词句都有注音的一本书,轻松学不认识的字,非常朗朗上口的对偶词…