原文:Understanding Convolutional Neural Networks for NLP

当我们听说卷积神经网络(CNN)时,我们通常会想到计算机视觉。 CNN负责图像分类方面的重大突破,是目前大多数计算机视觉系统的核心,从Facebook的自动照片标签到自动驾驶汽车。

最近,我们也开始将CNN应用于自然语言处理中的问题,并获得了一些有趣的结果。 在这篇文章中,我将尝试总结CNN是什么,以及它们如何在NLP中使用。 CNN背后的直觉对于计算机视觉用例来说有点容易理解,所以我将从那里开始,然后慢慢向NLP迈进。

What is Convolution?

理解卷积的最简单方法是将其视为应用于矩阵的滑动窗口函数。 这是一个满口的,但看着可视化变得非常清楚:

Convolution with 3×3 Filter. Source: http://deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution

想象一下,左边的矩阵代表黑白图像。 每个条目对应一个像素,0表示黑色,1表示白色(对于灰度图像,通常在0到255之间)。 滑动窗口称为内核,过滤器或特征检测器。 在这里,我们使用3×3滤波器,将其元素值与原始矩阵相乘,然后将它们相加。 为了获得完整的卷积,我们通过在整个矩阵上滑动滤波器来为每个元素执行此操作。

您可能想知道您实际上可以做些什么。 以下是一些直观的例子。

使用其相邻值平均每个像素会使图像模糊:

利用像素及其邻居之间的差异来检测边缘:

(为了直观地理解这一点,请考虑图像中光滑的部分会发生什么,其中像素颜色等于其邻居的颜色:添加取消,结果值为0或黑色。如果强度有锐利边缘 ,例如,从白色到黑色的过渡,您会得到很大的差异,并产生白色值)

GIMP手册还有一些其他例子。 为了更多地了解卷积如何工作,我还建议查看Chris Olah关于该主题的帖子。

What are Convolutional Neural Networks?

现在你知道什么是卷积。但CNN呢? CNN基本上只是几层卷积,其中非线性激活函数如ReLU或tanh应用于结果。在传统的前馈神经网络中,我们将每个输入神经元连接到下一层中的每个输出神经元。这也称为完全连接层或仿射层。在CNN中我们不这样做。相反,我们在输入层上使用卷积来计算输出。这导致局部连接,其中输入的每个区域连接到输出中的神经元。每个图层应用不同的过滤器,通常是数百或数千个,如上所示,并结合其结果。还有一些叫做池(子采样)层的东西,但我稍后会介绍。在培训阶段,CNN会根据您要执行的任务自动学习其过滤器的值。例如,在图像分类中,CNN可以学习从第一层中的原始像素检测边缘,然后使用边缘检测第二层中的简单形状,然后使用这些形状来阻止更高级别的特征,例如面部形状在更高层。最后一层是使用这些高级功能的分类器。

这个计算有两个方面值得关注:位置不变性和组合性。 假设您想要对图像中是否有大象进行分类。 因为您要在整个图像上滑动滤镜,所以您并不关心大象的位置。 在实践中,池化还可以为您提供平移,旋转和缩放的不变性,但稍后会有更多内容。 第二个关键方面是(本地)组合。 每个过滤器将较低级别要素的本地修补程序组合为更高级别的表示。 这就是CNN在计算机视觉领域如此强大的原因。 直观地说,您可以构建像素边缘,边缘形状以及形状中更复杂的对象。

那么,这些如何适用于NLP?

代替图像像素,大多数NLP任务的输入是表示为矩阵的句子或文档。 矩阵的每一行对应一个标记,通常是一个单词,但它可以是一个字符。 也就是说,每行是表示单词的向量。 通常,这些向量是word嵌入(低维表示),如word2vec或GloVe,但它们也可以是将单词索引为词汇表的one-hot向量。 对于使用100维嵌入的10个单词的句子,我们将使用10×100矩阵作为输入。 那是我们的“图片”。

