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攻擊的效果都不錯。