环境:
Anaconda3-Spyder、python+keras+pandas+sklearn
数据集介绍
KDDCup99的原始数据来自于1998年的DARPA入侵检测评估项目,所有的网络数据来自于一个模拟的美国空军局域网,网络中加了很多模拟的攻击。实验的训练数据为7周的网络流量,这些网络流量包含有约500万条网络连接;实验的测试数据为2周的网络流量,包含有约200万条网络连接。 对以上的数据集进行处理,形成了一个新的数据集。该数据集用于1999 年举行的KDDCUP 竞赛中,成为著名的KDD99 数据集。虽然年代有些久远,但KDD99数据集仍然是网络入侵检测领域的事实Benckmark,为基于计算智能的网络入侵检测研究奠定基础。
数据集中每个网络连接被标记为正常(normal)或异常(attack),异常类型被细分为4大类共39种攻击类型,其中22种攻击类型出现在训练集中,另有17种未知攻击类型出现在测试集中,这样设计的目的是检验分类器模型的泛化能力,对未知攻击类型的检测能力是评价入侵检测系统好坏的重要指标。4种异常类型如表1所示。
KDDCup99训练数据集中每个连接记录包含了41个固定的特征属性和1个类标识,标识用来表示该条连接记录是正常的,或是某个具体的攻击类型。在41个固定的特征属性中,9个特征属性为离散(symbolic)型,其他均为连续(continuous)型。
属性:
duration,protocol_type,service,flag,src_bytes,dst_bytes,land,wrong_fragment,urgent,ho,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,class
实例:
0,udp,private,SF,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00,normal.
0,udp,private,SF,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00,snmpgetattack.
步骤
(1)实验数据的选取
在实验研究中,使用KDDCup99中的网络入侵检测数据包kddcup_data_10percent做为训练集、corrected做为测试集。kddcup_data_10percent数据包是对kddcup_data数据包(约490万条数据记录)10%的抽样。
(2)选择衡量问题成功的指标
因为该实验是处理的数据是网络流量,输入一条网络流量,要能够预测它所属的类别(39种攻击+normal),所以选择衡量该模型性能的指标为准确率,即正确分类的概率。
(3)确定评估方法
实验选择的数据集有近五十万条网络流量,数据量比较大,所以采用留出验证集来评估,可以使用train_test_split()函数来划分出15%的训练集来充当验证集。
(4)实验数据预处理
下载的KDDCup99数据文件为kddcup.data_10_percent_corrected和corrected。
第一步,用Notepad++打开另存为.txt文件,方便python读取。
第二步,利用python将.txt文件转化为.csv文件(train.csv和test.csv)。(tocsv.py)
第三步,利用python对数据进行预处理,包含数值替换文本、数值归一化和标签独热编码。数值替换文本主要是将每条连接41个特征值中值为字符串的转换为数值形式。数值归一化采用最值归一化。预处理结束变为4个文件(train_x.csv、train_y.csv、test_x.csv、test_y.csv)。(prehandle.py)
(5)搭建模型
搭建一个四层卷积神经网络(卷积层+池化层+全连接层+softmax层)。因为该网络是要判断出网络流量所属哪种类别(39种攻击+normal),属于多分类问题,所以在最后一层使用softmax层。
在编译时,需要指定三个参数。损失函数(loss function)使用categorical_crossentropy(多类对数损失,用于多分类问题)。优化器(optimizer)使用Adadelta。Adadelta在数据量比较大时,运算速度比较快。在训练和测试过程中需要监控的指标(metric),本实验只关心准确度,即正确分类的流量所占的比例,所以选择accuracy。
训练网络,在Keras中是通过调用网络的fit方法来完成——在训练数据上拟合(fit)模型。并在fit函数参数中通过validation_data参数指定验证集。本次实验中,训练集、验证集和测试集如图3所示。
要始终监控训练损失(loss)和验证损失(val_loss),以及训练准确率(acc)和验证准确率(val_acc)。如果发现模型在验证数据上的性能开始下降,那么就出现了过拟合。
下一阶段就要开始正则化和调节模型,以便尽可能地接近理想模型,既不过拟合也不欠拟合。
不断地调节模型(包括添加dropout、增加或减少层数、添加L1/L2正则化、尝试不同的超参数等等)、训练、在验证集上评估、再再次调节模型,然后重复这一过程,直到模型达到最佳性能。
最后的模型及各参数如下
卷积层:输出的维度(卷积滤波器的数量)filters=32;1D卷积窗口的长度kernel_size=3;激活函数使用Relu函数。池化层:采用最大池化,池化窗口大小pool_size=2。全连接层:128个节点,激活函数使用Relu函数。softmax层:40个节点,激活函数使用softmax函数。
该模型的监控训练损失(loss)和验证损失(val_loss),以及训练准确率(acc)和验证准确率(val_acc)可以使用绘图代码绘制出来,如图4和图5所示。
如图4和图5,训练损失每轮都在降低,训练精度每轮都在提升。但验证损失和验证精度并非如此:它们似乎在第12轮达到最佳值。为了防止过拟合,可以在12轮之后停止训练。
当我们对模型较为满意时,就可以在所有可用数据(训练数据+验证数据)上训练,生成最终的模型。此时实验数据如图6所示。
然后进行测试,将测试集(test_x,test_y)传入evaluate函数即可,最后评估一次。
(6)预测
将要进行预测的数据(test_x)传入predict函数即可。
流程图
具体代码
文件格式转换
import pandas as pd
col_names = ["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"] #42个标识
data = pd.read_table("10_percent_corrected.txt",header=None, sep=',',names = col_names)
print(data.head(10))#查看前10行
data.to_csv("10_percent_corrected.csv")#另存为csv文件
数据预处理
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from pandas.core.frame import DataFrame
import numpy as np
def get_total_data(): #定义数值替换文本的函数
data = pd.read_csv('10_percent_corrected.csv',header=None)
#将源文件中3种协议类型转换成数字标识
data[1]=data[1].map({
'tcp':0, 'udp':1, 'icmp':2})
#将源文件中70种网络服务类型转换成数字标识
data[2]=data[2].map({
'aol':0, 'auth':1, 'bgp':2, 'courier':3, 'csnet_ns':4,'ctf':5, 'daytime':6, 'discard'