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