现在考虑这样一个问题,给一句话,如何判断这句话的情感是积极的(Positive)还是消极的(Negative)
例如下图中的一句话"I hate this boring movie",我们看一眼就知道这句话肯定是消极的,但是如何构建一个网络模型去识别呢?
有一种naive的方法,假设我们把这句话变成一个[5, 100]的tensor,5表示这句话里有5个词,100表示每句话的维度是100。然后对于将每个词$x_i=[100]$作为输入,分别带入5个Linear Layer,假设得到的输出$y_i=[2]$,把这五个输出合在一起就是$y=[5, 2]$,最后再接一个Linear Layer,输出$p=[1]$,这个值表示给出句子是$x$的情况下,这个句子的情感是Positive的概率,即$P(pos|x)$,就变成了一个二分类的问题
这只是一个naive的做法,这样做会存在很多问题。首先如果输入是一个很长的句子,那么这个句子里的单词就会很多,再加上每个单词对应还需要一段长度的词向量,整个参数量就会非常大;其次,这种做法没有考虑到上下文的信息,例如"我不喜欢你"这句话,如果你只分析"喜欢",你会以为这是一个积极的句子,但其实没有考虑到上文中的"不"字。再比如,一个人说:我喜欢旅游,其中最喜欢的地方是云南,以后有机会一定要去__
。这里填空,是个正常人都知道填"云南"。我们是根据上下文内容推断出来的,这就意味着,一句话不能单独一个单词一个单词来分析,所以我们希望能有一个consistent tensor来存储语境信息,并且在训练的时候能够将这个语境信息利用起来
对于第一个问题,如何解决参数量过大,我们可以参考CNN,卷积神经网络中的每个kernel都利用的权重共享的思想,应用到我们这里就是,每个单词经过的Linear Layer,其$w$和$b$,都是相同的,而不再是上面那张图的$w_1$,$w_2$,...$b_1$,$b_2$,...,具体见下图
对于第二个问题,如何将语境信息也贯穿在整个网络训练的过程中?
看下图的网络结构,每一层的输出,都会作为下一层的一部分输入。例如将"I"的词向量$x_1$和$h_0$作为输入,输出得到$h_1$,就,然后将"hate"这个词的词向量$x_2$和$h_1$作为输入,输出得到$h_2$,如此循环下去。因此这种网络被称为循环神经网络(RNN)
下图是一个典型的RNN网络结构。右边可以理解为左边按照时间进行展开
假设$x_{t-1},x_{t}$表示输入"我"和"是",$x_{t 1}$表示输入"中国",连起来输入就是"我是中国",那么$O_{t-1},O_{t}$就应该对应"是"和"中国",预测下一个词最有可能是什么?就是预测$O_{t 1}$最有可能是什么,应该是"人"的概率比较大
因此,我们可以做这样的定义:
$$ X_t:表示t时刻的输入,O_t:表示t时刻的输出,S_t:表示t时刻的记忆 $$
因为我们当前时刻的输出是由记忆和当前时刻的输入共同决定的。就像你现在大四,你的知识是由大四学到的知识(当前输入)和大三以及大三以前学到的知识(记忆)的结合。RNN在这点上也类似,神经网络最擅长做的就是通过一系列参数把很多内容整合到一起,然后学习这个参数,因此就定义了RNN的基础:
$$ S_t=f(U*x_t W*S_{t-1}) $$
这里的$f()$函数表示激活函数,对于CNN来说,激活函数一般选取的都是$ReLU$,但是RNN一般选用$tanh$
假设你大四快毕业了,要参加考研,请问你参加考研是先记住学过的内容然后去考研,还是直接带几本书参加考研呢?答案很显然。RNN的做法也就是预测的时候带着当前时刻的记忆$S_t$去预测。假如你要预测"我是中国"的下一个词,运用SoftMax在合适不过了,但预测不能直接用一个矩阵去预测,要转为一个向量,所以最终的公式表示为:
$$ O_t = softmax(V*S_t) $$
RNN的结构细节:
- 可以把$S_t$当作隐状态,捕捉了之前时间点上的信息。就像你去考研一样,考的时候记住了你能记住的所有信息
- 可惜的是$S_t$并不能捕捉之前所有时间点的信息,或者说在网络传播的过程中会"忘掉"一部分。就像你考研也记不住所有的英语单词一样
- 和卷积神经网络一样,RNN中的每个节点都共享了一组参数$(U, V, W)$,这样就能极大降低计算量