程序设计-在校整理-07 基于机器学习算法的DGA域名识别(NB、XGboost、MLP初探)

一、课题内容和要求

在网络发展如此迅速的现代社会,僵尸网络逐渐成为威胁网络安全的主要原因之一,而僵尸网络大量存在且不易被处理的重要技术组成部分之一就是“域名生成算法”的发明,即DGA域名。为了能够更好的识别网络中存在的恶意DGA域名,本文将研究基于机器学习相关算法的DGA域名识别研究与相关算法实现效果,通过N-Gram特征值与TEXT特征值的提取,运用多种机器学习算法,如:朴素贝叶斯;XGboost以及MLP在该方向上的探索,并在此基础上根据模型不同从而进行识别对比。

二、理论基础

2.1 DGA域名生成算法

随着网络的应用于WEB技术的快速发展,鉴于网络环境过于复杂,相关部门及对其监管难度大。近几年,恶意软件的数量和软件本身的复杂度都在持有增长的态势。由DGA域名算法产生的各类域名可以用于僵尸网络的产生,其可以提供于分布式平台,用于对目标发起DDOS攻击,恶意软件传播与网络欺诈等。本小节将对该算法的生成原理进行相关介绍。

2.2 DGA算法原理

DGA每天可以生成成千上万的恶意域名,但仅选择一小部分作为后续的攻击域名,相对于传统硬编码的恶意域名,更难检测。目前,按照生成的算法分类,DGA算法主要分类如下:
(1) 基于算术(Arithmetic-based)的DGA。
该原理较多的是通过计算一系列的数值,然后将这些数值按照一定的ASCII码进行划分,并且其根据ASCII码可以直接进行域名的生成。此算法目前流行度更高,使用较多。此外,在该方法下,这些值可以被作为偏移值,指向在DGA域名硬编码的字符表中的某一个字符,将其进行对应,从而进行域名的生成。目前,大部分DGA都属于这一类。
(2) 基于哈希(Hash-based)的DGA。
在这个方法下,常常使用十六进制表示的哈希值来生成DGA域名。这些DGA域名,在相应生成算法中大多使用SHA256和MD5两种哈希值进行相应生成操作,但是目前也有将“加盐”操作使用在DGA域名生成过程中的,这使得识别难度加大,DGA域名隐藏效果更好。
(3) 基于单词表(Wordlist-based)的DGA。
此实现方法,是从一个或多个单词表,专有词典中选择一些单词,然后将其进行连接后生成一个DGA域名,可以减少域名字符上的随机性,这样的DGA域名更具有迷惑性,字典内嵌可以在恶意程序中或者从公有服务中提取。但此算法需要的生成集较大,且随机生成时,相应的随机生成数,具有伪随机的特点,在对其识别的时候比较容易。
(4) 基于置换(Permutation-based)的DGA。
这个方式,大多通过对一个DGA域名进行置换操作从而生成多个新的DGA域名。对一个初始域名进行字符上的排列组合。
总而言之,DGA域名的生成原理方法众多,在实际攻防过程中,较难防备。这也是DGA域名具有较大危险性的原因。

三、代码详细说明

环境与数据文件

1. 安装环境:

首先是安装python3.8左右的版本(官网就可以下载)
编译器,我这边用的是pycharm

2. 库文件:

Win+R 调用系统的cmd窗口(类似C语言运行时的那个黑窗口)
在这个“黑窗口”下,依次输入一下命令:

pip install pandas
pip install sklearn
pip install tensorflow
pip install xgboost

上面这些库是程序运行的必备条件,tensorflow和xgboost安装的时候可能比较慢。
也有部分同学可能在安装的库文件的时候无法安装,可能是镜像源的问题。可采取一下方式:(以pandas为例,其他类似。)

pip3 install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple

3. 源文件相关内容说明

