文本分类系列4-textRCNN

paper reading

paper: Recurrent Convolutional Neural Networks for Text Classification

Introduction

先对之前的研究进行一番批判(0.0).

  1. 传统的文本分类方法都是基于特征工程 feature representation,主要包括:
  • 词袋模型 bag-of-words(BOW)model,用于提取unigram, bigram, n-grams的特征。
  • 常见的特征选择的方法:frequency, MI (Cover and Thomas 2012), pLSA (Cai and Hofmann 2003), LDA (Hingmire et al. 2013),用于选择具有更好的判别效果的特征。

其原理就是去噪声来提高分类效果。比如去掉停用词,使用信息增益,互信息,或者L1正则化来获取有用的特征。但传统的特征表示的方法通常忽视了上下文信息和词序信息。

  1. Richard Socher 提出的 Recursive Neural Network RecusiveNN 通过语言的tree结构来获取句子的语义信息。但是分类的准确率太依赖文本的树结构。在文本分类之前建立一个树结构需要的计算复杂度就是 \(O(n^2)\) (n是句子的长度)。所以对于很长的句子并不适用。

  2. 循环神经网络 Recurrent Neural Network 计算复杂度是 \(O(n)\),优点是能够很好的捕获长文本的语义信息,但是在rnn模型中,later words are more dominatant than earlier words. 但是如果对与某一个文本的分类,出现在之前的word影响更大的话,RNN的表现就不会很好。

为解决RNN这个问题,可以将CNN这个没有偏见的模型引入到NLP的工作中来,CNN能公平的对待句子中的每一个短语。 To tackle the bias problem, the Convolutional Neural Network (CNN), an unbiased model is introduced to NLP tasks, which can fairly determine discriminative phrases in a text with a max-pooling layer.

但是呢,通过前面的学习我们知道CNN的filter是固定尺寸的(fixed window),如果尺寸太短,会丢失很多信息,如果尺寸过长,计算复杂度又太大。所以作者提出个问题:能不能通过基于窗口的神经网络(CNN)学到更多的上下文信息,更好的表示文本的语义信息呢? Therefore, it raises a question: can we learn more contextual information than conventional window-based neural networks and represent the semantic of texts more precisely for text classification.

于是,这篇论文提出了 Recurrent Concolution Neural Network(RCNN).

Model

\[c_l{(w_i)} = f(W^{(l)}c_l(w_{i-1})+W^{(sl)}e(w_{i-1}))\] \[c_r{(w_i)} = f(W^{(r)}c_r(w_{i-1})+W^{(sr)}e(w_{i-1}))\]

这两个公式类似于双向RNN,将 \(c_l(w_i)\) 看作前一个时刻的隐藏状态 \(h_{t-1}\), \(c_l(w_{i-1})\) 就是 t-2 时刻的隐藏状态 \(h_{t-2}\)... 所以这就是个双向RNN.... 然后比较有创新的是,作者将隐藏状态 \(h_{t-1}\)\(\tilde h_{t+1}\) (\(\tilde h\) 表示反向), 以及当前word的词向量堆在一起,作为当前词以及获取了上下文信息的向量表示。

\[x_i = [c_l(w_i);e(w_i);c_r(w_i)]\]

然后是一个全连接层,这个可以看做textCNN中的卷积层,只是filter_size=1:

\[y_i^{(2)}=tanh(W^{(2)}x_i+b^{(2)})\]

接着是最大池化层:

\[y^{(3)} = max_{i=1}^ny_i^{(2)}\]

然后是全连接层+softmax:

\[y^{(4)} = W^{(4)}y^{(3)}+b^{(4)}\]

\[p_i=\dfrac{exp(y_i^{(4)})}{\sum_{k=1}^nexp(y_k^{(4)})}\]

感觉就是双向rnn呀,只不过之前的方法是用最后一个隐藏层的输出作为整个sentence的向量表示,但这篇论文是用每一个时刻的向量表示(叠加了上下时刻的隐藏状态),通过卷积层、maxpool后得到的向量来表示整个sentence.

确实是解决了RNN过于重视句子中靠后的词的问题,但是RNN训练慢的问题还是没有解决呀。但是在这里 brightmart/text_classification 中textCNN 和 RCNN的训练时间居然是一样的。why?

Results and Discussion

代码实现

需要注意的问题:

  • tf.nn.rnn_cell.DropoutWrapper

  • tf.nn.bidirectional_dynamic_rnn

  • tf.einsum

  • 损失函数的对比 tf.nn.softmax_cross_entropy_with_logits

  • 词向量是否需要正则化

  • tensorflow.contrib.layers.python.layers import optimize_loss 和 tf.train.AdamOptimizer(learning_rate).minimize(self.loss, self.global_steps) 的区别