[译]理解应用于NLP的CNN
注:本文译自http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/,仅为个人学习,谬误之处,欢迎评论指正。
[译文]
理解应用于自然语言处理的卷积神经网络
当听到卷积神经网络(CNN)时,我们会自然地联想到计算机视觉。CNN是图像分类的几个主要突破之一,并且是当今大多计算机视觉系统的核心算法,从facebook的图片自动标注到无人驾驶汽车。
最近以来,我们开始将CNN应用在自然语言处理(NLP)领域的一些问题,并取得了一些有意思的成果。本文将试着总结什么是CNN,如何将CNN应用在NLP方面。CNN背后的直观感知在计算机视觉用例上更易于理解,所以我将从这里开始,然后逐渐转向NLP。
什么是卷积?
对我来说理解卷积的最简单的方式是将它相像成一个应用于矩阵的滑动窗口函数。以上是描述,看一下可视化表示就会更加清楚:

3×3过滤器的卷积. 来源: http://deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution
想象左边的矩阵表示一幅黑白图像,每个实体对应一个像素,0表示黑,1表示白(灰度图像灰度值,典型地位于0-255之间)。滑动窗口叫做核,过滤器,或特征检测器。这里我们用一个3×3的过滤器,用初始矩阵逐元素乘以该过滤器,然后将结果累加。为了得到完整的卷积,我们在整个矩阵上滑动过滤器,针对每个元素进行计算。
你可能对你能用它来做什么感到困惑,下面是一些直观的例子。
对每个像素与其邻域像素值求平均值以模糊图像:

用一个像素与其邻域的差别来检测边缘:
(要直观地理解,考虑图像中平滑部分,其中像素颜色等于其邻域颜色:加法取消,结果值为0或黑色。 如果存在尖锐的边缘,例如从白色到黑色的过渡,则会产生较大的差异和白色的结果)

GIMP 手册 中还有几个其他例子。要理解更多关于卷积如何工作,还推荐查阅Christ Olah的文章 《理解卷积》。
什么是卷积神经网络?
现在大家知道什么是卷积了。但是什么是卷积神经网络呢?CNN基本而言是将非线性激活函数,如 ReLU 或 tanh 应用于结果的几层卷积。在一个传统的前向反馈神经网络中,我们将每个输入神经元与每个输出神经元在下一层进行联结。这又称为全连接层,或仿射层。在CNN中我们不这么做,取而代之的是,我们在输入层上使用卷积来计算出输出。这就导致了局部连接,其中输入的每个区域都与输出的一个神经元连接。 每层使用不同的过滤器,通常有成百上千个如上所示的滤波器,并合并它们的结果。还有个成为pooling(子采样)的层,这将在后面涉及到。在训练阶段,一个CNN自动学习它的滤波器的值,这些滤波器基于你想要完成的任务。例如,在图像分类中,一个CNN可以在第一层从原始像素中学习检测边缘,然后在第二层中使用边缘检测简单形状,再然后使用形状来检测更高级的特征,如较高层次中的面部形状等。最后一层是使用这些高级特征的分类器。
该计算中有2方面值得注意:地点不变 和 组合. 我们假设你想区分图像中是否有一头大象,因为你在整幅图像上滑动你的滤波器,你不关心大象会出现在哪里。在实际中,pooling还对翻译,旋转和缩放以及其它更多方面也带来不变性。第二个主要方面是(局部)组合。每个过滤器组成一个由低级特征转化为高级表示的一个局部补丁。这就是为何CNN在计算机视觉方面如此强大。它对从像素中提取边缘信息,从边缘信息提取形状信息,以及从形状信息中提取更为复杂的对象信息提供了直观概念。
那么,这些怎么应用到NLP?
不同于图像像素,大多数NLP任务的输入是表示为矩阵的句子或文档,矩阵的每行对应一个符号,通常是一个词,但也可能是一个字符。即,每行是一个代表一个词的向量。通常而言,这些向量是像word2vec或GloVe的词嵌入,但是它们可能是将单词索引到词汇表的one-hot向量。对于一个10个词的句子使用100维嵌入,我们将拥有一个10×100的矩阵作为输入,这就是我们的“图像”。
在视觉处理中,我们的过滤器在一幅图像的本地补丁上滑动。但是在NLP中我们通常使用滤波器在矩阵(词)的完整行上滑动,这样我们的过滤器“宽度”通常与输入矩阵的宽度相同,其高度,或称区域大小,可能有所不同,但通常滑动窗口一次会在2-5个词上进行滑动。综上所述,一个应用于NLP的卷积神经网络看起来可能像这样(花几分钟理解这幅图以及维度是如何被计算的;目前可先忽略pooling,我们将在下文解释):