注:(此处主要是介绍一下数据文件,源程序代码文件后面会细讲)
数据文件中包括dga.txt和top-1m.csv(Alexa)两个数据文件。
其中dga.txt已经从 DGA - Netlab OpenData Project ( https://data.netlab.360.com/dga ) 更新到2021-4-27的数据。Top-1m.csv还是使用 http://www.secrepo.com/ 上的数据。

4.1 库文件与数据文件路径

// 代码很烂,轻喷。注:仅供参考学习使用。
	# --coding = 'utf-8'--
	import re
    import warnings
	import pandas as pd
	import xgboost as xgb
	from sklearn import metrics
	from sklearn.naive_bayes import GaussianNB
	from sklearn.neural_network import MLPClassifier
	from sklearn.metrics import classification_report
	from sklearn.model_selection import train_test_split
	from sklearn.feature_extraction.text import CountVectorizer
# 数据文件路径
dga_file = "../data/dga/dga.txt"
alexa_file = "../data/dga/top-1m.csv"

4.2 数据读入相关

下面开始函数相关额介绍:

# 读入alexa(top-1m.csv)文件中的域名数据
def read_alexa():
    x = []
    data = pd.read_csv(alexa_file, sep=",", header=None)
    x = [i[1] for i in data.values]
    return x

函数名:read_alexa
功能:实现alexa数据文件中的数据的载入。
参数:无
返回值:x
详解:这个函数整体比较简单,也比较容易理解。流程如下:
1.构建一个列表。x = []用于后面文件中数据的读入。列表类似于C语言中的数组,可以进行下标索引。
2. data = pd.read_csv(alexa_file, sep=",", header=None)
这一句中,pd.read_csv()是调用pandas库中read_csv函数对top-1m.csv文件的数据进行读入。参数中alexa_file是文件路径;sep=","是分隔符“,”,把数据文件中的“,”去除,然后把文件中的编号和域名分开来。
此时,data数据格式为: 1

3.x = [i[1] for i in data.values] 这句运用了一些特殊的方式,列表推倒式这个操作,这个东西其实不难,就是类似C语言中的for循环。这句实现的是,把data数据格式中的数据部分放入了X这个列表中。【for i in data.values这个实现了前一部分的锁定,i[1]是后面一部分的锁定,然后通过for循环,把每一个域名数据放入x这个列表中】
此时X列表为: 【截图示意,没截全】
2

# 读入dga.txt文件中的域名数据
def read_dga():
    x = []
    data = pd.read_csv(dga_file, sep="\t", header=None,
                       skiprows=18)
    x = [i[1] for i in data.values]
    return x

函数名:read_dga
功能:实现dga数据文件中的数据的载入。
参数:无
返回值:x
详解:这个部分就不用介绍了吧,除了【skiprows=18】这个参数是为了跳过dga.txt文件的前18行,其他内容都是一样的。

4.3 特征模型建立相关

# 获取元音字母
def get_aeiou(domain):
    count = len(re.findall(r'[aeiou]', domain.lower()))

    return count

函数名:get_aeiou
功能:实现domain数据中元音字母数量的计数并返回该数值。
参数:domain
返回值:count
详解:
len(re.findall(r’[aeiou]’, domain.lower()))这里主要就是这个需要简单讲解一下。len()是返回数据的长度。re.findall()是re模块下的一个函数,
其可以以列表的形式返回能匹配的字符串。这里涉及了一些正则表达式的知识,这个不用过多了解。len(all(r’[aeiou]’, domain.lower()))个其实就是检测一下每个域名里【aeiou】这些字母的个数。例如“abbaee”进行匹配后,长度为4,也就是count=4

# 获取字母使用的数量
def get_uniq_char_num(domain):
    count = len(set(domain))

    return count

函数名:get_uniq_char_num
功能:实现domain数据中字母使用的数量并返回该数值。
参数:domain
返回值:count
详解:这个函数简单描述就是,看看里面abc…xyz和1234…这些英文字符中,一共用了多少个。len()用来返回长度,set()这个函数是去除重复字符。比如:"abb33ae2e"这个运行后的长度为:5【abe32一共5个字符】。也就是count=5

# 获取数字的数量
def get_num_num(domain):
    count = len(re.findall(r'[1234567890]', domain.lower()))

    return count

函数名:get_num_num
功能:实现计算domain数据中数字的数量并返回该数值。
参数:domain
返回值:count
详解:和前面get_aeiou获取元音字母数量的实现几乎一致,只是把元音字母【aeiou】换成了【12456789】这些数字。然后在运行的时候,会把函数数字的数量给记录下来并返回。比如:“abb33ae2e”,运行后,返回的长度为:3,也就是count=3

# 构造text特征模型
def text_feature():
    from sklearn import preprocessing
    alexa = read_alexa()
    dga = read_dga()
    v = alexa + dga
    y = [0] * len(alexa) + [1] * len(dga)
    x = []

    for vv in v:
        vvv = [get_aeiou(vv), get_uniq_char_num(vv), get_num_num(vv), len(vv)]
        x.append(vvv)

    x = preprocessing.scale(x)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)
    return x_train, x_test, y_train, y_test