在视觉中,我们的滤镜在图像的局部色块上滑动,但在NLP中,我们通常使用在矩阵的整行上滑动的滤镜(单词)。 因此,我们的滤波器的“宽度”通常与输入矩阵的宽度相同。 高度或区域大小可能会有所不同,但一次滑动窗口超过2-5个字是典型的。 将上述所有内容放在一起,NLP的卷积神经网络可能看起来像这样(花几分钟时间尝试理解这张图片以及如何计算维度。您现在可以忽略池化,我们稍后会解释):

Illustration of a Convolutional Neural Network (CNN) architecture for sentence classification. Here we depict three filter region sizes: 2, 3 and 4, each of which has 2 filters. Every filter performs convolution on the sentence matrix and generates (variable-length) feature maps. Then 1-max pooling is performed over each map, i.e., the largest number from each feature map is recorded. Thus a univariate feature vector is generated from all six maps, and these 6 features are concatenated to form a feature vector for the penultimate layer. The final softmax layer then receives this feature vector as input and uses it to classify the sentence; here we assume binary classification and hence depict two possible output states. Source: Zhang, Y., & Wallace, B. (2015). A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification.

我们对计算机视觉的直觉如何? 位置不变性和局部组合性对图像有直观的意义,但对于NLP则不那么重要。 你可能会在句子中出现一个单词。 彼此接近的像素可能在语义上相关(同一对象的一部分),但对于单词而言并非总是如此。 在许多语言中,短语的一部分可以由几个其他单词分开。 组成方面也不明显。 很明显,单词在某些方面构成,例如修饰名词的形容词,但这究竟是如何工作的,更高级别的表示实际上“意味着”并不像计算机视觉案例那样明显。

鉴于这一切,似乎CNN不适合NLP任务。 递归神经网络更直观。 它们类似于我们处理语言的方式(或者至少我们认为我们处理语言的方式):从左到右顺序阅读。 幸运的是,这并不意味着CNN不起作用。 所有模型都错了,但有些模型很有用。 事实证明,应用于NLP问题的CNN表现相当不错。 简单的Bag of Words模型显然过于简单化了不正确的假设,但多年来一直是标准方法,并取得了相当不错的结果。

CNN的一个重要论点是它们很快。 非常快。 卷积是计算机图形的核心部分,在GPU上的硬件级别上实现。 与n-gram之类的东西相比,CNN在表示方面也是有效的。 拥有大量词汇量,计算超过3-grams的任何东西都会很快变得昂贵。 即使谷歌也没有提供超过5-grams的东西。 卷积滤波器自动学习良好的表示,而无需表示整个词汇表。 具有大于5的过滤器是完全合理的。我喜欢认为第一层中的许多学习过滤器捕获与n-gram非常相似(但不限于)的特征,但是以更紧凑的方式表示它们。

CNN Hyperparameters

在解释CNN如何应用于NLP任务之前,让我们看一下构建CNN时需要做出的一些选择。 希望这有助于您更好地了解该领域的文献。

Narrow vs. Wide convolution

当我解释上面的卷积时,我忽略了我们如何应用滤波器的一些细节。 在矩阵的中心应用3×3滤波器工作正常,但边缘怎么样? 如何将滤镜应用于矩阵的第一个元素,该元素在顶部和左侧没有任何相邻元素? 您可以使用零填充。 将落在矩阵之外的所有元素都取为零。 通过这样做,您可以将滤镜应用于输入矩阵的每个元素,并获得更大或相同大小的输出。 添加零填充也称为宽卷积,不使用零填充将是一个窄卷积。 1D中的示例如下所示:

Narrow vs. Wide Convolution. Filter size 5, input size 7. Source: A Convolutional Neural Network for Modelling Sentences (2014)

当您有一个相对于输入大小的大过滤器时,您可以看到广泛的卷积是有用的,甚至是必要的。 在上文中,窄卷积产生大小(7-5)+ 1 = 3的输出,以及宽卷积和大小(7 + 2 * 4-5)+ 1 = 11的输出。 更一般地,输出大小的公式是

