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()))

Web安全之机器学习 | 朴素贝叶斯算法_第1张图片

3、示例:检测WebShell(一)

基于Webshell的文本特征进行WebShell的检测,将在互联网上搜集到的Webshell作为黑样本,当前最新的wordpress源码作为白样本。将一个PHP文件作为一个字符串处理,以基于单词2-gram切割,遍历全部文件形成基于2-gram的词汇表。然后进一步将每个PHP文件向量化。

Web安全之机器学习 | 朴素贝叶斯算法_第2张图片

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 
    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攻击的效果都不错。

你可能感兴趣的:(机器学习,朴素贝叶斯)