文本分类--CNN

作者: Nlp_小菜 | 来源:发表于2019-01-19 22:35 被阅读41次

    作为一个NLP届的菜鸟,想把自己学到的一点知识写下来,一是帮助自己梳理知识;二是希望能够帮到一些打算入门以及正在入门的NLPer.由于我的文笔挺差的,以及学识有限,有不忍直视的地方,请多包涵。

    github上有很多关于TextCNN的开源项目,从里面可以获得大量练手的数据。我在学TextCNN的时候,是在了解了cnn的基本原理之后,从github上下载了几个我觉得看着比较顺眼的(我就是觉得代码风格比较喜欢)。然后再按照自己的代码风格以及对于代码的理解进行重现。本文重点介绍TextCNN在tensorflow中的实行,所有数据均来自github,已有标签。首先根据实际数据,介绍数据预处理过程;最后说明tensorflow中的CNN实现。

    1.TxetCNN数据预处理

    1.1 词向量

    打算自己训练词向量的同学,可以使用gensim,方便快捷,当然使用tensorflow来做也是可以的。下面是使用gensim训练词向量的代码。

    gensim词向量

    size是词向量的维度,sg=0,是用cbow进行训练,sg=1,使用sg进行训练。

    1.2 文本分词

    有了打标签的文本,接下来当然是要处理它了啊。上代码。。。

    分词处理

    这步的操作主要是对文本分词,然后得到文本列表,标签列表。举个🌰。

    content=[['文本','分词'],['标签','列表'];label=['A','B']

    1.3 建立词典,词典词向量

    不能是个词我就要吧。那怎么办呢?去停用词!去了停用词之后,取文本(这个文本指的是所有文本,包括训练、测试、验证集)中前N个词,表示这N个词是比较重要的,然后保存。之前训练的词向量是个数据量很大集合。很多词,我已经不需要了,我只要这N个词的词向量。同样是上代码。

    词向量

    我提取了文本的前9999个比较重要的词,并按顺序保存了下来。embeddings= np.zeros([10000, 100]) 表示我建立了一个10000个词,维度是100的词向量集合。然后将9999个词在大词向量中的数值,按1-9999的顺序,放入了新建的词向量中。第0项,让它保持是100个0的状态。

    1.4  建立词典

    这部分比较简单,直接上代码。

    建立词典

    注意:词典里面词的顺序,要跟新建的词向量中词的顺序一致。

    1.5 标签词典

    标签词典

    将标签也词典一下。

    1.6 Padding的过程

    padding是将所有句子进行等长处理,不够的在句子最后补0;将标签转换为one-hot编码。

    padding过程

    首先将句子中的词,根据词典中的索引,变成全数字的形式;标签也进行同样处理。然后,根据max_length(句子最大长度)进行padding,得到x_pad,标签转换one-hot格式。好了,到这里文本的预处理,告一段落!

    1.7 读取所需数据

    我们保存了10000词的词向量,我们要读取它,还有处理的句子,我们也要分批,输入进模型。

    读取所需数据

    在代码里,我用一个例子,解释了np.random.permutation的作用。

    2.tensorflow中的TextCNN

    TextCNN过程图

    2.1 定义占位符

    占位符

    2.2 embedding

    embedding

    vocab_size:是词的个数,在这里是10000;

    embedding_size:是词向量尺寸,这里是100;

    embedding_lookup:我把它看成与excel vlookup类似的查找函数,是将embedding中的词向量根据input_x中的数字进行索引,然后填充。比如,input_x中的3,将input_x中的3用embedding中的第三行的100个数字进行填充,得到一个tensor:[batch_size,seq_length,embedding_size].

    因为,卷积神经网络中的,conv2d是需要4维张量的,故用tf.expand_dims在embedding_input最后再补一维。

    3.3 卷积层

    filte 高度设定为【2,3,4】三种,宽度与词向量等宽,卷积核数量设为num_filter。假设batch_size =1,即对一个句子进行卷积操作。每一种filter卷积后,结果输出为[1,seq_length - filter_size +1,1,num_filter]的tensor。再用ksize=[1,seq_length - filter_size + 1,1,1]进行max_pooling,得到[1,1,1,num_filter]这样的tensor.将得到的三种结果进行组合,得到[1,1,1,num_filter*3]的tensor.最后将结果变形一下[-1,num_filter*3],目的是为了下面的全连接。再次有请代码。

    卷积层

    3.4  全连接层

    在全连接层中进行dropout,通常保持率为0.5。其中num_classes为文本分类的类别数目。然后得到输出的结果scores,以及得到预测类别在标签词典中对应的数值predicitons。

    全连接层

    3.5 loss

    这里使用softmax交叉熵求loss, logits=self.scores 这里一定用的是未经过softmax处理的数值。

    loss

    3.6 optimizer

    这里使用了梯度裁剪。首先计算梯度,这个计算是类似L2正则化计算w的值,也就是求平方再平方根。然后与设定的clip裁剪值进行比较,如果小于等于clip,梯度不变;如果大于clip,则梯度*(clip/梯度L2值)。

    optimizer

    3.7 accuracy

    最后,计算模型的准确度。

    accuracy

    3.8 训练模型

    训练与测试

    模型迭代次数为5,每完成一轮迭代,模型保存一次。当global_step为100的整数倍时,输出模型的训练结果以及在测试集上的测试结果。

    训练结果

    一个batch中训练集最好准确度达到98%,同时在测试集上的结果达到100%。接下来,我们看看保存的模型在验证集上的效果。

    3.9 模型验证

    验证集有5000条语句,我用最后一次保存的模型,对5000条句子进行预测,将预测的结果与原标签进行对比,得到验证集上的准确率,结果表明在整个验证集上准确达到96.58%,并输出前10条语句,将预测结果与原结果进行对比。

    部分验证代码 验证结果

    整个模型的流程,分析完毕。流程和文中的TextCNN过程图基本一致。因学识有限,文中难免有描述不对的地方,请各位批评指正。希望我的文章,能够帮到大家。

    本文代码地址:https://github.com/NLPxiaoxu/Easy_TextCnn_Rnn

    参考文献:

    《Convolutional Neural Networks for Sentence Classification》

    https://github.com/cjymz886/text-cnn

    http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow

    相关文章

      网友评论

        本文标题:文本分类--CNN

        本文链接:https://www.haomeiwen.com/subject/pihxyftx.html