Stride Size

你的卷积的另一个超参数是步幅大小,定义你想要在每一步移动过滤器的程度。 在上面的所有示例中,步幅大小为1,并且过滤器的连续应用重叠。 步幅越大,滤波器的应用越少,输出尺寸越小。 以下来自斯坦福大学cs231网站的结果显示,应用于一维输入的步幅大小为1和2:

Convolution Stride Size. Left: Stride size 1. Right: Stride size 2. Source: http://cs231n.github.io/convolutional-networks/

在文献中,我们通常会看到步幅大小为1,但是更大的步幅可能允许您构建一个与递归神经网络类似的模型,即看起来像一棵树。

Pooling Layers

卷积神经网络的一个关键方面是池化层,通常在卷积层之后应用。 池化层对其输入进行子采样。 池化它以将最大操作应用于每个过滤器的结果的最常用方法。 您不一定需要在整个矩阵上进行池化,也可以在窗口上进行池化。 例如,以下显示了2×2窗口的最大池化(在NLP中,我们通常在整个输出上应用池,每个过滤器只产生一个数字):

Max pooling in CNN. Source: http://cs231n.github.io/convolutional-networks/#pool

为什么要池化? 有几个原因。 池化的一个特性是它提供固定大小的输出矩阵,这通常是分类所需的。 例如,如果您有1,000个过滤器并且对每个过滤器应用最大池,则无论过滤器的大小或输入的大小如何,都将获得1000维输出。 这允许您使用可变大小的句子和可变大小的过滤器,但始终获得相同的输出维度以提供给分类器。

池化还会降低输出维数,但(希望)可以保留最显着的信息。 您可以将每个过滤器视为检测特定功能,例如检测该句子是否包含例如“不令人惊讶”的否定。 如果此短语出现在句子中的某处,则将过滤器应用于该区域的结果将产生较大的值,但在其他区域中产生较小的值。 通过执行最大操作,您将保留有关该功能是否出现在句子中的信息,但您正在丢失有关它出现在何处的信息。 但这个关于地方的信息真的没用吗? 是的,这是和一袋n-gram模型正在做的有点类似。 你正在丢失有关地点的全局信息(在句子中发生了什么事情),但你保留了过滤器捕获的本地信息,比如“不惊人”与“惊人的不是”非常不同。

在图像识别中,池化还提供了翻译(移位)和旋转的基本不变性。 当您在一个区域上池化时,即使您将图像移动/旋转几个像素,输出也将保持大致相同,因为无论如何,最大操作将选择相同的值。

Channels

我们需要理解的最后一个概念是通道。 通道是输入数据的不同“视图”。 例如,在图像识别中,您通常具有RGB(红色,绿色,蓝色)通道。 您可以跨渠道应用卷积,具有不同或相等的权重。 在NLP中你可以想象有各种各样的频道:你可以有不同的词汇嵌入的单独频道(例如word2vec和GloVe),或者你可以有一个用不同语言表示的同一个句子的频道,或用不同的方式表达。

Convolutional Neural Networks applied to NLP

现在让我们看一下CNN对自然语言处理的一些应用。 我会尝试总结一些研究结果。 总是我会想念许多有趣的应用程序(请在评论中告诉我),但我希望至少涵盖一些更受欢迎的结果。

CNN的最自然适合似乎是分类任务,例如情绪分析,垃圾邮件检测或主题分类。 卷积和池化操作会丢失有关单词本地顺序的信息,因此在PoS标记或实体提取中的序列标记有点难以适应纯CNN体系结构(尽管不是不可能,但您可以向输入添加位置特征)。

[1]评估各种分类数据集的CNN架构,主要包括情感分析和主题分类任务。 CNN架构在数据集中实现了非常好的性能,并且在一些数据集上实现了新的最新技术。 令人惊讶的是,本文中使用的网络非常简单,这就是它的强大功能。输入层是一个由连接的word2vec字嵌入组成的句子。 接下来是带有多个滤波器的卷积层,然后是最大池层,最后是softmax分类器。 本文还以静态和动态词嵌入的形式对两个不同的通道进行了实验,其中一个通道在训练期间被调整而另一个通道没有被调整。 之前在[2]中提出了类似但更复杂的架构。 [6]添加一个额外的层,对该网络架构执行“语义聚类”。

