基于机器学习的网络入侵检测与特征选择及随机森林分类器性能评估(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 cycle

from 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 metrics

from sklearn import linear_model

from sklearn.ensemble import VotingClassifier

from 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 IsolationForest

from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier

import 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 pyplot

X, 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等多种分类器进行集成学习,提高整体预测性能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

问答系统设计:核心架构解析

在近几年中,问答回答(QA)应用的快速发展彻底改变了我们获取信息的方式。无论是在搜索引擎、聊天机器人,还是在从大量主题数据中检索相关信息的应用程序中,QA应用的身影无处不在。 简而言之,QA应用的主要目的是在文本段落中找到对特定问题最合适的答案。早期的一些方法包…

【考研数学】129高分学姐二战经验+资料分享

21年数学三87分 22年数学三129分 可以说这两年该踩的雷我都踩了、该做的题我都做了。 进来看看是什么使我突然醒悟让我数学提分40多分的叭。 李林的880题我也做过,先来说说这本书的优缺点以及适用人群吧。 习题优点 李林老师的880题难度适中,很贴近…

Day01-项目介绍及初始化-登录页面(test)

1.人力资源项目介绍 1.1 项目架构和解决方案 1.2 课程安排 1.3 课程具备能力 1.4 课程地址 vue-element-admin文档地址:链接演示地址: 链接人力资源项目演示地址: 链接 2. 拉取项目基础代码 拉取命令 $ git clone https://github.com/P…

VS2017 boost环境配置与报错解决

1、下载Boost 2、boost编译 将下载好的压缩包文件解压,我这里放到了D:\Qt文件夹内 按win键找到 vs2017(主要看你的vs是什么版本)的x86_x64兼容工具命令提示符 输入以下命令: 首先进入到解压的boost文件夹,复制一下前面解压的路径 cd D:\Qt\boost_1_78_0然后输入命令,…

【Python】牛客网—软件开发-Python专项练习(day1)

1.(单选)下面哪个是Python中不可变的数据结构? A.set B.list C.tuple D.dict 可变数据类型:列表list[ ]、字典dict{ }、集合set{ }(能查询,也可更改)数据发生改变,但内存地址不变 不…

【kubernetes】关于k8s集群中的ingress规则案例

目录 一、k8s 对外服务之 Ingress 1.1什么是ingress 1.2外部的应用能够访问集群内的服务有哪些方案? 1.3Ingress 组成 1.4Ingress-Nginx 工作原理 1.5ingress 暴露服务的方式 二、实操ingress暴露服务 前期.部署 nginx-ingress-controller 2.1基于host网络…

海翔ERP getylist_login.do接口存在sql注入漏洞

@[toc] 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 海翔ERP 简介 微信公众号搜索:南风漏洞复…

什么是ETL?什么是ELT?怎么区分它们使用场景

在大数据处理的领域中,ETL和ELT是两个经常被数据工程师提到的工具,而有很多数据工程师对这两种工具的区别和使用和定位有一定的模糊,其实它们分别代表了两种不同的数据集成方法。尽管这两种方法看起来都是从源系统提取数据,转换数…

常见BUG如何在测试过程中分析定位

前言 在测试的日常工作中,相信经常有测试的小伙伴遇到类似的情况:在项目上线时,只要出现问题(bug),就很容易成为“背锅侠”。 软件测试人员在工作中是无法避免的要和开发人员和产品经理打交道的&#xff…

第14章 西瓜书——概率图模型

概率图模型 概率图模型(Probabilistic Graphical Model)是用图结构来表示多元随机变量之间条件依赖关系的模型。在图模型中,节点表示随机变量,边表示变量之间的依赖关系。概率图模型可以分为有向图模型(如贝叶斯网络&a…

【XMU学科实践二】豆瓣爬虫实践

文章目录 分析豆瓣阅读网站具体步骤构造headersBeautiful soup中的定位函数find() 、find_all() 完整爬虫代码 叠甲:仅供学习。。 XMU的小朋友实在不会了可以参考我的思路,但还是建议自己敲一遍哈。 学科实践二还是挺有意思的! 分析豆瓣阅读网…

人才推荐 | 毕业于美国凯斯西储大学的博士,专业知识广泛

编辑 / 木子 审核 / 朝阳 伟骅英才 伟骅英才致力于以大数据、区块链、AI人工智能等前沿技术打造开放的人力资本生态,用科技解决职业领域问题,提升行业数字化服务水平,提供创新型的产业与人才一体化服务的人力资源解决方案和示范平台&#x…

前端实现生成图片并批量下载,下载成果物是zip包

简介 项目上有个需求,需要根据表单填写一些信息,来生成定制的二维码图片,并且支持批量下载二维码图片。 之前的实现方式是直接后端生成二维码图片,点击下载时后端直接返回一个zip包即可。但是项目经理说后端实现方式每次改个东西…

Qt 自绘进度条 QProgressBar使用

文章目录 效果图控件介绍绘制函数总结 效果图 控件介绍 QProgressBar是Qt框架中提供的一个控件,用于在界面上显示任务的进度。它通常用于向用户展示一个操作完成的百分比,比如文件复制、数据加载等操作的进度。 QProgressBar的主要特性: 范…

BUUCTF----[极客大挑战 2019]HardSQL

输入1’ 单引号闭合 进行永真式判断 竟然说我是臭弟弟----八嘎(肯定是进行了过滤) 经过手法判断,过滤了,空格,and等报错注入updatexml() 报错注入顾名思义就是,通过特殊函数错误使用并使其输出错误结果来获…

实现鼠标移动el-select下拉框的label上面显示出table悬浮窗

首先是对vue代码 实现思路就是在el-option里面放一个span来包裹el-popover&#xff0c;里面在放tabe实现悬浮表格 <el-form-item label"原理图编号"><el-select v-model"data.number" placeholder"请选择" clearable multiple collaps…

操作系统笔记(进程)

注&#xff1a; 下面图片资源来源于 王道计算机考研 操作系统 1.进程概念 进程&#xff08;process&#xff09;&#xff1a;是动态的&#xff0c;是程序的一次执行过程&#xff08;同一程序多次执行&#xff0c;会产生多个进程&#xff09;程序&#xff1a;是静态的&…

ChatGPT提示技巧:种子词提示

ChatGPT提示技巧&#xff1a;种子词提示 种子词提示是一种通过提供特定种子词或短语来控制 ChatGPT 输出的技术。 种子词提示符的提示公式是种子词或短语&#xff0c;然后是指令 “请根据以下种子词生成文本”。 示例&#xff1a; 文本生成&#xff1a; 任务&#xff1a; …

MVC,MVP的对比(附代码)一次搞懂!

首先看下我们的页面 一个edittext&#xff0c;一个获取用户信息的button&#xff0c;一个展示用户信息的textview 实现&#xff1a;点击按钮&#xff0c;根据用户输入的账号&#xff0c;获取账号信息并显示在textview上 现在我们用三种方式实现 &#xff08;1&#xff09;不使…

Unity性能优化篇(十) 模型优化之网格合并 Easy Mesh Combine Tool插件使用以及代码实现网格合并

把多个模型的网格合并为一个网格。可以使用自己写代码&#xff0c;使用Unity自带的CombineMeshes方法&#xff0c;也可以使用资源商店的插件&#xff0c;在资源商店搜Mesh Combine可以搜索到相关的插件&#xff0c;例如Easy Mesh Combine Tool等插件。 可大幅度减少Batches数量…