特征选取
在所给的数据集上,将每个特征的数据映射称为一组数字,相同的标称型映射为相同的数,并进行相关性分析,即可得到各特征的相关性表.
操作 | 网络协议 | 备用字符串5 | 目的端口 | 网络应用协议 | 备用字符串6 | |
---|---|---|---|---|---|---|
事件类型 | 0.52 | 0.35 | 0.39 | -0.44 | 0.44 | 0.18 |
在特征选取的过程当中,攻击行为与设备IP相关性很高。但在现实当中,设备IP显然不是一个有效特征,因为每台设备都有被攻击的风险。假如某台服务器十分重要,那么我们自然应该给这台设备增强防护,提高模型中判断行为性质的阈值。当然还有很多特征和设备有关,所以我在这儿不一一列举。
所以我选择了一些关于网络访问行为中产生的数据作为主要特征,就是表1中所选取的。操作行为与事件类型相关度高达0.52,因为在网络攻击中,大多需要上传、执行等操作;网络协议和网络应用协议这两个特征的相关度也很高,因为很多攻击是基于网络协议漏洞进行,所以某种特定系列攻击与协议类型高度相关,在后续的实验当中,发现网络应用协议和网络协议两者取一即可,并根据模型收敛速度,选择了网络应用协议;目的端口决定了访问服务的功能,而某些特定服务才是攻击者攻击的目标;备用字符串6是访问者IP所在地,备用字符串5是网络行为类型,访问者IP所在地主要考虑到国外攻击,而网络行为类型也和操作行为类似,但是在后续的实验当中发现这两个特征对模型性能的影响微乎其微,所以不选他们.
最后,经过实验分析,选定了操作,网络应用协议,目的端口三个特征.
BP算法
BP神经网络
BP神经网络模型是在当前人工神经网络基础上使用梯度下降优化算法进行数据集训练,是目前应用最广泛的模型之一.相比于其他神经网络模型,其网络更加成熟,结构更简单,分为输入层,隐藏层和输出层三个部分.
Dropout正则化方法
Dropout正则化是神经网络当中常用的避免模型过拟合的方法。Dropout正则化方法是将隐藏层的 N 个神经元在每次训练的迭代过程中, 以概率P (一般P=0.5) 随机暂时删除部分神经元, 用余下的 (1-P) * N 个神经元所构成的网络进行训练。
节点的随机丢弃首先是根据定义好的概率P进行选择要删除的节点,强制将其激活值置为0,根据概率P生成二项分布的向量 (由0和1构成),0表示节点被暂时删除,连接断开,1表示节点被保留,将向量q^(n) 与上层的输出q^(n )相乘得到x1^(n)作为这层的输入, 用于BP神经网络的训练,达到随机丢弃的效果.
模型结构
在本次实验中所建立的模型是Dropout正则化改进后的bp神经网络,两层全连接层,一层Dropout层,模型信息如下:
(fc1): Linear(in_features=1842, out_features=128, bias=True)
(drop): Dropout(p=0.4, inplace=False)
(fc2): sigmoid(Linear(in_features=128, out_features=2, bias=True))
KMeans算法
k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
模拟实验与结果分析
one-hot编码
One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效.One-Hot编码是分类变量作为二进制向量的表示.这首先要求将分类值映射到整数值.然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1.
数据预处理
在处理所选特征时,均采用one-hot编码.例如在处理目的端口时,端口号并非是越大或者越小好,而是某个特定值对结果判断影响很大.假如直接使用端口号作为数据直接输入,模型的学习情况将会非常糟糕。
数据处理完后,数据维度展开到1842维,虽然相比于原数据展开的非常大,但是对于神经网络来说,数据量不算很大.
实验过程及结果分析
使用FaceBook开源数据流引擎Pytorch验证BP神经网络算法效果,Pytorch支持在多种平台上运行,如CPU,GPU或Android设备,符合实验要求.
本实验使用BP神经网络进行仿真实验,数据集70%作为训练集,30%作为验证集.在BP神经网络上进行两次实验,每次实验迭代50次.使用训练集训练模型,并在验证集上评估实验性能.
从图 2 可以看到,模型在训练时的损失值下降得很快,在大概30个epoch时就已经趋于平稳.而从图 1 可以看到模型的准确度在大概20个epoch时就已经趋于平稳,准确率高达96%.但在训练到50个epoch时达到顶峰,高达99%.而在测试集上,模型的泛化能力也表现得很优秀,在每个batch(32个)上,模型预测的准确率也平均在99%以上.
KMeans算法采用Python第三方模块sklearn中内置的KMeans算法,数据集也根据上述方法进行数据处理,并分为两类进行迭代,最终获得的结果平均准确率约为34%左右.但因为是二分类问题,所以标签可以互换,实际上模型的准确率约为66%.我认为主要是该数据集在高维空间上表现为类内不紧致,类间不分散所致。所以需要进一步得非线性变换,使其在更高的维度上相同类别聚集成簇.
神经网络模型的准确率远超KMeans算法模型,而且算法的稳定性良好,在数据集上的表现十分优秀。我认为主要是因为,神经网络模型当中有很多非线性的计算,使得在有监督的学习下,数据集在高维空间下进行非线性变换,从而可以将其线性分类.
代码detection.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch.utils
from sklearn.cluster import KMeans
file_name = "event3.csv"
LR = 0.0001
Epoch = 50
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(1799,12)
self.drop = nn.Dropout(0.4)
self.fc2 = nn.Linear(12,2)
def forward(self, x):
x = self.drop(torch.sigmoid(self.fc1(x)))
x = torch.sigmoid(self.fc2(x))
return x
def WashData(RawData):
Data = pd.DataFrame()
Label = pd.DataFrame()
Label["事件类型"] = RawData["事件类型"].map(lambda x: 1 if x == "/网络访问" else 0)
#print(Label["事件类型"].value_counts())
#print(RawData["操作"].value_counts())
Data = pd.get_dummies(RawData["操作"])
#RawData["备用字符串6"] = RawData["备用字符串6"].map(lambda x: "其他地方" if x == " " else x)
#print(RawData["备用字符串6"].value_counts())
#Data = Data.join(pd.get_dummies(RawData["备用字符串6"]))
RawData['网络应用协议'] = RawData['网络应用协议'].map(lambda x: "others" if x == "unknown" else x)
#print(RawData['网络应用协议'].value_counts())
Data = Data.join(pd.get_dummies(RawData["网络应用协议"]))
#print(RawData['备用字符串5'].value_counts())
#Data = Data.join(pd.get_dummies(RawData["备用字符串5"]))
#print(RawData["网络协议"].value_counts())
#Data = Data.join(pd.get_dummies(RawData["网络协议"]))
#print(RawData["目的端口"].value_counts())
Data = Data.join(pd.get_dummies(RawData["目的端口"]))
#print(RawData["请求内容"].value_counts())
return np.array(Data,dtype=np.float32),np.array(Label)
def LoadData(file_name):
RawData = pd.read_csv(file_name)
Data,Label = WashData(RawData)
return Data,Label
def train(train_loader):
device = torch.device('cuda:0' if torch.cuda.is_available() else "cpu")
AllLoss = []
AllAccuracy = []
net = Net()
net = net.to(device)
for m in net.modules():
if isinstance(m,nn.Linear):
nn.init.normal_(m.weight)
optimizer = optim.Adam(net.parameters(), lr=LR, betas=(0.9, 0.99))
criterion = nn.CrossEntropyLoss()
for epoch in range(Epoch):
running_loss = 0.0
correct = 0
total = 0
for i,data in enumerate(train_loader,0):
inputs,labels = data
inputs,labels = inputs.to(device),labels.to(device)
optimizer.zero_grad()
outputs = net(inputs)
_,predicted = torch.max(outputs.data,1)
total += labels.size(0)
correct += (predicted == labels.squeeze()).sum()
loss = criterion(outputs,labels.long().squeeze())
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print('[%d,%5d] loss:%.3f accuracy:%.3f %%'%(epoch + 1,(epoch + 1)*2000,running_loss/2000,100*correct/total))
AllLoss.append(running_loss/2000)
AllAccuracy.append(100*correct/total)
running_loss = 0.0
print("Finished Training")
torch.save(net.state_dict(), './net_params.pkl')
np.savetxt('loss.txt',np.array(AllLoss))
np.savetxt('accuracy.txt', np.array(AllAccuracy))
def test(test_loader):
device = torch.device('cuda:0' if torch.cuda.is_available() else "cpu")
net = Net()
net.load_state_dict(torch.load('./net_params.pkl'))
net = net.to(device)
torch.no_grad()
correct = 0
total = 0
for i, data in enumerate(test_loader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
outputs = net(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels.squeeze()).sum()
print('Batch:%d accuracy:%.3f %%'%(i,100*correct/total))
def UseKMeans(Data,Label):
y_pred = KMeans(n_clusters=2, random_state=9).fit_predict(Data)
print(y_pred)
Label = Label.reshape((len(Label)))
Acc = 1 - sum((Label - y_pred) ** 2) / len(y_pred)
return Acc
if __name__ == '__main__':
Data, Label = LoadData(file_name)
DataSize = len(Data)
TrainSize = int(0.7 * DataSize)
train_dataset, test_dataset = torch.from_numpy(Data[:TrainSize, ]), torch.from_numpy(Data[TrainSize:, ])
train_label, test_label = torch.from_numpy(Label[:TrainSize, ]), torch.from_numpy(Label[TrainSize:, ])
#print(train_dataset.shape,train_label.shape)
#print(test_dataset.shape, test_label.shape)
#'''
TrainDataset = torch.utils.data.TensorDataset(train_dataset, train_label)
TestDataset = torch.utils.data.TensorDataset(test_dataset, test_label)
train_loader = torch.utils.data.DataLoader(TrainDataset, batch_size=32, shuffle=False, num_workers=2)
test_loader = torch.utils.data.DataLoader(TestDataset, batch_size=100, shuffle=False, num_workers=2)
train(train_loader)
test(test_loader)
#'''
# Acc = UseKMeans(Data, Label)
# print(Data.shape, Label.shape)
代码Plot.py
import matplotlib.pyplot as plt
import numpy as np
def Load_Data():
loss = np.loadtxt("loss.txt")
acc = np.loadtxt("accuracy.txt")
return loss,acc
if __name__ == "__main__":
lost,acc = Load_Data()
plt.plot(range(len(lost)),lost)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()
plt.plot(range(len(acc)), acc)
plt.xlabel("epoch")
plt.ylabel("accuracy")
plt.show()