整理自唐宇迪老师的视频课程,感谢他!
本文最后会贴出所有的源代码文件,下文只是针对每个小点贴出代码进行注释说明,可以略过。

1.思路
关于利用CNN做文本分类,其主要思想通过下面这幅图就能够一目了然。

本文主要记录了利用CNN来分类英文垃圾邮件的全过程。数据集主要包含两个文件:里面分别是垃圾邮件和正常邮件,用记事本就能打开。先来看看数据集长什么样:

simplistic , silly and tedious .
unfortunately the story and the actors are served with a hack script .
all the more disquieting for its relatively gore-free allusions to the serial murders , but it falls down in its attempts to humanize its subject .
a sentimental mess that never rings true .
while the performances are often engaging , this loose collection of largely improvised numbers would probably have worked better as a one-hour tv documentary .
interesting , but not compelling .

这里展示的是其中的6封邮件,可以看到每封邮件之间是通过回车换行来分隔的,我们等下也通过这个特点来分割每一个样本。

我们知道,在CNN文本分类中,是通过将每个单词对应的词向量堆叠起来,形成一个二维矩阵,以此来进行卷积和池化的。但在此处我们没有词向量怎么办呢?既然没有,那索性就不要,把它也当做一个参数,让它在训练中产生。具体做法就是:

①根据所有邮件中的单词,选取出现频率靠前的k个或者全部(本例采用全部)产生一个长度为vocabulary_size的字典(词表);
②随机初始化一个大小为[vocabulary_size,embedding_size]的词向量矩阵,embedding_size表示你用多少维的向量来表示一个词;
③对于每一封邮件,找出其每个单词在字典中对应的索引,然后按照索引从词向量矩阵中取出对应位置的词向量,堆叠形成表示该邮件的二维矩阵;
④为所有的邮件设定一个最大长度,即最多由多少个单词构成,多的截取,少的用0填充。

例如:

一封邮件内容为tomorrow is sunny,假设这三个单词在字典中对应的索引为6,2,3,且邮件的最大长度为7;那么我们首先得到这封邮件对应单词的索引序列就为:56,28,97,0,0,0,0。同时初始化的词向量矩阵为:

[[0.398 0.418 0.29  0.344 0.898 0.555 0.033 0.056 0.923]    0[0.668 0.957 0.428 0.942 0.692 0.084 0.413 0.619 0.02 ]    1    [0.329 0.618 0.189 0.544 0.76  0.702 0.009 0.811 0.882]    2[0.912 0.042 0.777 0.765 0.708 0.887 0.944 0.272 0.5  ]    3[0.397 0.828 0.244 0.439 0.598 0.298 0.505 0.63  0.883]    4[0.402 0.084 0.419 0.66  0.69  0.031 0.354 0.117 0.494]    5[0.966 0.016 0.218 0.732 0.523 0.263 0.749 0.813 0.547]    6[0.065 0.739 0.394 0.077 0.461 0.203 0.246 0.456 0.809]]   7

tomorrow is sunny这封邮件对应的矩阵就为:

[[0.966 0.016 0.218 0.732 0.523 0.263 0.749 0.813 0.547]    6[0.329 0.618 0.189 0.544 0.76  0.702 0.009 0.811 0.882]    2[0.912 0.042 0.777 0.765 0.708 0.887 0.944 0.272 0.5  ]    3[0.398 0.418 0.29  0.344 0.898 0.555 0.033 0.056 0.923]    0[0.398 0.418 0.29  0.344 0.898 0.555 0.033 0.056 0.923]    0[0.398 0.418 0.29  0.344 0.898 0.555 0.033 0.056 0.923]    0[0.398 0.418 0.29  0.344 0.898 0.555 0.033 0.056 0.923]]   0

同时,这也就对应着一个样本。可能有人就会问,初始化的词向量本来就不能表示每个词,那这样构造出来的矩阵能代表一封邮件吗?对于这个问题可以从两个角度来看:第一,开始可能它是不正确的,但由于我们这里是有监督学习,只要它不正确,最后就会会产生误差,算法可以根据产生误差来纠正这一错误,通过多次的迭代,就自然正确了;第二,虽然这个词向量矩阵是随机产生的,可能是错的,但所有邮件的表示方式都是根据这个错误的矩阵形成的,从某种意义上来说也就是对的了,我们之所以觉得它错了,是因为我们找不到一种度量方式来说明它是对的。咳,扯远了……

2 预处理

有了上面的总体思路,我们下面就细致的来对邮件进行预处理。

2.1 构造数据集

一次读入所有邮件(为一个字符串),按’\n’作为分割符分开,并去掉每个样本前后的空格。

