Web安全之機器學習 | 樸素貝葉斯算法

1、樸素貝葉斯算法概述

貝葉斯分類是一系列分類算法的總稱,這類算法均以貝葉斯定理爲基礎,故統稱爲貝葉斯分類。其中樸素貝葉斯(Naive Bayesian,NB)是其中應用最廣泛的分類算法之一。通常企業和大型郵件服務商都會提供攔截垃圾的功能,最常見的一種算法就是基於樸素貝葉斯的文本分類算法,大體思路是通過學習大量的垃圾郵件和正常郵件樣本,讓樸素貝葉斯訓練出文本分類模型。

NB算法是基於貝葉斯定理與特徵條件獨立假設的分類方法。NB基於一個簡單的假定:給定目標值時屬性之間相互條件獨立。

NB包括以下算法:

高斯樸素貝葉斯(Gaussian Naive Bayes)、多項式樸素貝葉斯(Multinomial Naive Bayes)、伯努利樸素貝葉斯(Bernoulli Naive Bayes)

2、示例:樸素貝葉斯應用


from sklearn import datasets
from sklearn.naive_bayes import GaussianNB

# 導入數據集
iris = datasets.load_iris()
# 訓練數據集
gnb = GaussianNB()
# 驗證結果
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print(iris.target)
print(y_pred)
print("Number of mislabeled points out of a total %d points : %d" % (iris.data.shape[0],(iris.target != y_pred).sum()))

3、示例:檢測WebShell(一)

基於Webshell的文本特徵進行WebShell的檢測,將在互聯網上搜集到的Webshell作爲黑樣本,當前最新的wordpress源碼作爲白樣本。將一個PHP文件作爲一個字符串處理,以基於單詞2-gram切割,遍歷全部文件形成基於2-gram的詞彙表。然後進一步將每個PHP文件向量化。

import os
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB

# 將PHP文件轉換成一個字符串
def load_file(file_path):
    t=""
    with open(file_path ,encoding='utf-8') as f:
        for line in f:
            line = line.strip('\n')
            t+=line
    return t

# 遍歷樣本集合,將全部文件以字符串的形式加載
def load_files(path):
    files_list=[]
    for r, d, files in os.walk(path):
        for file in files:
            if file.endswith('.php'):
                file_path=path+file
                print("Load %s" % file_path)
                t=load_file(file_path)
                files_list.append(t)
    return  files_list



if __name__ == '__main__':

    #bigram_vectorizer = CountVectorizer(ngram_range=(2, 2),token_pattern = r'\b\w+\b', min_df = 1)
    # 對黑樣本集合,以2-gram算法生成全局的詞彙表,其中2-gram基於單詞切割,設置token的切割方法爲r'\b\w+\b
    # ngram_range設置爲(2,2)表明基於2-gram;
    # decode_error設置爲ignore表明忽視異常字符的影響;
    # token_pattern設置爲r'\b\w+\b'表明按照單詞切割。
    webshell_bigram_vectorizer = CountVectorizer(ngram_range=(2, 2), decode_error="ignore",
                                        token_pattern = r'\b\w+\b',min_df=1)
    webshell_files_list=load_files("PHP-WEBSHELL/xiaoma/")
    x1=webshell_bigram_vectorizer.fit_transform(webshell_files_list).toarray()
    y1=[1]*len(x1)
    vocabulary=webshell_bigram_vectorizer.vocabulary_

    # 設置CountVectorizer函數的vocabulary,讓黑樣本生成的詞彙表來進行向量化
    wp_bigram_vectorizer = CountVectorizer(ngram_range=(2, 2), decode_error="ignore",
                                        token_pattern = r'\b\w+\b',min_df=1,vocabulary=vocabulary)
    wp_files_list=load_files("wordpress/")
    x2=wp_bigram_vectorizer.fit_transform(wp_files_list).toarray()
    y2=[0]*len(x2)

    x=np.concatenate((x1,x2))
    y=np.concatenate((y1, y2))

    # 訓練樣本
    clf = GaussianNB()
    # 使用三折交叉驗證
    scores = cross_val_score(clf, x, y, n_jobs=-1,cv=3)
    print(scores)
    print(scores.mean())

