深度学习近一段时间以来在图像处理和NLP任务上都取得了不俗的成绩。一般,图像处理的任务是借助CNN来完成的,其特有的卷积、池化结构可以提取图像中各类不一样程度的纹理、结构,并最终结合全链接网络实现信息的汇总和输出。RNN因为其记忆功能为处理NLP中的上下文提供了途径。html
在短文本分析任务中,因为句子句长长度有限、结构紧凑、可以独立表达意思,使得CNN在处理这一类问题上成为可能。论文Convolutional Neural Networks for Sentence Classification(论文做者Yoon Kim)即在这一类问题上作了尝试。首先来看看论文中介绍的模型结构及原理:
python
如图所示,输入层是句子中的词语对应的wordvector依次(从上到下)排列的矩阵,假设句子有 n 个词,vector的维数为 k ,那么这个矩阵就是 n × k 的(在CNN中能够看做一副高度为n、宽度为k的图像)。git
这个矩阵的类型能够是静态的(static),也能够是动态的(non static)。静态就是word vector是固定不变的,而动态则是在模型训练过程当中,word vector也当作是可优化的参数,一般把反向偏差传播致使word vector中值发生变化的这一过程称为Fine tune。(这里若是word vector若是是随机初始化的,不只训练获得了CNN分类模型,还获得了word2vec这个副产品了,若是已经有训练的word vector,那么实际上是一个迁移学习的过程)github
对于未登陆词的vector,能够用0或者随机小的正数来填充。windows
输入层经过卷积操做获得若干个Feature Map,卷积窗口的大小为 h ×k ,其中 h 表示纵向词语的个数,而 k 表示word vector的维数。经过这样一个大型的卷积窗口,将获得若干个列数为1的Feature Map。(熟悉NLP中N-GRAM模型的读者应该懂得这个意思)。网络
接下来的池化层,文中用了一种称为Max-over-timePooling的方法。这种方法就是简单地从以前一维的Feature Map中提出最大的值,文中解释最大值表明着最重要的信号。能够看出,这种Pooling方式能够解决可变长度的句子输入问题(由于无论Feature Map中有多少个值,只须要提取其中的最大值)。最终池化层的输出为各个Feature Map的最大值们,即一个一维的向量。app
池化层的一维向量的输出经过全链接的方式,链接一个Softmax层,Softmax层可根据任务的须要设置(一般反映着最终类别上的几率分布)。机器学习
在倒数第二层的全链接部分上使用Dropout技术,Dropout是指在模型训练时随机让网络某些隐含层节点的权重不工做,不工做的那些节点能够暂时认为不是网络结构的一部分,可是它的权重得保留下来(只是暂时不更新而已),由于下次样本输入时它可能又得工做了,它是防止模型过拟合的一种经常使用的trikc。同时对全链接层上的权值参数给予L2正则化的限制。这样作的好处是防止隐藏层单元自适应(或者对称),从而减轻过拟合的程度。学习
在样本处理上使用minibatch方式来下降一次模型拟合计算量,使用shuffle_batch的方式来下降各批次输入样本之间的相关性(在机器学习中,若是训练数据之间相关性很大,可能会让结果不好、泛化能力得不到训练、这时一般须要将训练数据打散,称之为shuffle_batch)。优化
论文做者也公布了本身的实现程序(下载戳这里),同时有一位同行对上述论文给出了解读并基于上述程序作了对比实验(论文解读戳这里)。本人上面的分析也是基于原始论文和解读,算是锦上添花吧。
参考上述论文和源程序,本人对其在中文短文本分类问题上进行了实验。
Python环境
安装结巴分析的python版本
安装numpy、pandas等一系列科学计算相关库,windows下借助Anaconda进行安装比较方便
安装theano,这个参考各类安装、使用教程吧。
语料库:使用的是搜狗语料库,搜索SogouC.reduced可找到下载链接。
使用jieba分词后将一些实词汉词提取出来,同时,因为CNN输入窗口的大小是必定的,对于长度小于N的句子,使用Pad with zeroes的方式,对于长度大于N的句子,将其切分为若干段长度小于等于N的句子。使用军事和教育两个题材的预料进行处理后,样本总数量大体在2W的样子。
模型结构与trikc均与原文一直,在处理word vector size时,采用原始论文采用的300时,效果不是太理想,将该参数调低,采用szie=50、size=100,最终效果还算能够。同时,feature_map的数量要比word vector size值大一些,以尽量提取更为丰富的句子信息。
下面是训练过程当中的一些结果:
word vector size=50& feature_maps size = 100
来看看训练获得的wordvector在语义空间的映射效果若是,以该词对应的向量空间的余弦积的形式衡量词之间的类似性:
左:word vector size=50 & feature_maps size= 100 右:word vector size=100& feature_maps size = 100
军事题材类的词,语义表达的效果较好,而医疗卫生相关的则效果通常。若是原始预料集更大,可能效果还会进一步提高的。同时,也能够考虑使用word2vec模型训练获得word vector,在使用上述模型训练CNN分类模型,同时更新word vector。
本文同时在知加发表,欢迎围观。
最后,进过本人使用的实验代码可从github下载(Theano),对做者的原始代码作了比较详尽的注释,同时增长汉语的分词预处理模块和后面的word vector展示模块。
我的采用Tensorflow实现的版本:github (Tensorflow版本),欢迎一块儿交流学习~~~