positive = open(positive_data_file, 'rb').read().decode('utf-8')  # 得到一个字符串,因为含有中文所以加decode('utf-8')negative = open(negative_data_file, 'rb').read().decode('utf-8')positive_examples = positive.split('\n')[:-1]  # 将整个文本用换行符分割成一个一个的邮件negative_examples = negative.split('\n')[:-1]  # 得到的是一个list,list中的每个元素都是一封邮件(并且去掉最后一个换行符,[:-1]表示去掉最后一个元素)positive_examples = [s.strip() for s in positive_examples]  # 去掉每个邮件开头和结尾的的空格negative_examples = [s.strip() for s in negative_examples]x_text = positive_examples + negative_examples  # 两个列表相加构成数据集x_text = [clean_str(sent) for sent in x_text]  # 去除每个邮件中的标点等无用的字符

其中函数clean_str()是去除每个样本(邮件)中的其它字符。

处理完后如下(前3个):

[“the rock is destined to be the 21st century 's new conan and that he 's going to make a splash even greater than arnold schwarzenegger , jean claud van damme or steven segal”, “the gorgeously elaborate continuation of the lord of the rings trilogy is so huge that a column of words cannot adequately describe co writer director peter jackson 's expanded vision of j r r tolkien 's middle earth”, ‘effective but too tepid biopic’]

2.2 构造标签

    positive_label = [[0, 1] for _ in positive_examples]  # 构造one-hot 标签[[0, 1], [0, 1], [0, 1], [0, 1],....]negative_label = [[1, 0] for _ in negative_examples]

对于每个样本,我们用One-hot的形式进行标签化处理,结果这样处理后的结果如下:

print(positive_label[:5])
[[0, 1], [0, 1], [0, 1], [0, 1], [0, 1]]

同理,负样本的标签也是如此。接着就是将两者合并到一起:

 y = np.concatenate([positive_label, negative_label], axis=0)

其中axis=0表示纵向堆叠,结果如下:

print(y[:5])
[[0 1][0 1][0 1][0 1][0 1]]

2.3 数字化数据集

所谓数字化数据集就是我们在第一部分中说道的,先建立一个字典,然后找到每个邮件中的单词在字典中对应的索引。好在TensorFlow已经为我们提供了这么一个模块from tensorflow.contrib import learn,让我们可以方便的得到这些。

首先我们取邮件中最长单词数作为每封邮件的长度(不足的按0填充)

max_document_length = max([len(x.split(' ')) for x in x_text])

本例中max_document_length=56,也就代表着每封邮件都按56个单词处理。

接着:

vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length)
x = np.array(list(vocab_processor.fit_transform(x_text)))  # 得到每个样本中,每个单词对应在词典中的序号
print(x[:3])#
[[ 1  2  3  4  5  6  1  7  8  9 10 11 12 13 14  9 15  5 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0][ 1 31 32 33 34  1 35 34  1 36 37  3 38 39 13 17 40 34 41 42 43 44 45 46 47 48 49  9 50 51 34 52 53 53 54  9 55 56  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  0  0  0  0  0  0  0  0  0]]

2.4 打乱数据并构造训练集和测试集

到目前为止,我们已经将邮件转化成了一个数字化的表现形式;但此时所有的样本都是正负样本密集聚在一起的,所有要先将其打乱。

np.random.seed(10)# 生成一个种子
shuffle_indices = np.random.permutation(np.arange(len(y)))#产生随机数
x_shuffled = x[shuffle_indices]  # 打乱数据
y_shuffled = y[shuffle_indices]dev_sample_index = -1 * int(0.2 * float(len(y)))
x_train, x_dev = x_shuffled[:dev_sample_index], x_shuffled[dev_sample_index:]
y_train, y_dev = y_shuffled[:dev_sample_index], y_shuffled[dev_sample_index:]  # 划分训练集和验证集

此时,经过上面一系列的处理,我们已经得到了每封邮件每个单词对应的索引序列,和其对应的标签,并进行了打乱。

接着在下面一篇博文中,我们就开始进行二维矩阵的构造,然后卷积,池化全连接等。

源码

更多内容欢迎扫码关注公众号月来客栈!