一个句子分类CNN的架构图。这里我们描绘了3个过滤器区域大小:2,3和4。每个区域有2个过滤器,每个过滤器在句子矩阵上执行卷积计算并生成(变长)特征映射。然后对每个映射执行1-max pooling,即记录下每个特征映射的最大数值。这样从6个映射生成了一个单变量特征向量,这6个特征被联结起来为倒数第二层形成一个特征向量。最后softmax层接收到这个特征向量作为输入,并用它来对句子进行分类;这里我们假设为二元分类,因此描述了2种输出状态。来源:Zhang, Y., & Wallace, B. (2015). A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification.
那么我们对计算机视觉的那些直觉如何呢? 地点不变和局部组合是图像的直观感觉,但对NLP没太大意义。你可能确实关注句子中某个词出现在哪里,相邻的像素与语义相关的词类似(某种程度上是同一对象),但是对词而言并非可一直这样简单类比。在许多语言中,部分短语可能被几个其它词分开,组合方面也不是很明显。清楚的是,词以一些方式组合,例如形容词修饰名词,但这些规则能在多大程度上得出高级别表示并没有计算机视觉的案例那么明显。
考虑到这些,CNN对NLP任务将不太合适。递归神经网络(Recurrent Neural Networks, RNN)有更直观的意义,它们与我们如何处理语言(或我们认为我们如何处理语言)的方式类似:从左往右顺序地读。幸运的是,这并非意味着CNN无效,所有模型都不对,但对的就有效。结果证明CNN应用于NLP问题表现相当好,简单的 词袋模型 是一个明显的带有错误假设的过度简化模型,但多年来一直是标准方案并有着相当不错的结果。
关于CNN的一个较大的争论是它很快,非常快。卷积是计算机图形学的一个核心部分,并在GPU硬件级别上实现。与n-grams之类相比,CNN在多项表示方面还是有效的。用一个大型词汇表,计算多于3-grams的东西将变得十分耗资源,即使google也不能提供超过5-grams的任何计算。卷积过滤器自动学习好的表示,不需要表示整个词汇表,大于5元的滤波器是完全合理的。我想第一层的许多训练滤波器与n元捕获的特征十分相似(但没有限制),但其表示更紧凑。
CNN 超参数
在开始解释CNN如何应用于NLP任务之前,让我们看看在构建一个CNN时需要做哪些选择。希望这将帮助你更好地理解该领域文化。
窄卷积 vs. 宽卷积
在上面解释卷积时,我忽略了一个小细节:如何使用滤波器。在矩阵中心使用一个3×3滤波器效果不错,但在矩阵边缘效果如何呢?你将如何对矩阵的第一个元素使用滤波器呢?在它们的上部和左部都没有邻接元素。你可以使用零对齐,落在矩阵外的所有元素都被记为零,这样就可以对输入矩阵的每个元素都应用过滤器,获得一个较大或相等的输出。增加零对齐被称为宽卷积,未增加零对齐称为窄卷积。 以下是一个一维的例子:

窄卷积 vs. 宽卷积。过滤器大小为5,输入大小为7。来源:句子建模的一个卷积神经网络 (2014)
可以看出当过滤器大小比输入大小大时,宽卷积是有用甚至是必要的。上图中,窄卷积产生输出的大小为 ,宽卷积产生输出的大小为
。总体而言,输出大小的公式为
。
步幅
卷积计算的另一个超参数是步幅,定义为过滤器每一步的偏移量。上面例子中步幅均为1,过滤器连续应用产生叠加;较大的步幅会使过滤器应用次数减少,输出大小也减少。来自斯坦福大学课程cs231说明了 应用于一维输入的步幅分别为 1 和 2 的情况:

卷积步幅。左:步幅为1。右:步幅为2。来源: http://cs231n.github.io/convolutional-networks/
我们常见的步幅一般为1,但一个较大的步幅将使你能构建一个类似Recursive Neural Network的模型,即,看起来像树型结构。
Pooling层
CNN的一个主要方面是Pooling层,一般在卷积层之后应用。Pooling层对输入进行子采样。最通常的一个Pooling方法是对每次过滤结果取最大值操作。不必要对整个矩阵进行pool,还可以在一个窗口范围内进行pool,例如,下图展示对一个 2×2 窗口进行最大化子采样 (在NLP中,我们通常针对整个输出进行Pooling,针对每个过滤器只产生一个值):

