KDD-CUP99 網絡入侵檢測數據集的處理與研究

對於入侵檢測的研究,須要大量有效的實驗數據。數據能夠經過抓包工具來採集,如Unix下的Tcpdump,Windows下的libdump,或者專用的軟件snort捕捉數據包,生成鏈接記錄做爲數據源。本文使用的是基於數據挖掘的入侵檢測技術研究中使用的KDDCup99的網絡入侵檢測數據集。git

原文連接 https://blog.gongyan.me/2017/04/kdd-cup99/ 轉載請註明,有問題歡迎聯繫我gongyanc@outlook.comgithub


1 KDDCup99網絡入侵檢測數據集介紹

該數據集是從一個模擬的美國空軍局域網上採集來的9個星期的網絡鏈接數據,分紅具備標識的訓練數據和未加標識的測試數據。測試數據和訓練數據有着不一樣的機率分佈,測試數據包含了一些未出如今訓練數據中的攻擊類型,這使得入侵檢測更具備現實性。
在訓練數據集中包含了1種正常的標識類型normal和22種訓練攻擊類型,如表1-1所示。另外有14種攻擊僅出如今測試數據集中。算法

表1-1 KDDCup99入侵檢測實驗數據的標識類型sql

標識類型 含義 具體分類標識
Normal 正常記錄 Normal
DOS 拒絕服務攻擊 back、land、neptune、pod、smurf、teardrop
Probing 監視和其餘探測活動 ipsweep、nmap、portsweep、satan
R2L 來自遠程機器的非法訪問 ftp_write、guess_passwd、imap、multihop、phf、spy、warezclient、warezmaster
U2R 普通用戶對本地超級用戶特權的非法訪問 buffer_overflow、loadmodule、perl、rootkit

數據特徵:KDDCup99訓練數據集中每一個鏈接記錄包含了41個固定的特徵屬性和1個類標識,如圖1-1所示,標識用來表示該條鏈接記錄是正常的,或是某個具體的攻擊類型。在41個固定的特徵屬性中,9個特徵屬性爲離散(symbolic)型,其餘均爲連續(continuous)型。apache

2 數據預處理

聚類算法中要使用計算距離的方法對數據進行聚類,而鏈接記錄的固定特徵屬性中有兩種類型的數值:離散型和連續型。對於連續型特徵屬性,各屬性的度量方法不同。通常而言,所用的度量單位越小,變量可能的值域就越大,這樣對聚類結果的影響也越大,即在計算數據間距離時對聚類的影響越大,甚至會出現「大數」吃「小數」的現象。所以爲了不對度量單位選擇的依賴,消除因爲屬性度量的差別對聚類產生的影響,須要對屬性值進行標準化。對於離散型特徵屬性本文中並不做標準化處理,而是放在聚類算法中計算距離時處理。因此數據標準化是針對連續型特徵屬性的。設訓練數據集有n條網絡鏈接記錄,每一個記錄中有22個連續型屬性向量記做Xij(1≤i≤n,11≤j≤41)。對Xij數據預處理分爲兩步:數值標準化和數值歸一化。網絡

表1-4以2秒時間窗口計算的流量特徵app

特徵名 描述 類型
count 過去的2秒內與當前鏈接有着相同的目的地址的鏈接 連續
serror_rate 出現SYN錯誤的鏈接次數 連續
rerror_rate 出現REJ錯誤的鏈接次數 連續
same_srv_rate 創建相同服務的鏈接次數 連續
diff_srv_rate 創建不一樣服務的鏈接次數 連續
srv_count 過去2秒時間內出現和當前鏈接服務相同的鏈接次數 連續
srv_serror_rate 出現SYN錯誤的鏈接次數 連續
srv_rerror_rate 出現REJ錯誤的鏈接次數 連續
srv_diff_host_rate 鏈接不相同主機的次數 連續

2.1 數值標準化

設 $X'_{ij}$ 爲 $X_{ij}$ 數值標準化後的值。ide

$X'_{ij} = \frac{ X_{ij}-AVG_j }{ STAD_j }$工具

