纵观机器学习或者深度学习算法,都没有某一个算法只适用于某一个领域,大多数在某个领域取得显著成果的算法,稍加修改后在别的领域依旧能够取得非常不错的结果。我们知道卷积神经网络(CNN)广泛用于计算机视觉中,大约从2014年开始ImageNet参赛队伍提交的模型基本都是基于CNN的。在卷积神经网络在图像领域取得巨大成果后,有研究人员开始在自然语言处理领域开始使用卷积神经网络,早期的研究是在句子分类任务上做的,基于CNN的模型取得了非常显著的效果,这也表明了CNN同样适用于NLP领域的一些问题【PS,附上一个彩蛋,这里有一个用Theano实现的CNN模型GRU-or-CNN(觉得不错记得加星哟),可以对两个有关系的句子进行建模】。同样的,我们知道NLP中最常见的深度学习模型是循环神经网络(RNN),这是一个对序列进行建模的模型,因而这一模型在语音处理领域也有广泛的应用,其实也有人尝试过在图像处理领域使用RNN模型,比如这篇论文《ReNet: A Recurrent Neural Network Based Alternative to Convolutional Networks》。由此可见,CNN、RNN这些深度学习算法并没有领域之分,同样传统的机器学习算法也一样,比如最常见的分类模型SVM,只要是分类任务基本都可以用SVM,无论是在图像还是自然语言领域。
下面我们就来看一些卷积神经网络在NLP中的应用以及所取得的显著效果:
- 《A Convolutional Neural Network for Modelling Sentences》,这篇论文应该算是比较早期在NLP任务中运用卷积神经网络的了,这是ACL2014年的一篇论文。论文中提到CNN模型的一个优势就是不依赖于parse树,并且很容易适用于任何语言。这篇论文的一个创新点在于动态pooling技术,即在做max pooling的时候不是只取最大值,而是取k-max的值。这里插入一句,关于CNN中max pooling的一些介绍,请参考这篇博客《自然语言处理中CNN模型几种常见的Max Pooling操作》,这篇博客对常见几种max pooling方法都有很详细的介绍。对于这篇论文,还有一点需要注意的,就是论文中的模型是针对词向量的每一维进行卷积的,而后续的其他模型一般都是对整个词向量进行卷积的(即卷积窗口的长度为词向量维度),这一点也可以从如下模型示意图中看出,
- 《Convolutional Neural Networks for Sentence Classification》,这是EMNLP2014的一篇论文。论文中基于CNN的模型和上一篇论文中的CNN不太一样,第一个是并没有采用动态pooling的技术,第二卷积窗口的长度为词向量的维度,这两点都可以从模型示意图中看出来,
具体的操作为,假如卷积窗口宽度为m,那么取m个连续的词,将他们对应的词向量连接在一起得到一个[latex]m*d[/latex]维的向量[latex]\mathbf{x}_{i:i+m-1}[/latex]([latex]d[/latex]表示词向量维度)。然后向量[latex]\mathbf{x}_{i:i+m-1}[/latex]与卷积核w相乘(w也是一个向量),[latex]c_i=f(\mathbf{w}{\cdot}\mathbf{x}_{i:i+m-1}+b)[/latex],窗口滑动得到[latex]\mathbf{c}=[c_1,c_2,…,c_{n-m+1}][/latex],再对[latex]\mathbf{c}[/latex]做max pooling得到一个值,假设现在又K个卷积核,那么最后得到K维的向量。很显然,这里做pooling操作的目前就是处理不同长度的句子,使得无论句子长度为多少,卷积核宽度是多少,最终到得到定长的向量表示,同时max pooling也是capture最重要的特征信息。作者在7个数据集上与14个模型进行了比较,这7个数据集全是句子分类任务(包括电影reviews,question分类,以及MP3的reviews)。通过大量的实验证明了CNN模型适用于多种任务,而且效果非常显著,相比于传统方法不用进行繁琐的特征工程而且也不需要parse树。这篇论文还给出了一个非常好的结论,模型输入预先训练好的词向量比随机初始化词向量效果要好很多,目前大家使用deep learning都会输入预先训练好的词向量。 - 《Document Modeling with Gated Recurrent Neural Network for Sentiment Classification》,这是EMNLP2015的一篇论文,论文主要是对文本进行建模,然后分析文本的情感极性。作者采用了两层神经网络来学习文本的表示,即先用CNN来学习句子的表示,在用一个双向的RNN来学习文本的表示,最后一个softmax层得到情感极性,模型结构如下图,
模型中从词到句子表示的CNN模型采用的第二篇论文中的CNN模型,而且作者分别设置窗口宽度为1、2、3,这正好类似于uni-grams,bi-grams,和tri-grams。 - 《Answer Sequence Learning with Neural Networks for Answer Selection in Community Question Answering》,这篇论文同样同时使用了CNN和RNN,不过是对不同的内容进行建模的。论文所正对的任务是answer selection,对于一个question,有很多answers作为候选,模型需要选出匹配question的answer,同时该论文所针对的answers还有一个特定是这些answers之间存在对话关系(即关于该question的一个讨论,比如一些论坛,同一个问题下有很多回答,而这些回答存在一个回复对话关系)。作者将这一任务看出是一个序列标注任务,即对所有answers打标签。具体算法步骤为,先用CNN学习question和一个answer之间的联合表示,然后将这个表示作为RNN的输入,学习answers之间的序列关系,RNN输出每个answers的标签(good,bad,和potential)。
说了这么多,大家对CNN模型也有了一个大致的认识,下面通过一些代码来更加直观的理解CNN,代码用theano实现。(代码来自CNNModel.py,略有改动)
|
|
简单解读一下这段代码,24行的Convolution函数是这个类的核心函数,输入的xe变量需要是一个三维tensor,每一个元素都是一个单行矩阵,而且需要包含至少3个元素。ConvLayer1,ConvLayer2,和ConvLayer3本别对应窗口宽度为1,2,3的卷积操作。这里需要重点提一下33行的代码,T.mean(T.concatenate([hidden1, hidden2, hidden3], axis=0), axis=0)
,其实这个操作就对hidden1,hidden2,hidden3求平均,按理说直接采用被注释掉的34行的写法是最简单的,但是如果采用34行的写法,在求梯度时会报错(错误信息大意是在构建图的时候会引入环,“This substitution would insert a cycle in the graph”)。所以不得已采用了33行这种复杂的写法,具体为什么会出现这个原因我至今还没有弄清楚,但这至少告诉了我们一点,就是尽可能用theano的函数来实现一些计算,因为这些函数的具体求导形式或构建网络图theano肯定是定义好了的,所以不容易出错。顺带我们再分析一下输出的维度吧,首先xe是一个3维tensor,所以每次传给ConvLayer的是一个矩阵,同时ConvLayer返回的也是一个矩阵,因此_res1将是一个3维tensor,然后T.max操作会降一维,得到的hidden1是一个矩阵,最后的T.mean再降一维,所以返回的将是一个向量(只有一维)。
以上内容全是我个人观点和总结,如有错误欢迎指正和讨论。