數(shù)據(jù)來(lái)源:http://www.schonlau.net/網(wǎng)頁(yè)中的Masquerading User Data。其中包含50個(gè)用戶的操作日志,每個(gè)日志包含1500條操作命令,前面5000條是正常的操作,后面的10000條日志中隨即包含有異常操作。具體參考《Web安全機(jī)器學(xué)習(xí)入門》
“專業(yè)、務(wù)實(shí)、高效、創(chuàng)新、把客戶的事當(dāng)成自己的事”是我們每一個(gè)人一直以來(lái)堅(jiān)持追求的企業(yè)文化。 創(chuàng)新互聯(lián)公司是您可以信賴的網(wǎng)站建設(shè)服務(wù)商、專業(yè)的互聯(lián)網(wǎng)服務(wù)提供商! 專注于成都網(wǎng)站建設(shè)、成都做網(wǎng)站、軟件開(kāi)發(fā)、設(shè)計(jì)服務(wù)業(yè)務(wù)。我們始終堅(jiān)持以客戶需求為導(dǎo)向,結(jié)合用戶體驗(yàn)與視覺(jué)傳達(dá),提供有針對(duì)性的項(xiàng)目解決方案,提供專業(yè)性的建議,創(chuàng)新互聯(lián)建站將不斷地超越自我,追逐市場(chǎng),引領(lǐng)市場(chǎng)!
本來(lái)想自己寫的,但是網(wǎng)上資料太多,就沒(méi)必要寫了??聪缕渌罄袑戇^(guò)的就行了:
這兩個(gè)看了,基本上就沒(méi)啥問(wèn)題了
Step 1:隨便選擇一個(gè)user日志,里面每行代表一個(gè)命令。每150個(gè)命令弄成一個(gè)操作序列,保存在列表之中
def load_user(filename):
most_cmd = []
mini_cmd = []
cmd_list = []
cmd_seq = []
# 獲取操作序列
with open(filename, 'r', encoding="utf-8") as f:
cmd = f.readline()
temp = []
cnt = 0
while(cmd):
cmd_list.append(cmd.strip('\n'))
temp.append(cmd.strip('\n'))
cnt = cnt + 1
if(cnt == 150): # 這里不按照書上的分,我這里按照150個(gè)命令為一個(gè)序列,剛好和標(biāo)簽對(duì)上號(hào),因?yàn)闃?biāo)簽只有100個(gè)值
cmd_seq.append(temp)
cnt = 0
temp = []
cmd = f.readline()
Step 2:然后將user日志中所有的命令進(jìn)行統(tǒng)計(jì),統(tǒng)計(jì)出它們最頻繁的50個(gè)命令,以及最不頻繁的50個(gè)命令
# 獲取最頻繁的前50個(gè)命令,獲取最不頻繁的前50個(gè)命令
fdist = sorted(FreqDist(cmd_list).items(),key = operator.itemgetter(1), reverse = True) # 按照出現(xiàn)頻率排序
most_cmd = [ item[0] for item in fdist[:50]]
mini_cmd = [ item[0] for item in fdist[-50:]]
Step 3:特征化。在 Step 1 的操作序列上,我們按一個(gè)操作系列為單元,①統(tǒng)計(jì)其中不重復(fù)的命令個(gè)數(shù)、②最頻繁的10個(gè)命令、③最不頻繁的10個(gè)命令
user_feature = []
for cmd_list in user_cmd_list:
# 獲取每個(gè)序列不重復(fù)命令的個(gè)數(shù)
seq_len = len(set(cmd_list))
# 將每個(gè)序列按照出現(xiàn)頻率由高到低的排列命令
fdist = sorted(FreqDist(cmd_list).items(), key=operator.itemgetter(1), reverse=True)
seq_freq = [item[0] for item in fdist]
# 獲取最頻繁和最不頻繁的前10個(gè)命令
f2 = seq_freq[:10]
f3 = seq_freq[-10:]
Step 4:因?yàn)镵NN只能接收數(shù)值類型輸入。在 Step 4 中,②和③都是字符串的命令,我們需要將其標(biāo)量化。標(biāo)量化的方式:統(tǒng)計(jì)最頻繁使用的50個(gè)命令和最不頻繁使用的50個(gè)命令計(jì)算重合程度
# 計(jì)算重合度
f2 = len(set(f2) & set(user_max_freq))
f3 = len(set(f3) & set(user_min_freq))
# 合并特征:①每個(gè)序列不重復(fù)的命令個(gè)數(shù);②每個(gè)序列最頻繁的前10個(gè)命令和user中最頻繁的50個(gè)命令重合度;
# ③每個(gè)序列最不頻繁的前10個(gè)命令和user中最不頻繁的前50個(gè)命令重合度;
user_feature.append([seq_len, f2, f3])
from nltk.probability import FreqDist # 統(tǒng)計(jì)命令出現(xiàn)頻率
import operator
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
def load_user(filename):
most_cmd = []
mini_cmd = []
cmd_list = []
cmd_seq = []
# 獲取操作序列
with open(filename, 'r', encoding="utf-8") as f:
cmd = f.readline()
temp = []
cnt = 0
while(cmd):
cmd_list.append(cmd.strip('\n'))
temp.append(cmd.strip('\n'))
cnt = cnt + 1
if(cnt == 150): # 這里不按照書上的分,我這里按照150個(gè)命令為一個(gè)序列,剛好和標(biāo)簽對(duì)上號(hào),因?yàn)闃?biāo)簽只有100個(gè)值
cmd_seq.append(temp)
cnt = 0
temp = []
cmd = f.readline()
# 獲取最頻繁的前50個(gè)命令,獲取最不頻繁的前50個(gè)命令
fdist = sorted(FreqDist(cmd_list).items(),key = operator.itemgetter(1), reverse = True) # 按照出現(xiàn)頻率排序
most_cmd = [ item[0] for item in fdist[:50]]
mini_cmd = [ item[0] for item in fdist[-50:]]
return cmd_seq, most_cmd, mini_cmd
def get_user_feature(user_cmd_list, user_max_freq, user_min_freq):
user_feature = []
for cmd_list in user_cmd_list:
# 獲取每個(gè)序列不重復(fù)命令的個(gè)數(shù)
seq_len = len(set(cmd_list))
# 將每個(gè)序列按照出現(xiàn)頻率由高到低的排列命令
fdist = sorted(FreqDist(cmd_list).items(), key=operator.itemgetter(1), reverse=True)
seq_freq = [item[0] for item in fdist]
# 獲取最頻繁和最不頻繁的前10個(gè)命令
f2 = seq_freq[:10]
f3 = seq_freq[-10:]
# 計(jì)算重合度
f2 = len(set(f2) & set(user_max_freq))
f3 = len(set(f3) & set(user_min_freq))
# 合并特征:①每個(gè)序列不重復(fù)的命令個(gè)數(shù);②每個(gè)序列最頻繁的前10個(gè)命令和user中最頻繁的50個(gè)命令重合度;③每個(gè)序列最不頻繁的前10個(gè)命令和user中最不頻繁的前50個(gè)命令重合度;
user_feature.append([seq_len, f2, f3])
return user_feature
def get_labels(filename): # 獲取第三列的標(biāo)簽
labels = []
cnt = 0
with open(filename, 'r', encoding="utf-8") as f:
temp = f.readline().strip('\n')
while(temp):
labels.append(int(temp[4]))
cnt += 1
temp = f.readline().strip('\n')
return labels
if __name__ == "__main__":
user_cmd_list, user_max_freq, user_min_freq = load_user('user.txt')
user_feature = get_user_feature(user_cmd_list, user_max_freq, user_min_freq)
labels = get_labels('labels.txt')
# 切割數(shù)據(jù)集:訓(xùn)練集和測(cè)試集
x_train = user_feature[0:70]
y_train = labels[0:70]
x_test = user_feature[70:]
y_test = labels[70:]
# 訓(xùn)練數(shù)據(jù)
neight = KNeighborsClassifier(n_neighbors=3)
neight.fit(x_train, y_train)
# 預(yù)測(cè)
y_predict = neight.predict(x_test)
# 計(jì)算得分
score = np.mean(y_test == y_predict) * 100
print(score) # 90.0
最終獲得90%的正確率。
①獲取最頻繁的前50個(gè)命令,書上的方式獲取的并不是最頻繁的前50個(gè)。在這里我改了下代碼。②標(biāo)簽和數(shù)據(jù)對(duì)不上號(hào),命令共有15000個(gè),標(biāo)簽只有100個(gè)。書上的做法是每100個(gè)為一個(gè)操作序列,也就是有150個(gè)操作序列,然后在標(biāo)簽出再前面增加了50個(gè)標(biāo)簽。我的代碼是將150個(gè)命令作為一個(gè)序列,這樣下來(lái)剛好合適。
最后推薦下個(gè)人博客:https://unihac.github.io/