贝叶斯分类是一系列分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。其中朴素贝叶斯(Naive Bayesian,NB)是其中应用最广泛的分类算法之一。通常企业和大型邮件服务商都会提供拦截垃圾的功能,最常见的一种算法就是基于朴素贝叶斯的文本分类算法,大体思路是通过学习大量的垃圾邮件和正常邮件样本,让朴素贝叶斯训练出文本分类模型。
NB算法是基于贝叶斯定理与特征条件独立假设的分类方法。NB基于一个简单的假定:给定目标值时属性之间相互条件独立。
NB包括以下算法:
高斯朴素贝叶斯(Gaussian Naive Bayes)、多项式朴素贝叶斯(Multinomial Naive Bayes)、伯努利朴素贝叶斯(Bernoulli Naive Bayes)
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()))
基于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个包作为训练集进行训练集。)
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
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
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攻击的效果都不错。