函数名:text_feature
功能:实现text特征模型的建立,并把数据集分割为训练集与测试集。
参数:无
返回值:x_train, x_test, y_train, y_test
详解:这个函数进行了两个部分的功能,一个是1.将数据构造成text模型,另一个是2.将构造后的数据分为训练集与测试集。
先说1.将数据构造成text模型(2-12行)from sklearn import preprocessing这一句就是导入了一个库函数(类似头文件),其在第二个部分才有作用。
alexa = read_alexa()
dga = read_dga()
v = alexa + dga
这三行就是调用之前的函数,把相应的数据导入,然后将二者联合在一起传给V
y = [0] * len(alexa) + [1] * len(dga)这一句是开列表,开一个alexa和dga总长度大小的列表,其中,alexa长度部分,标记为0,dga长度部分标记为1。同时开一个x=[],准备接收数据。
对y就是一个列表(或者称之为数组)里面就是一堆的0,1。前alexa长度个是0.后面dga长度个是1.
对于x,现在还是空的,马上要把以下数据作为特征值放入X列表中。
for vv in v:
vvv = [get_aeiou(vv), get_uniq_char_num(vv), get_num_num(vv), len(vv)]
x.append(vvv)
这就是往x里放数据的操作。首先是这个for循环,按照C语言的习惯,我们会有一个计数的i来记录循环的次数【for(int i = 0 ; i < 10 ; i++)类似这样的】,然后再循环数组(或者叫列表)的下标进行操作。但是在python中,可以直接循环数据里的具体数据,不用进行下标索引。for vv in v这一句中的vv每次都是v中的一个数据(v是由alexa和dga组合成的一个大数据集,vv循环的就是里面的具体域名,从第一个,到最后一个),然后,对每一个vv进行的操作是:[get_aeiou(vv), get_uniq_char_num(vv), get_num_num(vv), len(vv)](调用前面的函数,把每一个域名对应的,元音字母数,字符数量,数字数量,和自身域名长度放在这个列表里),然后把这个包含每个域名特征信息的列表,赋给vvv,然后再通过列表的append操作把vvv这条数据添加到x中。
循环结束后,x就和y是同样的长度了,但是,x中包含的是每个域名的特征信息(元音字母数,字符数量,数字数量,和自身域名长度)而,y中存放的是0和1。例如“google。com”经过处理后是:[4, 7, 0, 10]
2.区分训练集与测试集。这部分,先对数据进行了预处理,预处理可以简化程序运行的复杂度。下面是处理和划分训练集 与测试集的程序:
x = preprocessing.scale(x)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)
return x_train, x_test, y_train, y_test
第一行的程序就是对已经存好数据的x列表进行预处理,使用的是sklearn库下的preprocessing.scale(x)函数进行处理的,其过程是:按列进行,减去其均值,然后除以其方差。例如:
[[1 , -1 , 2],
[2 , 0 , 0]
[0 , 1 , -1]]
其经过处理后是:
[[ 0 -1.22474487 1.33630621],
[ 1.22474487 0 -0.26726124]
[-1.22474487 1.22474487 -1.06904497]]
对于x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)这句是进行样本数据的划分,将处理后的数据特征集x和其对应的分类结果y(也就是y中的0代表非dga域名,1代表dga域名)进行分类,test_size=0.4代表样本集x中的40%是测试集,其他的是训练集。(总长度不是2万,而应该是20000-18=19982,因为dga中跳过了18行)