Kim, Y. (2014). Convolutional Neural Networks for Sentence Classification

[4]从头开始训练CNN,不需要像word2vec或GloVe这样的预训练的单词向量。 它将卷积直接应用于one-hot向量。 作者还为输入数据提出了一种节省空间的词袋式表示,减少了网络需要学习的参数数量。 在[5]中,作者使用另外的无监督“区域嵌入”扩展了模型,该区域嵌入是使用CNN预测文本区域的上下文来学习的。 这些论文中的方法似乎适用于长篇文本(如电影评论),但它们在短文本(如推文)上的表现并不清楚。 直观地说,对于短文本使用预先训练的单词嵌入将比在长文本中使用它们产生更大的收益是有意义的。

构建CNN架构意味着有许多超参数可供选择,其中一些我在上面介绍:输入表示(word2vec,GloVe,one-hot),卷积滤波器的数量和大小,池化策略(最大值,平均值)和激活函数(ReLU,tanh)。 [7]对CNN架构中不同超参数的影响进行了实证评估,研究了它们对多次运行的性能和方差的影响。如果您希望实施自己的CNN进行文本分类,那么使用本文的结果作为起点将是一个很好的主意。突出的一些结果是最大池化总是超过平均池化,理想的过滤器大小是重要的但是依赖于任务,并且正则化似乎在所考虑的NLP任务中没有大的不同。这项研究的一个警告是,所有数据集在文档长度方面都非常相似,因此相同的指南可能不适用于看起来相当不同的数据。

[8]探讨了关系提取和关系分类任务的CNN。 除了单词向量之外,作者还使用单词与感兴趣实体的相对位置作为卷积层的输入。 该模型假设给出了实体的位置,并且每个示例输入包含一个关系。 [9]和[10]探索了类似的模型。

另一个有趣的CNN在NLP中的使用案例可以在微软研究院的[11]和[12]中找到。 这些论文描述了如何学习可用于信息检索的语义有意义的句子表示。 论文中给出的示例包括基于他们当前正在阅读的内容向用户推荐可能有趣的文档。 基于搜索引擎日志数据训练句子表示。

大多数CNN架构以这种或那种方式学习单词和句子的嵌入(低维表示)作为其训练过程的一部分。 并非所有论文都关注训练的这一方面或调查学习嵌入的意义。 [13]提出了一种CNN架构来预测Facebook帖子的主题标签,同时为单词和句子生成有意义的嵌入。 然后,这些学习的嵌入成功应用于另一个任务 - 向用户推荐可能有趣的文档,并根据点击流数据进行训练。

Character-Level CNNs

到目前为止,所有呈现的模型都基于单词。 但也有研究将CNN直接应用于角色。 [14]学习字符级嵌入,将它们与预先训练的字嵌入连接起来,并使用CNN进行词性标注。 [15] [16]探讨了使用CNN直接从角色学习,而无需任何预先训练的嵌入。 值得注意的是,作者使用了一个总共9层的相对较深的网络,并将其应用于情感分析和文本分类任务。 结果表明,直接从字符级输入进行学习对大型数据集(数百万个示例)非常有效,但在较小数据集(数十万个示例)上表现不佳。 [17]探讨了将字符级卷积应用于语言建模,使用字符级CNN的输出作为每个时间步的LSTM的输入。 相同的模型适用于各种语言。

令人惊奇的是,基本上所有上述论文都是在过去1  -  2年内发表的。 显然,CNN之前在NLP上的表现非常出色,就像Scratch的自然语言处理(几乎)一样,但新结果的发展速度和发布的最新系统显然正在加速发展。

Questions or Feedback? Let me know in the comments. Thanks for reading!

Paper References