CNN英文垃圾邮件分类(数据预处理)相关推荐

  1. CNN中文垃圾邮件分类(二)

    本文整理自唐宇迪老师视频,谢谢他! 1.思路 在上一篇博客CNN中文垃圾邮件分类(一)中介绍了两种预处理方式,现在来介绍第二种,先用分好词的数据作为训练语料,选择前n个词作为词表(或者去掉出现频率较低 ...

  2. 基于朴素贝叶斯的垃圾邮件分类-着重理解拉普拉斯变换

    1. 引言 在正式学习朴素贝叶斯之前,需要明确的是机器学习所要实现的是基于有限的训练样本集尽可能准确地估计出后验概率P(c|x),即根据特征得到所属类别的概率,首先引入两个概念. 判别式模型(disc ...

  3. 基于Bayes和SVM的垃圾邮件分类实现(改进版)

    对本文标题进行分词和提取关键词,本文关键词如下:分类.垃圾邮件分类(spam).Bayes.SVM.改进版(体现在哪里?).本文不对Bayes.SVM原理做过多的摄入和解释,主要是使用这些算法做一个基 ...

  4. 4.4 机器学习系统设计--垃圾邮件分类-机器学习笔记-斯坦福吴恩达教授

    机器学习系统设计–垃圾邮件分类 假定我们现有一封邮件,其内容如下: From: cheapsales@buystufffromme.com To: ang@cs.stanford.edu Subjec ...

  5. 垃圾邮件分类实战(SVM)

    1. 数据集说明 trec06c是一个公开的垃圾邮件语料库,由国际文本检索会议提供,分为英文数据集(trec06p)和中文数据集(trec06c),其中所含的邮件均来源于真实邮件保留了邮件的原有格式和 ...

  6. 垃圾邮件分类 python_在python中创建SMS垃圾邮件分类器

    垃圾邮件分类 python 介绍 (Introduction) I have always been fascinated with Google's gmail spam detection sys ...

  7. 垃圾邮件分类-朴素贝叶斯算法

    目录 一.贝叶斯公式原理 二.使用朴素贝叶斯进行文档分类 三.Python代码实现 一.贝叶斯公式原理 在基础的概率学中,经典的有求独立事件的概率以及求关联时间的概率,贝叶斯所要解决的问题就是在有条件 ...

  8. 机器学习--使用朴素贝叶斯进行垃圾邮件分类

    一.学习背景 垃圾邮件的问题一直困扰着人们,传统的垃圾邮件分类的方法主要有"关键词法"和"校验码法"等,然而这两种方法效果并不理想.其中,如果使用的是" ...

  9. 朴素贝叶斯(西瓜数据集分类,社区恶意留言分类,垃圾邮件分类,新浪新闻分类),AODE分类器 代码实现

    朴素贝叶斯(西瓜数据集分类,社区恶意留言分类,垃圾邮件分类,新浪新闻分类),AODE分类器 代码实现 以下代码为本人学习后,修改或补充后的代码实现,数据集和原代码请参考:https://github. ...

  10. 基于朴素贝叶斯+Python实现垃圾邮件分类和结果分析

    基于朴素贝叶斯+Python实现垃圾邮件分类 朴素贝叶斯原理 请参考: 贝叶斯推断及其互联网应用(二):过滤垃圾邮件 Python实现 源代码主干来自: python实现贝叶斯推断--垃圾邮件分类 我 ...

最新文章

  1. 给Sqlite数据库设置密码
  2. eclipse运行WordCount
  3. 微软宣布将于08年发布Centro服务器软件
  4. 交叉编译php-5.6.30,linux下用arm-none-linux-gnueabi交叉编译arm内核模块
  5. 我的模块加载系统 v17的入门教程2
  6. pytest框架_Python最火的第三方开源测试框架——pytest
  7. 浅析五种C语言内存分配的方法及区别
  8. 【Java】HashMap源码(1.7)
  9. 大数据_Spark框架_快速上手_使用Idea创建Spark的Maven项目---Spark工作笔记0004
  10. C语言关键字浅析-signed
  11. angular写的移动端模板《一》
  12. 有关sd2068时钟芯片问题
  13. 计算机专业的电脑桌面,win7电脑桌面计算机图标不见了怎么办
  14. 中通快递宣布全球发售定价
  15. Android:证书生成
  16. 什么是土壤电阻率,它如何影响防雷接地
  17. 牛鞭效应matlab代码,牛鞭效应在啤酒游戏中的运用.doc
  18. MathType在word中的安装使用方法(要配合microsoft公式3.0才能使用)(ps:弄得不好可能造成word中Ctrl+V失灵)
  19. 揭秘阿里云WAF背后神秘的AI智能防御体系
  20. 文件上传漏洞绕过手法

热门文章

  1. 电芯容量在前期循环中容量增加_关于锂离子电池使用性能的那些事---容量“跳水”...
  2. 3DGIS+数字孪生技术打造智慧工地监控系统分析
  3. 关于Windows 443端口被占用问题的解决
  4. shapley和树的shap
  5. TBase集群安装配置
  6. 点击折叠菜单(HTML/CSS/JS)
  7. ubuntu12.10 使用lync
  8. 阿里电话面试面试题总结,附答案!
  9. ADS实验报告三:匹配电路的设计与仿真
  10. 菲尼克斯电源模块的安装