# 构造N-Gram模型特征
def ngram_feature(start, end):
    alexa = read_alexa()
    dga = read_dga()
    x = alexa + dga
    max_features = 10000
    y = [0] * len(alexa) + [1] * len(dga)

    CV = CountVectorizer(
        ngram_range=(start, end),
        token_pattern=r'\w',
        decode_error='ignore',
        strip_accents='ascii',
        max_features=max_features,
        stop_words='english',
    )
    x = CV.fit_transform(x)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)

    return x_train.toarray(), x_test.toarray(), y_train, y_test

函数名:ngram_feature
功能:实现N-Gram特征模型的建立,并把数据集分割为训练集与测试集。
参数:start, end
返回值:x_train.toarray(), x_test.toarray(), y_train, y_test
详解:本函数与上面的函数实现的效果相似。主要是两个部分的功能:1.实现N-Gram模型的建立与样本数据填充;2.训练集与测试集的划分。

  1. 现N-Gram模型的建立与样本数据填充,代码如下:

alexa = read_alexa()
dga = read_dga()
x = alexa + dga
max_features = 10000
y = [0] * len(alexa) + [1] * len(dga)
CV = CountVectorizer(
ngram_range=(start, end),
token_pattern=r’\w’,
decode_error=‘ignore’,
strip_accents=‘ascii’,
max_features=max_features,
stop_words=‘english’,
x = CV.fit_transform(x)

其中,前面这一部分:

alexa = read_alexa()
dga = read_dga()
x = alexa + dga
max_features = 10000
y = [0] * len(alexa) + [1] * len(dga)

与前面一个模型的处理一致,不在赘述。主要讲解后面这一部分:

CV = CountVectorizer(
ngram_range=(start, end),
token_pattern=r’\w’,
decode_error=‘ignore’,
strip_accents=‘ascii’,
max_features=max_features,
stop_words=‘english’,
)
x = CV.fit_transform(x)

ngram_range=(start, end)要提取的不同n-grams的n值范围的下限和上限。将使用n的所有值,使得start<= n <= end。简单来说,比如调用的时候是ngram_range=(2, 2)则表示每个单词被按序切分为2个字符长度单位,如“baidu”被处理后是:ba, ai, id, du ;如果调用的时候是ngram_range=(3,3),“baidu”被处理后是:bai, aid, idu(就是个切分长度)。
token_pattern=r’\w’ 表示每次匹配一个字符
decode_error=‘ignore’ 表示如果给出一个字节序列来分析包含不是给定编码的字符,该怎么做(默认编码是utf-8),'ignore’表示对上述问题进行忽略即可。
strip_accents='ascii’表示使用ascii编码在预处理步骤去除样本数据中的重音符号,咱们这个没有可以忽略。
max_features=max_features这个是建立一个词汇表,仅用词频排序的前max_features个词创建语料库,前面alexa的大小是10000,所以用其所有数据做了一个词汇表,用与训练的时候使用
stop_words=‘english’ 这个表示使用内置的英语停用词词表
(这部分是模型具体实现部分,需要结合模型的理论部分进行分析,这边不需要特别深入(研究生都不见得搞得明白)这些参数知道大概什么意思就好,答辩的时候也不会问你参数设置的问题。)
最后x = CV.fit_transform(x)将样本中的数据转换为词频矩阵
2. 划分样本集为训练集与测试集。这部分和上一个函数的实现过程一致,没有具体区别,不在赘述。

4.4 训练模型相关

# 运用朴素贝叶斯训练和识别
def do_nb(x_train, x_test, y_train, y_test):
    gnb = GaussianNB()
    gnb.fit(x_train, y_train)
    y_pred = gnb.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))

