文本分类--CNN

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

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

1.TxetCNN数据预处理

1.1 词向量

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

《文本分类--CNN》 gensim词向量

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

1.2 文本分词

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

《文本分类--CNN》 分词处理

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

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

1.3 建立词典,词典词向量

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

《文本分类--CNN》 词向量

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

1.4  建立词典

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

《文本分类--CNN》 建立词典

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

1.5 标签词典

《文本分类--CNN》 标签词典

将标签也词典一下。

1.6 Padding的过程

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

《文本分类--CNN》 padding过程

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

1.7 读取所需数据

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

《文本分类--CNN》 读取所需数据

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

2.tensorflow中的TextCNN

《文本分类--CNN》 TextCNN过程图

2.1 定义占位符

《文本分类--CNN》 占位符

2.2 embedding

《文本分类--CNN》 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],目的是为了下面的全连接。再次有请代码。

《文本分类--CNN》 卷积层

3.4  全连接层

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

《文本分类--CNN》 全连接层

3.5 loss

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

《文本分类--CNN》 loss

3.6 optimizer

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

《文本分类--CNN》 optimizer

3.7 accuracy

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

《文本分类--CNN》 accuracy

3.8 训练模型

《文本分类--CNN》 训练与测试

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

《文本分类--CNN》 训练结果

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

3.9 模型验证

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

《文本分类--CNN》 部分验证代码
《文本分类--CNN》 验证结果

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

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

参考文献:

《Convolutional Neural Networks for Sentence Classification》

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

Implementing a CNN for Text Classification in TensorFlow

    原文作者:Nlp_小菜
    原文地址: https://www.jianshu.com/p/f95d472b13ea
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