文本分类(下)-卷积神经网络(CNN)在文本分类上的应用

1 简介

原先写过两篇文章,分别介绍了传统机器学习方法在文本分类上的应用以及CNN原理,而后本篇文章结合两篇论文展开,主要讲述下CNN在文本分类上的应用。前面两部份内容主要是来自两位博主的文章(文章中已经给出原文连接),是对两篇论文的解读以及总结,基本上阐释了CNN文本分类模型;后半部分讲一个实例和项目实战html

2 论文1《Convolutional Neural Networks for Sentence Classification

模型结构

在短文本分析任务中,因为句子句长长度有限、结构紧凑、可以独立表达意思,使得CNN在处理这一类问题上成为可能,主要思想是将ngram模型与卷积操做结合起来git

2.1 输入层

如图所示,输入层是句子中的词语对应的wordvector依次(从上到下)排列的矩阵,假设句子有 n 个词,vector的维数为 k ,那么这个矩阵就是 n × k 的(在CNN中能够看做一副高度为n、宽度为k的图像)。github

这个矩阵的类型能够是静态的(static),也能够是动态的(non static)。静态就是word vector是固定不变的,而动态则是在模型训练过程当中,word vector也当作是可优化的参数,一般把反向偏差传播致使word vector中值发生变化的这一过程称为Fine tune。(这里若是word vector若是是随机初始化的,不只训练获得了CNN分类模型,还获得了word2vec这个副产品了,若是已经有训练的word vector,那么实际上是一个迁移学习的过程)算法

对于未登陆词的vector,能够用0或者随机小的正数来填充。bash

2.2 第一层卷积层:

输入层经过卷积操做获得若干个Feature Map,卷积窗口的大小为 h ×k ,其中 h 表示纵向词语的个数,而 k 表示word vector的维数。经过这样一个大型的卷积窗口,将获得若干个列数为1的Feature Map。(熟悉NLP中N-GRAM模型的读者应该懂得这个意思)。网络

2.3 池化层:

接下来的池化层,文中用了一种称为Max-over-timePooling的方法。这种方法就是简单地从以前一维的Feature Map中提出最大的值,文中解释最大值表明着最重要的信号。能够看出,这种Pooling方式能够解决可变长度的句子输入问题(由于无论Feature Map中有多少个值,只须要提取其中的最大值)。最终池化层的输出为各个Feature Map的最大值们,即一个一维的向量。app

2.4 全链接+softmax层:

池化层的一维向量的输出经过全链接的方式,链接一个Softmax层,Softmax层可根据任务的须要设置(一般反映着最终类别上的几率分布)。机器学习

2.5 训练方案

在倒数第二层的全链接部分上使用Dropout技术,Dropout是指在模型训练时随机让网络某些隐含层节点的权重不工做,不工做的那些节点能够暂时认为不是网络结构的一部分,可是它的权重得保留下来(只是暂时不更新而已),由于下次样本输入时它可能又得工做了,它是防止模型过拟合的一种经常使用的trikc。同时对全链接层上的权值参数给予L2正则化的限制。这样作的好处是防止隐藏层单元自适应(或者对称),从而减轻过拟合的程度。ide

在样本处理上使用minibatch方式来下降一次模型拟合计算量,使用shuffle_batch的方式来下降各批次输入样本之间的相关性(在机器学习中,若是训练数据之间相关性很大,可能会让结果不好、泛化能力得不到训练、这时一般须要将训练数据打散,称之为shuffle_batch)。函数

项目代码:CNN_sentence 以上部份内容来自:https://www.cnblogs.com/cl1024cl/p/6205012.html