函数名:do_nb
功能:用朴素贝叶斯进行训练和预测识别分析。
参数:x_train, x_test, y_train, y_test
返回值:无
详解:这个部分比较容易理解:
大概流程就是:首先建立朴素贝叶斯的训练器(这里用的是高斯朴素贝叶斯,朴素贝叶斯一共有三种,这里选用的是其中一种,程序里用的都是这一种,三种之间的区别你可以度一下,在后面论文部分我也会提及),然后将训练集x_train和对应的分类y_train训练模型中进行训练;训练结束后,进行测试,将测试集x_test导入训练模型下的predict(x_test)函数进行对测试集的结果预测,将测试结果返回给y_pred。至此,可以得到预测的结果,然后通过metrics.precision_score(),metrics.recall_score(),metrics.f1_score(),三个函数分别获得预测的得分情况。precision_score,recall_score,f1_score分别对应准确率(或者叫精度),召回率,和f1值
更深入理解可以看这两个博客介绍:
【1】sklearn评估指标precision_score/recall_score/f1_score原理分析及应用_NewFarmland的博客-CSDN博客。

https://blog.csdn.net/tttwister/article/details/81138865

【2】sklearn计算准确率、精确率、召回率、F1 score_MrLittleDog的博客-CSDN博客_sklearn计算准确率。

https://blog.csdn.net/hfutdog/article/details/88085878?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id=1619669237123_76753&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

# 用xgboost进行训练和识别
def do_xgboost(x_train, x_test, y_train, y_test):
    xgb_model = xgb.XGBClassifier().fit(x_train, y_train)
    y_pred = xgb_model.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))

函数名:do_xgboost
功能:进行xgboost进行训练和预测识别分析。
参数:x_train, x_test, y_train, y_test
返回值:无
详解:这个函数里的东西与前面朴素贝叶斯的内容很相似,只是每个模型下的构造方法略微有点不同,或者说是python语法结构上的一些简便操作。
xgb_model = xgb.XGBClassifier().fit(x_train, y_train)
这一句就是把xgboost模型建立与训练数据的输入同时进行了,并将训练好的模型返回给xgb_model这个变量名。这个相当于朴素贝叶斯中:
gnb = GaussianNB()
gnb.fit(x_train, y_train)
这两句的作用是一样的,应该还是比较好理解的,把这一长句拆分开类似朴素贝叶斯的样子的话,是这样:
xgb_model = xgb.XGBClassifier()
xgb_model.fit(x_train, y_train)
这样就一致了,化成一句只是python语法的便捷性的原因,实现的功能是一样的。
后面进行预测,和相关预测得分的输出与朴素贝叶斯的一致,不在赘述。

# 运用MLP进行训练和识别
def do_mlp(x_train, x_test, y_train, y_test):
    global max_features
    # Building deep neural network
    clf = MLPClassifier(solver='lbfgs',
                        alpha=1e-5,
                        hidden_layer_sizes=(5, 3),
                        random_state=1)
    clf.fit(x_train, y_train)
    y_pred = clf.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))

