传统的自然语言处理模型
- 1.传统的词袋模型或者连续词袋模型(CBOW)都可以通过构建一个全连接的神经网络对句子进行情感标签的分类,但是这样存在一个问题,我们通过激活函数可以让某些结点激活,但由于在这样网络构建里,句子中词语的顺序被忽略,也许同样两个句子都出现了not和hate但是一个句子(I do not hate this movie)表示的是good的情感,另一个句子(I hate this movie and will not choose it)表示的是bad的情感。其实很重要的一点是在刚才上述模型中我们无法捕获像not hate这样由连续两个词所构成的关键特征的词的含义。
- 2.在语言模型里n-gram模型可以用来解决上面的问题的,想法其实就是将连续的两个词作为一个整体纳入到模型中,这样确实能够解决我们刚才提出的问题,加入bi-gram,tri-gram可以让我们捕捉到例如“don’t love”,”not the best”.但是新的问题是,如果我们使用多元模型,实际训练时的参数是一个非常大的问题,因为假设你有20000个词,加入bi-gram实际上你就要有400000000个词,这样参数训练显然是爆炸的。另外一点,相似的词语在这样的模型中不能共享例如参数权重等,这样就会导致相似词无法获得交互信息。
自然语言处理中的卷积神经网络
单层CNN
假设词向量$x_i∈R^k$,那么n个单词的句子可视作词向量(列向量)的按列拼接。对于h个单词上的卷积滤波器w∈$R^{hk}$,比如k=2,n=5,h=3,下图就是NLP中的单层CNN:
也就是说,每相邻3个词语的组合对应卷积结果中的一个标量。卷积滤波器的权值w也是一个向量,最终得到每个卷积结果$c_i=f(w^Tx_{i:i+h-1}+b)$,组合得到向量$c=[c_1,c_2,..c_{n-h+1}]∈R^{n-h+1}$
对最后两个词语,由于不够长(h=3),常见的技巧是补零:
一个滤波器就是一个向量,卷积运算的子运算实际上就是与某个n-gram的内积,内急代表相似性。于是卷积核实际上在挑选与自己相似的那种pattern,比如正面情感的n-gram。
池化
卷积不是最终目的,最终目的是将卷积结果输入到其他网络中去。在不补零的情况下,卷积结果c中有n-h+1个数,与n有关;而我们想要一个定长的输入。一个解决办法是max-pooling,输入是CNN结果$c∈R^{n-h+1}$,输出是一个标量$\hat{c}=max{c}$,其中$\hat{c}∈R$
当然也可以用min,但是RELU时经常结果是0,所以没有什么意义。max的意义是,这个滤波器就是要过滤出最强烈的那个n-gram,作为整段话的中心意思。
为了得到多个卷积特征,简单地使用多个卷积核(不需要大小一致),然后把池化结果拼接起来。另外,有一个关于词向量的技巧。如果任由梯度流入词向量,则词向量会根据分类任务目标而移动,丢失语义上泛化的相似性。解决办法是用两份相同的词向量,称作两个通道(channel)。一个通道可变,一个通道固定。将两个通道的卷积结果输入到max-pooling中。
常见的几种池化方式:
Max-Pooling 最为常见,最大池化是取整个区域的最大值作为特征,在自然语言处理中常用于分类问题,希望观察到的特征是强特征,以便可以区分出是哪一个类别。Average-Pooling通常是用于主题模型,常常是一个句子不止一个主题标签,如果是使用Max-Pooling的话信息过少,所以使用Average的话可以广泛反映这个区域的特征。K-max pooling是选取一个区域的前K个最大的特征。Dynamic Pooling是根据网络结构动态调整取特征的个数。
Dropout
同样自然语言中也可以像图像处理中的那样,用到Dropout。
dropout作用就是在数据上采样子集训练,然后平均起来(ensemble)。
CNN在自然语言中的使用
在图像中卷积核通常是对图像的一小块区域进行计算,而在文本中,一句话所构成的词向量作为输入。每一行代表一个词的词向量,所以在处理文本时,卷积核通常覆盖上下几行的词,所以此时卷积核的宽度与输入的宽度相同,通过这样的方式我们就能够捕捉到多个连续词之间的特征(只要通过设置卷积核的尺寸,卷积核的宽度一般和词向量的长度一致,长度可以用1,2,3这类的值,当取3时就会将3个连续词的特征表示出来),并且能够在同一类特征计算时共享权重。
如上图所示,不同长度的卷积核,会获得不同长度的输出值,但是在之后的池化层中又会得到相同的长度(比如上面的深红色的卷积核是4×5,对于输入值为7×5的输入值,卷积之后的输出值是4×1,最大池化之后就是1×1;深绿色的卷积核是3×5,卷积之后的输出值是5×1,最大池化之后就是1×1),最后将所有池化后的值组合在一起,这样有一点好处,无论输入值的大小是否相同(输入值行一般不相等,对于输入值列是词向量的长度,一般是相等,但是行是和文本中词的数量有关),要用相同数量的卷积核进行卷积,之后再池化就会获得相同长度的向量(向量的长度和卷积核的数量相等),这样在之后就可以用全连接层了(全连接层的输入值的向量大小必须是一致的)。
CNN在自然语言中做出的改进
- 1.扩展CNN的输入:扩充词向量的维度,加入新的特征( Event Detection and Domain Adaptation with Convolutional Neural Networks);将RNN的输出作为CNN的输入(Recurrent Convolutional Neural Network for Text Classification)
- 2.卷积层的改造。如:将word2vec横向组合,以发现句子层级的特征(Event Extraction via Dynamic Multi-Pooling Convolutional Neural Networks);卷积层的非线性改造( Molding CNNs for text: non-linear, non-consecutive convolutions)
- 3.Pooling层的改造:使用K-max Pooling以保留更多的特征(An Architecture for General Matching of Text Chunks on Multiple Levels of Granularity);分段pooling(Distant Supervision for Relation Extraction via Piecewise Convolutional Neural Networks)
- 4.CNN模型的组合。对同一输入做多重cnn分类,组合结果(Question Answering over Freebase with Multi-Column Convolutional Neural Networks);一个句子一个CNN(Learning to Rank Short Text Pairs with Convolutional Deep Neural Networks)
CNN在NLP中应用的不足
目前我们所看到的CNN在NLP中的应用,大部分的网络结构都非常浅,主要是对于文本的不定长的特点,不好用多层CNN网络去训练,但是如果网络不够深,似乎又无法捕捉到更深层次的特征。因此,我们到底应不应该在NLP中应用多层CNN的结构,如果应该,该采用怎样的策略?总结/Q&A(转自知乎)
本篇综述中具体介绍了卷积神经网络的结构以及应用于自然语言处理中的场景,最后再做一个简单地归纳总结。
还有一些有关卷积神经网络细节上的问题与答案,与大家分享。
. 卷积层和池化层有什么区别?
首先可以从结构上可以看出,卷积之后输出层的维度减小,深度变深。但池化层深度不变。同时池化可以把很多数据用最大值或者平均值代替。目的是降低数据量。降低训练的参数。对于输入层,当其中像素在邻域发生微小位移时,池化层的输出是不变的,从而能提升鲁棒性。而卷积则是把数据通过一个卷积核变化成特征,便于后面的分离。
- 采用宽卷积的好处有什么?
通过将输入边角的值纳入到滑窗中心进行计算,以便损失更少的信息。
- 卷积输出的深度与哪个部件的个数相同?
输出深度(通道)与卷积核(滤波器)的个数相等。
- 激活函数通常放在卷积神经网络的那个操作之后?
通常放在卷积层之后。
- 为什么激活函数通常都是采用非线性的函数?
如果网络中都采用线性函数的组合,那么线性的组合还是线性,那么使用多次线性组合就等同于使用了一次线性函数。因此采用非线性函数可以来逼近任意函数。
- 非线性激活函数中sigmod函数存在哪些不足?
Sigmod函数存在饱和状态,尤其是值过大时,当进入饱和状态时,进行梯度下降计算时,很容易出现梯度消失的情况,求导的精确值不能保证。
- ReLU和SoftPlus激活函数有哪些优势?
与sigmod相比,不存在指数计算,求导计算量变小,同时缓解了过拟合的情况,一部分输出为0,减少了参数的相互依存。