CNN中的最大化pool。来源: http://cs231n.github.io/convolutional-networks/#pool
为何要进行Pooling? 有以下几个原因。pooling的一个属性是它提供了一个固定大小的输出矩阵,这是分类时的一个普遍要求。例如,若你有1000个过滤器,对每个都使用最大化pooling,你将得到一个1000维的输出,不管过滤器大小或输入的大小。这允许你使用长度不一的句子,以及大小变化的过滤器,但一直获得相同维度的输出来提供给分类器。
Pooling还减少了输出维度,但(希望)保持了最重要的信息。你可以将每个过滤器想象成用于检测某个特定特征,如检测句子中是否含有一个负面情绪词,如“not amazing”。如果句子中某处出现该短语,在该处应用这个过滤器时会产生一个大值,在其它区域应用这个过滤器时会产生一个小值。通过执行max操作,可以保留关于句子中是否含有所检测特征的信息,但是将丢失该特征具体在何处出现的信息。但是位置信息并不是很有用,是吗?是的,这与一个n-grams模型词袋比较相似。你将失去关于位置(某词在句中何处出现)的全局信息,但将保留过滤器捕捉到的信息,如“not amazing” 与 “amazing not”有很大区别。
在图像识别中,Pooling还对翻译(偏移)和轮转提供了一个不变性。 当你在某个区域进行Pooling操作时,即使将图像的几个像素进行偏移/旋转,输出也将会保持近似相同,因为max操作将获得相同的值。
通道
我们需要理解的最后一个概念是通道。通道是输入数据的不同的“视”。例如,图像识别中一般会有RGB通道。可以将卷积应用在不同通道,无论高度是否相同。在NLP中你也可以想象有不同通道:你可能对不同的词嵌入(如word2vec和GloVe)拥有不同通道。 或对相同句子以不同语言,或不同表达方式的短语等获得一个通道。
应用于NLP的卷积神经网络
现在让我们来看看CNN在自然语言处理中的一些应用。我将尽量总结一些研究成果,但总是可能会遗漏一些有意思的应用(请大家在评论里指出来),但我希望覆盖至少几个最流行的成果。
CNN的最自然的使用方式是在一些分类任务上,例如情感分析,垃圾邮件识别或主题分类等。由于卷积和pooling操作会丢掉局部词序信息,导致词性标注或实体提取里的顺序标注比较难于通过单纯的CNN架构(但不是不可能,可以在输入里添加位置特征)来实现。
[1] 评价不同分类数据集上的CNN架构,大多由情感分析和主题分类任务组成。CNN架构在不同数据集上都获得非常好的性能,在几个数据集上刷新了最佳性能。令人惊讶的是,本文中使用的网络相当简单,这就是它的强大之处。输入层是一个联结了word2vec词嵌入的句子,然后是一个多过滤器的卷积层,然后是max-pooling层, 最后是softmax分类器。论文还用了2个分别以静态和动态词嵌入组成的不同通道来实验,一个通道在训练时调整,另一个没有。[2]提出了一个相似但更为复杂的架构 。[6]在本网络架构基础上增加了一个附加层,来执行“语义聚类”。