函数名:do_mlp
功能:用深度学习方法mlp进行训练和预测识别分析。
参数:x_train, x_test, y_train, y_test
返回值:无
详解:这个部分想弄的很清楚还是有点难度的,我也没有完全搞明白这个模型,深度学习还是有点太复杂了些,这部分不用特别特别的深入,了解一下参数的作用和基本的原理就好了。(深入的知识应该要研究生才会去学,本科阶段一般不会太深入涉及的。)
solver=‘lbfgs’:进行选择权重优化的求解器:'lbfgs’是准牛顿方法族的优化器,对于小型数据集,“lbfgs”可以更快地收敛并且表现更好。
alpha=1e-5:默认0.0001,正则化项参数(用的默认值,不用太在意)
hidden_layer_sizes=(5, 3): 表示有两层隐藏层,第一层隐藏层有5个神经元,第二层也有3个神经元。
random_state=1是随机数生成器的种子,简单来说是为了模型数据可以复现而设置的,如果不设置,那么每次模型里生成的数据都是随机的,而设置为1后,每次运行程序的时候,模型内部生成的随机数都会是相等的,那么测试的结果会非常相似(因为还有后续处理,但是,在模型里是一致的),测试结果也就可以复现了。
然后即使进行:clf.fit(x_train, y_train)将训练数据拟合载入训练,后面就和之前的函数一致啦,不再赘述了。
深入理解一下的话可以看一下:
【1】sklearn 神经网络 MLPClassifier简单应用与参数说明 - 简书 (jianshu.com)

https://www.jianshu.com/p/71fde5d90136

【2】sklearn 神经网络MLPclassifier参数详解_欢迎光临啊噗不是阿婆主的酒馆-CSDN博客_mlpclassifier

https://blog.csdn.net/weixin_38278334/article/details/83023958

【3】对random_state参数的理解_枪枪枪的博客-CSDN博客

https://blog.csdn.net/az9996/article/details/86616668

四、完整源程序代码

// 代码很烂,轻喷。注:仅供参考学习使用。
# --coding = 'utf-8'--
import re
import warnings
import pandas as pd
import xgboost as xgb
from sklearn import metrics
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer

# 数据文件路径
dga_file = "../data/dga/dga.txt"
alexa_file = "../data/dga/top-1m.csv"


# 读入alexa(top-1m.csv)文件中的域名数据
def read_alexa():
    x = []
    data = pd.read_csv(alexa_file, sep=",", header=None)
    x = [i[1] for i in data.values]
    return x


# 读入dga.txt文件中的域名数据
def read_dga():
    x = []
    data = pd.read_csv(dga_file, sep="\t", header=None,
                       skiprows=18)
    x = [i[1] for i in data.values]
    return x


# 获取元音字母
def get_aeiou(domain):
    count = len(re.findall(r'[aeiou]', domain.lower()))

    return count


# 获取字母使用的数量
def get_uniq_char_num(domain):
    count = len(set(domain))

    return count


# 获取数字的数量
def get_num_num(domain):
    count = len(re.findall(r'[1234567890]', domain.lower()))

    return count


# 构造text特征模型
def text_feature():
    from sklearn import preprocessing
    alexa = read_alexa()
    dga = read_dga()
    v = alexa + dga
    y = [0] * len(alexa) + [1] * len(dga)
    x = []

    for vv in v:
        vvv = [get_aeiou(vv), get_uniq_char_num(vv), get_num_num(vv), len(vv)]
        x.append(vvv)

    x = preprocessing.scale(x)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)
    return x_train, x_test, y_train, y_test


# 构造N-Gram模型特征
def ngram_feature(start, end):
    alexa = read_alexa()
    dga = read_dga()
    x = alexa + dga
    max_features = 10000
    y = [0] * len(alexa) + [1] * len(dga)

    CV = CountVectorizer(
        ngram_range=(start, end),
        token_pattern=r'\w',
        decode_error='ignore',
        strip_accents='ascii',
        max_features=max_features,
        stop_words='english',
    )
    x = CV.fit_transform(x)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4)

    return x_train.toarray(), x_test.toarray(), y_train, y_test


# 运用朴素贝叶斯训练和识别
def do_nb(x_train, x_test, y_train, y_test):
    gnb = GaussianNB()
    gnb.fit(x_train, y_train)
    y_pred = gnb.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))


