系列目录
《Web安全之机器学习入门》笔记:第十五章 15.4 TensorFlow识别验证码(一)
《Web安全之机器学习入门》笔记:第十五章 15.5 TensorFlow多层感知机识别验证码(二)
《Web安全之机器学习入门》笔记:第十五章 15.6 TensorFlow DNN识别验证码(三)
《Web安全之机器学习入门》笔记:第十五章 15.7与15.8 TensorFlow识别垃圾邮件
目录
本小节通过识别垃圾邮件,讲解tensorflow通过神经网络DNN在网络安全方向的应用,同时还对比了NB算法的垃圾邮件识别效果。
一、SpamBase数据集
SpamBase 数据集是一个用于垃圾邮件检测的经典数据集,由惠普实验室创建,以下是其详细介绍。
- 数据集规模:包含 4601 条电子邮件样本,其中垃圾邮件 1813 封,正常邮件 2788 封。
- 特征维度:每封邮件由 57 个属性描述,具体如下:
- 单词频率属性:48 个连续型实数属性,范围在 0 到 100 之间,如
word_freq_make
表示 “make” 这个单词在邮件中出现的频率占总单词数的百分比。 - 字符频率属性:6 个连续型实数属性,范围在 0 到 100 之间,如
char_freq_
表示某个字符在邮件中出现的频率占总字符数的百分比。 - 大写字母序列属性:3 个属性,包括
capital_run_length_average
(大写字母连续序列的平均长度)、capital_run_length_longest
(最长的大写字母连续序列的长度)和capital_run_length_total
(大写字母连续序列的总长度,即邮件中大写字母的总数)。 - 类别属性:1 个名义属性
spam
,取值为 0 或 1,0 表示非垃圾邮件,1 表示垃圾邮件。
- 单词频率属性:48 个连续型实数属性,范围在 0 到 100 之间,如
- 数据特点:该数据集存在数据不平衡问题,垃圾邮件数量少于正常邮件。并且可能包含一些反映其收集标准和来源特点的偏差。
二、TensorFlow识别垃圾邮件
本小节通过识别垃圾邮件,讲解tensorflow通过神经网络DNN检测垃圾邮件,如下为流程图。
1、数据集与特征化
本小节使用SpamBase这个入门级垃圾邮件数据集进行训练和测试,这里要强调SpamBase数据不是原始的邮件内容,而是已经特征化的数据。共有58个属性,对应的特征是统计的关键字以及特殊符号的词频,其中最后一个是垃圾邮件的标志位。如下图所示,特征结构举例如下:
代码实现了 SpamBase 垃圾邮件数据集的加载与预处理。load_SpamBase
函数从文件读取数据,将每行的 57 个特征转为浮点数作为输入x
,最后一列标签转为整数作为输出y
,并按 4:6 比例划分训练集和测试集。main
函数调用加载函数获取数据后,使用 TensorFlow 推断实值特征列。代码完成了从数据加载到特征准备的流程,为后续机器学习模型训练做准备。
- 数据读取:从文件逐行读取 SpamBase 数据集
- 格式转换:将特征转为浮点数,标签转为整数
- 数组构建:将处理后的特征和标签转为 NumPy 数组
- 数据划分:按 4:6 比例分割训练集和测试集
- 维度打印:输出各数据集的形状信息
- 特征推断:使用 TF 推断实值特征列
- 数据准备:完成垃圾邮件分类数据预处理
def load_SpamBase(filename):
x=[]
y=[]
with open(filename) as f:
for line in f:
line=line.strip('\n')
v=line.split(',')
y.append(int(v[-1]))
t=[]
for i in range(57):
t.append(float(v[i]))
t=np.array(t)
x.append(t)
x=np.array(x)
y=np.array(y)
print(x.shape)
print(y.shape)
x_train, x_test, y_train, y_test=train_test_split( x,y, test_size=0.4, random_state=0)
print(x_train.shape)
print(x_test.shape)
return x_train, x_test, y_train, y_test
def main(unused_argv):
x_train, x_test, y_train, y_test=load_SpamBase("../data/spambase/spambase.data")
feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(x_train)
打印数据集总体size如下所示。
(4601, 57)
本节训练集和测试集采用6:4,打印训练集和测试集,他们的特征值size分别如下所示。
(2760, 57)
(1841, 57)
打印训练集第一项的57个特征,如下所示。
[2.70e-01 0.00e+00 1.30e-01 0.00e+00 8.20e-01 0.00e+00 0.00e+00 0.00e+00
0.00e+00 0.00e+00 0.00e+00 5.50e-01 4.10e-01 0.00e+00 0.00e+00 0.00e+00
0.00e+00 0.00e+00 1.24e+00 0.00e+00 1.10e+00 0.00e+00 0.00e+00 0.00e+00
1.65e+00 8.20e-01 1.30e-01 1.30e-01 1.30e-01 1.30e-01 1.30e-01 1.30e-01
0.00e+00 1.30e-01 1.30e-01 1.30e-01 4.10e-01 0.00e+00 0.00e+00 1.30e-01
0.00e+00 4.10e-01 1.30e-01 0.00e+00 4.10e-01 0.00e+00 0.00e+00 2.70e-01
4.10e-02 1.02e-01 2.00e-02 2.00e-02 0.00e+00 0.00e+00 2.78e+00 3.40e+01
3.67e+02]
2、DNN训练数据集
本小节使用两个隐藏层,其中隐藏层1为30个神经元,隐藏层2为10个神经元,分为两类
classifier = tf.contrib.learn.DNNClassifier(
feature_columns=feature_columns, hidden_units=[30,10], n_classes=2)
classifier.fit(x_train, y_train, steps=500,batch_size=10)
3、DNN验证数据集
接下来评估训练好的分类器性能:先通过分类器对测试集数据 x_test 进行预测,将可迭代的预测结果转为列表 y_predict;再用 metrics.accuracy_score 计算测试集真实标签 y_test 与预测标签 y_predict 的准确率;最后打印出该准确率数值,以此衡量模型分类效果。
y_predict=list(classifier.predict(x_test, as_iterable=True))
score = metrics.accuracy_score(y_test, y_predict)
print('Accuracy: {0:f}'.format(score))
结果如下所示,准确率为72%左右。
Accuracy: 0.724063
4、朴素贝叶斯NB法训练与验证数据集
代码使用高斯朴素贝叶斯算法实现分类任务:首先实例化 GaussianNB 分类器;接着用训练集数据 x_train 和标签 y_train 对其进行训练,并直接对测试集 x_test 进行预测,得到预测标签 y_predict;最后通过 accuracy_score 计算预测标签与真实标签 y_test 的准确率,并打印结果,展示模型在测试集上的表现。
gnb = GaussianNB()
y_predict = gnb.fit(x_train, y_train).predict(x_test)
score = metrics.accuracy_score(y_test, y_predict)
print('Accuracy: {0:f}'.format(score))
测试结果如下所示,准确率为82.6%左右。
Accuracy: 0.826181
5、完整代码
代码实现垃圾邮件分类,加载 SpamBase 数据集,提取 57 个特征与标签,按 6:4 划分训练集和测试集。用 TensorFlow 构建含 30、10 个神经元的两层 DNN,训练 500 步后评估准确率;同时训练高斯朴素贝叶斯模型,通过输出两者准确率进行对比,完成二分类任务。
- 数据加载:读取 SpamBase 数据集,提取 57 个特征与标签
- 数据划分:按 6:4 比例分割训练集和测试集
- 特征处理:自动推断实值特征列,适配 TensorFlow 模型
- DNN 构建:搭建含 30、10 神经元的两层深度神经网络
- 模型训练:训练 DNN 模型,设置 500 步和 10 的批次大小
- 模型评估:计算并输出 DNN 模型的准确率
- 对比实验:训练高斯朴素贝叶斯,输出准确率作对比
import tensorflow as tf
from tensorflow.contrib.learn.python import learn
from sklearn import metrics
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.naive_bayes import GaussianNB
# SpamBase数据集格式示例:
# 0,0.64,0.64,0,0.32,0,0,0,0,0,0,0.64,0,0,0,0.32,0,1.29,1.93,0,0.96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
# 0,0,0,0,0.778,0,0,3.756,61,278,1
def load_SpamBase(filename):
"""加载SpamBase垃圾邮件数据集
参数:
filename: 数据集文件路径
返回:
x_train, x_test, y_train, y_test: 划分后的训练集和测试集
"""
x = [] # 特征向量列表
y = [] # 标签列表
# 读取数据集文件
with open(filename) as f:
for line in f:
line = line.strip('\n') # 去除行尾换行符
v = line.split(',') # 使用逗号分割每行数据
# 提取标签(最后一列): 1=垃圾邮件, 0=正常邮件
y.append(int(v[-1]))
# 提取前57个特征
t = []
for i in range(57):
t.append(float(v[i]))
x.append(np.array(t)) # 将特征转换为NumPy数组
# 转换为NumPy数组以便后续处理
x = np.array(x)
y = np.array(y)
# 打印数据集形状信息
print(f"特征矩阵形状: {x.shape}") # (样本数, 57)
print(f"标签向量形状: {y.shape}") # (样本数,)
# 划分训练集(60%)和测试集(40%)
x_train, x_test, y_train, y_test = train_test_split(
x, y, test_size=0.4, random_state=0)
# 打印数据集划分结果
print(f"训练集特征形状: {x_train.shape}")
print(f"测试集特征形状: {x_test.shape}")
return x_train, x_test, y_train, y_test
def main(unused_argv):
"""主函数:加载数据并训练模型"""
# 1. 加载SpamBase数据集
x_train, x_test, y_train, y_test = load_SpamBase("../data/spambase/spambase.data")
# 2. 为TensorFlow模型准备特征列
# 自动推断实值特征列,每个特征对应一个RealValuedColumn
feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(x_train)
# 3. 构建深度神经网络分类器
# - 网络结构: 输入层(57) -> 隐藏层1(30) -> 隐藏层2(10) -> 输出层(2)
# - 激活函数: 默认使用ReLU
# - 优化器: 默认使用Adagrad
classifier = tf.contrib.learn.DNNClassifier(
feature_columns=feature_columns,
hidden_units=[30, 10], # 两个隐藏层,分别有30和10个神经元
n_classes=2, # 二分类问题
model_dir="./spam_model" # 模型保存路径
)
# 4. 训练DNN模型
classifier.fit(
x=x_train,
y=y_train,
steps=500, # 训练步数
batch_size=10 # 批次大小
)
# 5. 评估DNN模型
y_predict = list(classifier.predict(x_test, as_iterable=True))
dnn_accuracy = metrics.accuracy_score(y_test, y_predict)
print(f'DNN 准确率: {dnn_accuracy:.6f}')
# 6. 训练并评估朴素贝叶斯模型作为对比
gnb = GaussianNB()
y_predict = gnb.fit(x_train, y_train).predict(x_test)
nb_accuracy = metrics.accuracy_score(y_test, y_predict)
print(f'朴素贝叶斯 准确率: {nb_accuracy:.6f}')
# 7. 输出模型对比结果
print(f"\nDNN vs 朴素贝叶斯 准确率差异: {dnn_accuracy - nb_accuracy:.6f}")
if __name__ == '__main__':
tf.app.run() # 运行TensorFlow应用,会调用main函数