Kim, Y. (2014). Convolutional Neural Networks for Sentence Classification
[4] 从头开始训练了一个CNN,不需要预训练词向量如word2vec或GloVe。它将卷积直接应用在one-hot向量上。作者还提出了一个省空间的类"词袋"输入数据表示方式,减少了网络学习所需的参数数目。在[5]中,作者扩展了带有附加的非监督的"区域嵌入"模型,使用CNN学习来预测文本区域的上下文。这些论文方法看起来都对长文本(如电影评论)效果良好,但是它们在短文本(如推特文本)上的性能尚不清楚。直观上看,对短文本使用预训练的词嵌入将比针对长文本能产生更好效果。
构建一个CNN架构意味着有许多超参数需要选择,上文已提及的有: 输入指代(word2vec, GloVe, one-hot),过滤器的数量和大小,pooling策略(max, average),以及激活函数(ReLU, tanh)等。[7] 针对CNN架构中的不同超参数影响做了一个经验评估,调查了它们在多次运行中的性能和变化影响。如果你希望实现自己的文本分类CNN架构,使用该文中的结果作为起点会是个相当不错的主意。几个突出的结果包括,max-pooling 总是优于平均值pooling;理想的过滤器大小很重要,但随任务而不同;正则化看起来在NLP任务中没啥太大影响。该研究的一个附注是,所有数据集在文本长度上十分相似,所以这些指导意见可能不适用于看起来区别很大的数据。
[8] 探索了关系提取和关系分类任务中的CNN。除词向量外,作者还将词对于感兴趣的实体的相对位置作为输入提供给卷积层。这个模型假设实体位置已经给出,且每个输入的例子含有一个关系。[9]和[10]探索了相似的模型。
CNN的另一个有趣的用例可在[11]和[12]中看到,来自于微软研究院。这些论文描绘了如何学习可用于信息获取的句子有意义的语义表达。论文给出的例子包括基于用户正在阅读的文档来推荐潜在感兴趣的文档。句子表示是基于搜索引擎日志数据进行训练。
大多数CNN架构以这样那样方式学习词和句子嵌入(低维表示)作为它们的训练过程。但不是所有论文都关注了训练中的这个方面或者调查了训练嵌入有多少意义。[13]提供了一个针对facebook帖子预测#标签的CNN架构,同时对词和句子生成有意义的嵌入,然后这些学习得到的嵌入内容被成功应用于另一个任务——基于点击流数据进行训练,推荐潜在感兴趣的文档给用户。
字符级别的CNN
目前为止,所有模型都基于词,但已经有研究涉及到直接将CNN应用于字符。[14]学习了字符级别嵌入,与预训练的词嵌入进行连接,然后使用CNN进行词性标注。[15][16]探索了直接使用CNN进行学习,不需要任何预训练的嵌入。值得注意的是,作者使用了一个相对很深的网络,一共9层,应用到情感分析和文本分类任务。结果显示直接从字符级输入进行学习在大数据集(上百万例子)上效果良好,但在较小数据集(上万例子)上表现差于更为简单的模型。[17]探索将字符级别卷积应用于语言建模,在每一步使用字符级CNN的输出作为LSTM的输入,同样的模型用于不同语言。
令人惊异的是基本上上述所有论文都是过去1-2年发表的,当然以前也有关于CNN应用于NLP方面的很好的工作,如 Natural Language Processing (almost) from Scratch,但是新成果和时下最优系统发表的步伐明显加快了。
参考文献
- [1] Kim, Y. (2014). Convolutional Neural Networks for Sentence Classification. Proceedings of the 2014 Conference on Empirical Methods in Natural Language Processing (EMNLP 2014), 1746–1751.
- [2] Kalchbrenner, N., Grefenstette, E., & Blunsom, P. (2014). A Convolutional Neural Network for Modelling Sentences. Acl, 655–665.
- [3] Santos, C. N. dos, & Gatti, M. (2014). Deep Convolutional Neural Networks for Sentiment Analysis of Short Texts. In COLING-2014 (pp. 69–78).
- [4] Johnson, R., & Zhang, T. (2015). Effective Use of Word Order for Text Categorization with Convolutional Neural Networks. To Appear: NAACL-2015, (2011).
- [5] Johnson, R., & Zhang, T. (2015). Semi-supervised Convolutional Neural Networks for Text Categorization via Region Embedding.
- [6] Wang, P., Xu, J., Xu, B., Liu, C., Zhang, H., Wang, F., & Hao, H. (2015). Semantic Clustering and Convolutional Neural Network for Short Text Categorization. Proceedings ACL 2015, 352–357.
- [7] Zhang, Y., & Wallace, B. (2015). A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification,
- [8] Nguyen, T. H., & Grishman, R. (2015). Relation Extraction: Perspective from Convolutional Neural Networks. Workshop on Vector Modeling for NLP, 39–48.
- [9] Sun, Y., Lin, L., Tang, D., Yang, N., Ji, Z., & Wang, X. (2015). Modeling Mention , Context and Entity with Neural Networks for Entity Disambiguation, (Ijcai), 1333–1339.
- [10] Zeng, D., Liu, K., Lai, S., Zhou, G., & Zhao, J. (2014). Relation Classification via Convolutional Deep Neural Network. Coling, (2011), 2335–2344.
- [11] Gao, J., Pantel, P., Gamon, M., He, X., & Deng, L. (2014). Modeling Interestingness with Deep Neural Networks.
- [12] Shen, Y., He, X., Gao, J., Deng, L., & Mesnil, G. (2014). A Latent Semantic Model with Convolutional-Pooling Structure for Information Retrieval. Proceedings of the 23rd ACM International Conference on Conference on Information and Knowledge Management – CIKM ’14, 101–110.
- [13] Weston, J., & Adams, K. (2014). # T AG S PACE : Semantic Embeddings from Hashtags, 1822–1827.
- [14] Santos, C., & Zadrozny, B. (2014). Learning Character-level Representations for Part-of-Speech Tagging. Proceedings of the 31st International Conference on Machine Learning, ICML-14(2011), 1818–1826.
- [15] Zhang, X., Zhao, J., & LeCun, Y. (2015). Character-level Convolutional Networks for Text Classification, 1–9.
- [16] Zhang, X., & LeCun, Y. (2015). Text Understanding from Scratch. arXiv E-Prints, 3, 011102.
- [17] Kim, Y., Jernite, Y., Sontag, D., & Rush, A. M. (2015). Character-Aware Neural Language Models.

浙公网安备 33010602011771号