# 用xgboost进行训练和识别
def do_xgboost(x_train, x_test, y_train, y_test):
    xgb_model = xgb.XGBClassifier().fit(x_train, y_train)
    y_pred = xgb_model.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))


# 运用MLP进行训练和识别
def do_mlp(x_train, x_test, y_train, y_test):
    global max_features
    # Building deep neural network
    clf = MLPClassifier(solver='lbfgs',
                        alpha=1e-5,
                        hidden_layer_sizes=(5, 3),
                        random_state=1)
    clf.fit(x_train, y_train)
    y_pred = clf.predict(x_test)
    # print(classification_report(y_test, y_pred))
    print('precision_score:%.4f' % (metrics.precision_score(y_test, y_pred)))
    print('recall_score:%.4f' % (metrics.recall_score(y_test, y_pred)))
    print('f1_score:%.4f\n' % (metrics.f1_score(y_test, y_pred)))


# 测试N-Gram在N的不童值下朴素贝叶斯的识别情况
def test_NGram():
    print('# test_NGram:')
    print("---1-gram & nb---")
    x_train, x_test, y_train, y_test = ngram_feature(1, 1)
    do_nb(x_train, x_test, y_train, y_test)
    print("---2-gram & nb---")
    x_train, x_test, y_train, y_test = ngram_feature(2, 2)
    do_nb(x_train, x_test, y_train, y_test)
    print("---3-gram & nb---")
    x_train, x_test, y_train, y_test = ngram_feature(3, 3)
    do_nb(x_train, x_test, y_train, y_test)


# 测试 N-Gram和Text模型下的朴素贝叶斯识别效率情况
def test_NGram_text_feature():
    print('# test_NGram_text_feature:')
    print("---2-gram & nb---")
    x_train, x_test, y_train, y_test = ngram_feature(2, 2)
    do_nb(x_train, x_test, y_train, y_test)

    print("---text feature & nb---")
    x_train, x_test, y_train, y_test = text_feature()
    do_nb(x_train, x_test, y_train, y_test)


# 测试在相同特征模型N-Gram下不同机器学习算法的识别效果
def test_MLAlgorithm():
    print('# test_MLAlgorithm:')
    print("---2-gram & nb---")
    x_train, x_test, y_train, y_test = ngram_feature(2, 2)
    do_nb(x_train, x_test, y_train, y_test)

    print("---2-gram & XGBoost---")
    x_train, x_test, y_train, y_test = ngram_feature(2, 2)
    do_xgboost(x_train, x_test, y_train, y_test)

    print("---2-gram & mlp---")
    x_train, x_test, y_train, y_test = ngram_feature(2, 2)
    do_mlp(x_train, x_test, y_train, y_test)


if __name__ == '__main__':
    warnings.filterwarnings('ignore')  # 去除一些不必要的warning

    # 测试N-Gram模型下字符长度对朴素贝叶斯算法的影响
    test_NGram()

    #  测试不同模型下的朴素贝叶斯算法效果
    test_NGram_text_feature()

    #  测试N-Gram模型不同机器学习算法的效果
    test_MLAlgorithm()

五、测试总结

此程序对代码部分进行了一些详细的说明,解释较为详细,且通俗易懂,且整体难度相对较低。然而本人水平很低,对此内容仅仅进行了实现没有进行优化改进,有兴趣的朋友可以深入一下。
程序运行的部分就不贴图啦。有兴趣的话,大家自己运行一下吧~

六、源代码&其他

源代码在下面哦~:
https://download.csdn.net/download/qq_40934206/20916088

以上以及博客中含有在校整理字样的博客内容,均是本人本科在校学习期间所写的代码,源文件以及数据文件等在个人主页资源区可以获取。本人水平很低,大佬轻喷。整理出来是为了帮助初学者学习的过程中,在有需要的情况下能够有所参考。再次声明:仅供学习交流使用。大家有什么问题,欢迎留言~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值