測試結果顯示準確率約80%。

[0.79166667 0.76595745 0.82608696]
0.7945703566656389

(k折交叉驗證,就是將數據集合a分爲訓練集b和測試集c,在樣本量不充足的情況下,爲了充分利用數據集對算法效果進行測試,將數據集a隨機分爲k個包,每次將其中一個包作爲測試集,剩下k-1個包作爲訓練集進行訓練集。)

4、示例:檢測WebShell(二)

WebShell的一系列管理功能本質上是一系列函數調用,嘗試針對函數調用建立特徵。

if __name__ == '__main__':

 
    # 對黑樣本集合,以1-gram算法生成全局的詞彙表,其中1-gram基於函數和字符串常量進行切割,設置token的切割方法爲r'\b\w+\b\
    # ˄|\'\w+\''
    # ngram_range設置爲(1,1)表明基於1-gram;
    webshell_bigram_vectorizer = CountVectorizer(ngram_range=(1, 1), decode_error="ignore",
                                        token_pattern = r'\b\w+\b\(|\'\w+\'',min_df=1)
    webshell_files_list=load_files("PHP-WEBSHELL/xiaoma/")
    x1=webshell_bigram_vectorizer.fit_transform(webshell_files_list).toarray()
    y1=[1]*len(x1)
    vocabulary=webshell_bigram_vectorizer.vocabulary_

    # 使用黑樣本生成的詞彙表vocabulary,將白樣本特徵化
    wp_bigram_vectorizer = CountVectorizer(ngram_range=(1, 1), decode_error="ignore",
                                        token_pattern = r'\b\w+\b\(|\'\w+\'',min_df=1,vocabulary=vocabulary)
    wp_files_list=load_files("wordpress/")
    x2=wp_bigram_vectorizer.transform(wp_files_list).toarray()
    #print x2
    y2=[0]*len(x2)

    x=np.concatenate((x1,x2))
    y=np.concatenate((y1, y2))

    clf = GaussianNB()
    print(vocabulary)
    scores = cross_val_score(clf, x, y, n_jobs=-1,cv=3)
    print(scores)
    print(scores.mean())

測試結果準確率約96%:

[0.9375     0.9787234  0.97826087]
0.9648280912735121

5、示例:識別驗證碼

 MNIST是一個入門級的計算機視覺數據集,它包含各種手寫數字圖片,也包含每一張圖片對應的標籤,告訴我們這個數字是幾。

使用樸素貝葉斯識別MNIST組成的驗證碼:


from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB

import pickle
import gzip


def load_data():
    # 使用MNIST離線版數據
    with gzip.open('MNIST/mnist.pkl.gz') as fp:
        print(fp)
        training_data, valid_data, test_data = pickle.load(fp,encoding='bytes')
    return training_data, valid_data, test_data


if __name__ == '__main__':

    # MNIST已經將24x24的圖片特徵化成長度爲784一維向量
    # 使用NB訓練
    training_data, valid_data, test_data=load_data()
    x1,y1=training_data
    x2,y2=test_data
    clf = GaussianNB()
    clf.fit(x1, y1)
    score = cross_val_score(clf, x2, y2, scoring="accuracy")
    print(score)
    print(score.mean())

測試結果準確率約50%左右,效果不理想。一般NB算法在非黑即白的二分類問題上使用廣泛,但在多分類問題上表現不如其他算法。

[0.53684841 0.58385839 0.6043857 ]
0.575030833157769

如果遇到以下報錯:

Traceback (most recent call last):
  File "D:/Python3項目/machine_learning/7.6.py", line 21, in <module>
    training_data, valid_data, test_data=load_data()
  File "D:/Python3項目/machine_learning/7.6.py", line 13, in load_data
    training_data, valid_data, test_data = pickle.load(fp)
UnicodeDecodeError: 'ascii' codec can't decode byte 0x90 in position 614: ordinal not in range(128)

training_data, valid_data, test_data = pickle.load(fp)

改爲:

training_data, valid_data, test_data = pickle.load(fp,encoding='bytes')

另外還可以使用樸素貝葉斯檢測DGA域名和檢測針對Apache的DDos攻擊的效果都不錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章