$AVG_j = \frac{ 1 }{ n }(X_{1j}+X_{2j}+...+X_{nj})$oop

$STAD_j = \frac{ 1 }{ n }(\lvert X_{1j}-AVG_j \lvert +\lvert X_{2j}-AVG_j \lvert +...+ \lvert X_{nj}-AVG_j \lvert )$

2.2 數值歸一化

設 $X'' _{ij}$爲 $X_{ij}$歸一化後的值。

$ X''_{ij} = \frac{ X'_{ij}-X _{min} } { X_{max} - X_{min} } $

$X_{min} = min{ X'_{ij} }$

$X_{max} = max{ X'_{ij} }$

其中下標變量1<=i<=n, 11<=j<=41

數值歸一化處理過程及歸一化後數據實例如圖2-1

0.0 2.6104176374e-07 0.00105713002195
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
0.0156555772994 0.0 0.0
0.0 0.0 1.0
0.0 0.0352941176471 0.0352941176471
1.0 0.0 0.11
0.0 0.0 0.0
0.0 1

3. 樣本分析

KDD99數據集總共由500萬條記錄構成,它還提供一個10%的訓練子集和測試子集。樣本類別分佈表以下:

標籤 類別 訓練集(10%) 測試集(Corrected)
1 NORMAL 97278 60593
2 PROBE 4107 4166
3 ipsweep 1247 306
4 mscan / 1053
5 nmap 231 84
6 portsweep 1040 354
7 saint / 736
8 satan 1589 1633
9 DOS 391458 229853
10 apache2 / 794
11 back 2203 1098
12 land 21 9
13 mailbomb / 5000
14 neptune 107201 58001
15 pod 264 87
16 processtable / 759
17 smurf 280790 164091
18 teardrop 979 12
19 udpstorm / 2
20 U2R 52 228
21 buffer_overflow 30 22
22 httptunnel / 158
23 loadmodule 9 2
24 perl 3 2
25 ps / 16
26 rootkit 10 13
27 sqlattack / 2
28 xterm / 13
29 R2L 1126 16189
30 ftp_write 8 3
31 guess_passwd 53 4367
32 imap 12 1
33 multihop 7 18
34 named / 17
35 phf 4 2
36 sendmail / 17
37 snmpgetattack / 7741
38 snmpguess / 2406
39 spy 2 /
40 warezclient 1020 /
41 warezmaster 20 1602
42 worm / 2
43 xlock / 9
44 xsnoop / 4
  • 訓練集和測試集分別爲KDD99數據集中的10%訓練樣本和corrected 的測試樣本;
  • 「/」表示該種攻擊類型只在測試集(或訓練集)中出現,而未在訓練集(或測試集)中出現;

如上表,同DARPA98同樣,KDD99將攻擊類型分爲4類,而後又細分爲39小類,每一類表明一種攻擊類型,類型名被標記在訓練數據集每一行記錄的最後一項。
從表中能夠看出,訓練集中共出現了22個攻擊類型,而剩下的17種只在測試集中出現,這樣設計的目的是檢驗分類器模型的泛化能力,對未知攻擊類型的檢測能力是評價入侵檢測。

4 KNN算法

4.1 算法介紹

kNN算法的指導思想是「近朱者赤,近墨者黑」,由你的鄰居來推斷出你的類別。計算步驟以下:

  1. 算距離:給定測試對象,計算它與訓練集中的每一個對象的距離
  2. 找鄰居:圈定距離最近的k個訓練對象,做爲測試對象的近鄰
  3. 作分類:根據這k個近鄰歸屬的主要類別,來對測試對象分類

4.2 距離或類似度的衡量

什麼是合適的距離衡量?距離越近應該意味着這兩個點屬於一個分類的可能性越大。距離衡量包括歐式距離、夾角餘弦等。本實驗使用歐式(Euclidean)距離。

4.3 類別的斷定

投票決定:少數服從多數,近鄰中哪一個類別的點最多就分爲該類。
加權投票法:根據距離的遠近,對近鄰的投票進行加權,距離越近則權重越大(權重爲距離平方的倒數)

4.4 K值的設定

k過小,分類結果易受噪聲點影響;k太大,近鄰中又可能包含太多的其它類別的點。(對距離加權,能夠下降k值設定的影響)
k值一般是採用交叉檢驗來肯定(以k=1爲基準)
經驗規則:k通常低於訓練樣本數的平方根

4.5 斷定方式的選擇

投票法沒有考慮近鄰的距離的遠近,距離更近的近鄰也許更應該決定最終的分類,因此加權投票法更恰當一些。

4.6 衡量距離的選擇

高維度對距離衡量的影響:衆所周知當變量數越多,歐式距離的區分能力就越差。
變量值域對距離的影響:值域越大的變量經常會在距離計算中佔據主導做用,所以應先對變進行標準化。

4.7 數據處理

5 ROC曲線

附錄:源代碼

項目連接

# coding=utf-8
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt


def classify(input_vct, data_set):
    data_set_size = data_set.shape[0]
    diff_mat = np.tile(input_vct, (data_set_size, 1)) - data_set  # 擴充input_vct到與data_set同型並相減
    sq_diff_mat = diff_mat**2  # 矩陣中每一個元素都平方
    distance = sq_diff_mat.sum(axis=1)**0.5  # 每行相加求和並開平方根
    return distance.min(axis=0)  # 返回最小距離


def file2mat(test_filename, para_num):
    """
    將表格存入矩陣,test_filename爲表格路徑,para_num爲存入矩陣的列數
    返回目標矩陣,和矩陣每一行數據的類別
    """
    fr = open(test_filename)
    lines = fr.readlines()
    line_nums = len(lines)
    result_mat = np.zeros((line_nums, para_num))  # 建立line_nums行,para_num列的矩陣
    class_label = []
    for i in range(line_nums):
        line = lines[i].strip()
        item_mat = line.split(',')
        result_mat[i, :] = item_mat[0: para_num]
        class_label.append(item_mat[-1])  # 表格中最後一列正常1異常2的分類存入class_label
    fr.close()
    return result_mat, class_label


def roc(data_set):
    normal = 0
    data_set_size = data_set.shape[1]
    roc_rate = np.zeros((2, data_set_size))
    for i in range(data_set_size):
        if data_set[2][i] == 1:
            normal += 1
    abnormal = data_set_size - normal
    max_dis = data_set[1].max()
    for j in range(1000):
        threshold = max_dis / 1000 * j
        normal1 = 0
        abnormal1 = 0
        for k in range(data_set_size):
            if data_set[1][k] > threshold and data_set[2][k] == 1:
                normal1 += 1
            if data_set[1][k] > threshold and data_set[2][k] == 2:
                abnormal1 += 1
        roc_rate[0][j] = normal1 / normal  # 閾值以上正常點/全體正常的點
        roc_rate[1][j] = abnormal1 / abnormal  # 閾值以上異常點/全體異常點
    return roc_rate


def test(training_filename, test_filename):
    training_mat, training_label = file2mat(training_filename, 32)
    test_mat, test_label = file2mat(test_filename, 32)
    test_size = test_mat.shape[0]
    result = np.zeros((test_size, 3))
    for i in range(test_size):
        result[i] = i + 1, classify(test_mat[i], training_mat), test_label[i]  # 序號, 最小歐氏距離, 測試集數據類別
    result = np.transpose(result)  # 矩陣轉置
    plt.figure(1)
    plt.scatter(result[0], result[1], c=result[2], edgecolors='None', s=1, alpha=1)
    # 圖1 散點圖:橫軸爲序號,縱軸爲最小歐氏距離,點中心顏色根據測試集數據類別而定, 點外圍無顏色,點大小爲最小1,灰度爲最大1
    roc_rate = roc(result)
    plt.figure(2)
    plt.scatter(roc_rate[0], roc_rate[1], edgecolors='None', s=1, alpha=1)
    # 圖2 ROC曲線, 橫軸誤報率,即閾值以上正常點/全體正常的點;縱軸檢測率,即閾值以上異常點/全體異常點
    plt.show()


if __name__ == "__main__":
    test('training.csv', 'test.csv')
相關文章
相關標籤/搜索