前一段时间阅读了Yoon Kim发表的论文Convolutional Naural Networks for Sentence Classification,现在抽时间吧相关的内容记录下来。包括模型的介绍和代码实现。这篇文章介绍第一部分。
论文使用CNN处理NLP问题,使用预先处理的词向量处理句子层面的分类问题,在情感分析(sentiment analysis)和问题分类(question classification)等方面达到了很好的效果。
我们先来看整体的模型:
首先将单词embed到一个低维的向量,然后输入卷积层,在卷积层采用了不同大小的卷积核提取不同的特征,然后到池化层选取最大特征,最后经过全连接层softmax分类器得到分类结果。
1.词向量
对于模型的输入,论文中有两中channel,也是两种选择,一种是static的词向量,就是直接使用Google的word2vec作为每一个词的词向量,在训练过程中词向量是不会发生变化的,另一种是non-static的词向量,这种词向量作为模型训练的一部分,每一个单词对应的词向量在训练过程中不断改变。在最后的结果里,non-static对应的结果会相对更好,这是因为词向量更好的适应了实验的数据集。但我们也应该知道,这样的方法对于较小的数据集是不应该推荐的,容易产生过拟合的问题。
因为使用CNN处理,所以需要对输入处理成图片的形式。从图片里可以看出,每一个词向量组成图片矩阵的行,每一个句子最终组成一张图片矩阵。
2.卷积层
选取不同大小的卷积核提取不同的特征,大小是filter_size*embedding_size,其中filter_size可取3,4,5,代表卷积核纵向的长度,也就是一次卷积能覆盖几个单词,embedding_size是横向的长度,这里就是每个词向量的长度,这里embedding_size大小的选取是很巧妙的,因为这样提取的特征不会关注每个单词内部比特的关系,而是关注单词之间的关系,这正是我们希望得到的。通过卷积核的计算后,对于每一个图片矩阵我们就得到了一个一维的向量,代表着这个句子的特征。有多少和卷积核就能提取出多少种特征,即图中在纵深方向上channel的数量。
3.池化层
采用的是最大池化,将卷积得到的向量池化,也就是提取一个最大值出来,对于每一个向量我们都采取池化操作,这样在纵深方向上我们就得到一个维数是num_filters的行向量。这样做的附带的一个好处是,如果最开始没有对句子进行padding处理,句子长度不一致,卷积后的列向量维度也不一样,但是经过池化可以消除长度不一致的差异。
4.全连接层
论文做的实验是判断一个对电影评价的句子是正面还是负面,所以最终的输出需要经过一个softmax进行二分类。另外由于实验所用的数据集比较小,容易出现过拟合现象,在实验过程中也发现当迭代次数到3000轮的时候准确率就接近于1.。所以全连接层使用dropout方法减少过拟合。另外还可以考虑使用L2正则化的方法防止过拟合。
这篇论文主要贡献就是将CNN成功用在了NLP方向上,大大扩展了CNN的使用范围。实验的结果也达到了很好的效果。模型并不复杂,在下一篇博客中我们会介绍使用TensorFlow的实现。