3 论文2《A Sensitivity Analysis of (and Practitioners' Guide to) Convolutional Neural Networks for Sentence Classification

这篇论文主要工做是对“Convolutional Naural Networks for Sentence Classification”这篇论文的模型进行了各类各样的对比试验,并给出了调参的建议,进而获得了一些关于超参数的设置经验。

3.1 调参实验结论:

  • 因为模型训练过程当中的随机性因素,如随机初始化的权重参数,mini-batch,随机梯度降低优化算法等,形成模型在数据集上的结果有必定的浮动,如准确率(accuracy)能达到1.5%的浮动,而AUC则有3.4%的浮动;
  • 词向量是使用word2vec仍是GloVe,对实验结果有必定的影响,具体哪一个更好依赖于任务自己;
  • Filter的大小对模型性能有较大的影响,而且Filter的参数应该是能够更新的;
  • Feature Map的数量也有必定影响,可是须要兼顾模型的训练效率;
  • 1-max pooling的方式已经足够好了,相比于其余的pooling方式而言;
  • 正则化的做用微乎其微。

3.2 建议:

  • 使用non-static版本的word2vec或者GloVe要比单纯的one-hot representation取得的效果好得多;
  • 为了找到最优的过滤器(Filter)大小,可使用线性搜索的方法。一般过滤器的大小范围在1-10之间,固然对- 于长句,使用更大的过滤器也是有必要的;
  • Feature Map的数量在100-600之间;
  • 能够尽可能多尝试激活函数,实验发现ReLU和tanh两种激活函数表现较佳;
  • 使用简单的1-max pooling就已经足够了,能够不必设置太复杂的pooling方式;
  • 当发现增长Feature Map的数量使得模型的性能降低时,能够考虑增大正则的力度,如调高dropout的几率;
  • 为了检验模型的性能水平,屡次反复的交叉验证是必要的,这能够确保模型的高性能并非偶然。

4 一个CNN作文本分类的简单例子

I like this movie very much!
咱们以上图为例,图上用红色标签标注了5部分,结合这5个标签,具体解释下整个过程的操做,来看看CNN如何解决文本分类问题的。

4.1 #sentence

上图句子为“[I like this movie very much!” ,一共有两个单词加上一个感叹号,关于这个标点符号,不一样学者有不一样的操做,好比去除标点符号。在这里咱们先不去除,那么整个句子有7个词,词向量维度为5,那么整个句子矩阵大小为7x5

4.2 #filters

filters的区域大小可使不一样的,在这里取(2,3,4)3种大小,每种大小的filter有两个不一样的值的filter,因此一共是有6个filter。

4.3 #featuremaps

咱们在句子矩阵和过滤器矩阵填入一些值,那么咱们能够更好理解卷积计算过程,这和CNN原理那篇文章同样,

好比咱们取大小为2的filter,最开始与句子矩阵的前两行作乘积相加,获得 0.6 x 0.2 + 0.5 x 0.1 + … + 0.1 x 0.1 = 0.51,而后将filter向下移动1个位置获得0.53.最终生成的feature map大小为(7-2+1x1)=6。 为了得到feature map,咱们添加一个bias项和一个激活函数,好比Relu

4.4 #1max

由于不一样大小的filter获取到的feature map大小也不同,为了解决这个问题,而后添加一层max-pooling,选取一个最大值,相同大小的组合在一块儿 ###4.5 #concat1max 通过max-pooling操做以后,咱们将固定长度的向量给sofamax,来预测文本的类别。

5 文本分类实战

下面是利用Keras实现的CNN文本分类部分代码:

# 建立tensor
print("正在建立模型...")
inputs=Input(shape=(sequence_length,),dtype='int32')
embedding=Embedding(input_dim=vocabulary_size,output_dim=embedding_dim,input_length=sequence_length)(inputs)
reshape=Reshape((sequence_length,embedding_dim,1))(embedding)

# cnn
conv_0=Conv2D(num_filters,kernel_size=(filter_sizes[0],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_1=Conv2D(num_filters,kernel_size=(filter_sizes[1],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_2=Conv2D(num_filters,kernel_size=(filter_sizes[2],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)

maxpool_0=MaxPool2D(pool_size=(sequence_length-filter_sizes[0]+1,1),strides=(1,1),padding='valid')(conv_0)
maxpool_1=MaxPool2D(pool_size=(sequence_length-filter_sizes[1]+1,1),strides=(1,1),padding='valid')(conv_1)
maxpool_2=MaxPool2D(pool_size=(sequence_length-filter_sizes[2]+1,1),strides=(1,1),padding='valid')(conv_2)


concatenated_tensor = Concatenate(axis=1)([maxpool_0, maxpool_1, maxpool_2])
flatten = Flatten()(concatenated_tensor)
dropout = Dropout(drop)(flatten)
output = Dense(units=2, activation='softmax')(dropout)
model=Model(inputs=inputs,outputs=output)
复制代码

运行结果

英文:

准训练结果:验证集76%左右

中文:

准训练结果:验证集91%左右 项目地址:https://github.com/yanqiangmiffy/Text-Classification-Application

6 相关资料

相关文章
相关标签/搜索