N-gram语言模型
N-gram语言模型研究的是,给定前
n
−
1
n-1
n−1个词,判断第
n
n
n个词应该是哪一个?比如:
今天 的 天气 真 _______
即给定词
x
(
t
−
n
+
2
)
,
.
.
.
,
x
(
t
)
x^{(t-n+2)},...,x^{(t)}
x(t−n+2),...,x(t)判断
x
(
t
+
1
)
x^{(t+1)}
x(t+1),即求下面的最大值
P
(
x
(
t
+
1
)
∣
x
(
t
−
n
+
2
)
,
.
.
.
,
x
(
t
)
)
=
P
(
x
(
t
+
1
)
,
.
.
.
,
x
(
t
−
n
+
2
)
)
P
(
x
(
t
)
,
.
.
.
,
x
(
t
−
n
+
2
)
)
≈
c
o
u
n
t
(
x
(
t
+
1
)
,
.
.
.
,
x
(
t
−
n
+
2
)
)
c
o
u
n
t
(
x
(
t
)
,
.
.
.
,
x
(
t
−
n
+
2
)
)
\begin{aligned} P(x^{(t+1)}|x^{(t-n+2)},...,x^{(t)})&=\frac{P(x^{(t+1)}, ..., x^{(t-n+2)}) }{ P(x^{(t)}, ..., x^{(t-n+2)}) } \\ & \approx \frac{count(x^{(t+1)}, ..., x^{(t-n+2)})}{count(x^{(t)}, ..., x^{(t-n+2)})} \end{aligned}
P(x(t+1)∣x(t−n+2),...,x(t))=P(x(t),...,x(t−n+2))P(x(t+1),...,x(t−n+2))≈count(x(t),...,x(t−n+2))count(x(t+1),...,x(t−n+2))
c
o
u
n
t
(
)
count()
count()表示词在语料库中出现的次数。因此可以遍历语料库判断不同
x
(
t
+
1
)
x^{(t+1)}
x(t+1)应该出现的概率。
采用这种方法的问题是:
- 分子过小:比如分子的词语组合在语料库中从未出现。可以在分子和分母同时加上 δ \delta δ
- 分母过小:分母的词语组合也可能在语料库中从未出现,解决办法只能是去掉 x ( t ) x^{(t)} x(t),再看剩余的词是不是在语料库中出现过。
第二种方法是采用神经网络的方法。将 n n n个词向量拼成一个大的向量,送到神经网络进行判决。采用这种方法只能处理定长的 n n n个词。当词的数目要求可变时,仍然缺乏灵活性。
第三种方法就是RNN。
RNN
模型
RNN原理图如图所示
上图中的损失函数可以采用cross-entropy函数。
J
(
t
)
=
−
log
y
^
x
t
+
1
(
t
)
J
=
1
T
∑
t
=
1
T
J
(
t
)
J^{(t)}=-\log \hat{\mathbf{y}}^{(t)}_{x_{t+1}} \\ J=\frac{1}{T}\sum_{t=1}^T J^{(t)}
J(t)=−logy^xt+1(t)J=T1t=1∑TJ(t)
其中
∂
J
(
t
)
∂
W
h
=
∑
i
=
1
t
∂
J
(
t
)
∂
W
h
∣
i
\frac{\partial J^{(t)}}{\partial \mathbf{W}_h}=\sum_{i=1}^t \frac{\partial J^{(t)}}{\partial \mathbf{W_h} |_i}
∂Wh∂J(t)=i=1∑t∂Wh∣i∂J(t)
RNN优势在于:能处理任意长度的输入,当前的词可以利用之前的词的信息,且模型参数数量恒定。(注意每一个
W
e
,
W
h
\mathbf{W}_e,\mathbf{W}_h
We,Wh在不同的RNN cell中都是一样的)。
RNN存在的问题-梯度消失
注意到
∂
h
(
t
)
∂
h
(
t
−
1
)
=
d
i
a
g
(
σ
′
(
W
h
h
(
t
−
1
)
+
W
x
x
(
t
)
+
b
1
)
)
W
h
\frac{\partial{\mathbf h^{(t)}}}{\partial{\mathbf h^{(t-1)}}}=diag(\sigma'(\mathbf W_h\mathbf h^{(t-1)} + \mathbf W_x \mathbf x^{(t)} + \mathbf b_1)) \mathbf W_h
∂h(t−1)∂h(t)=diag(σ′(Whh(t−1)+Wxx(t)+b1))Wh
这样
∂
J
(
i
)
∂
h
(
j
)
=
∂
J
(
i
)
∂
h
(
i
)
W
h
(
i
−
j
)
∏
j
<
t
≤
i
d
i
a
g
(
σ
′
(
W
h
h
(
t
−
1
)
+
W
x
x
(
t
)
+
b
1
)
)
\begin{aligned} \frac{\partial J^{(i)}}{\partial \mathbf h^{(j)}}=\frac{\partial J^{(i)}}{\partial \mathbf h^{(i)}} \mathbf W_h^{(i-j)} \prod_{j<t \le i} diag(\sigma'(\mathbf W_h\mathbf h^{(t-1)} + \mathbf W_x \mathbf x^{(t)} + \mathbf b_1)) \end{aligned}
∂h(j)∂J(i)=∂h(i)∂J(i)Wh(i−j)j<t≤i∏diag(σ′(Whh(t−1)+Wxx(t)+b1))
这里,如果
W
h
\mathbf W_h
Wh的特征值都小于1,那么有可能得到的梯度会特别小,接近于0;反之,有可能会在某个方向出现比较大的梯度值。在前者会导致处理到句子靠后的部分,会丢失句子前面部分的信息。比如
为了取得真经,他们挑着担牵着马,经历了xxxxxxxx(等等等等九九八十一难)(此处省略1000字),最终取得了____
这样在普通的RNN中,由于中间句子很长,导致最刚开始提到的“真经”,无法出现在最后的句子里。
而对于梯度值过大,处理方法会简单一些,比如可以采用
g
←
t
h
∣
∣
g
∣
∣
g
\mathbf{g} \leftarrow \frac{th}{||\mathbf{g}||}\mathbf g
g←∣∣g∣∣thg
梯度消失解决-LSTM
LSTM的原理通过开关门,选择性的将上一级信息传到下一级。如下面两图所示。
相比起RNN,LSTM虽然没有完全解决梯度消失的问题,但是比RNN能更好的记录长时间间隔的信息。
梯度消失的解决-GRU
LSTM记录的信息是
c
(
t
)
\mathbf c^{(t)}
c(t)和
h
(
t
)
\mathbf h^{(t)}
h(t),而在GRU中,则省去了
c
(
t
)
\mathbf c^{(t)}
c(t)而只有
h
(
t
)
\mathbf h^{(t)}
h(t)。
LSTM vs. GRU
相比较起来,GRU比LSTM的参数更少些,计算速度能更快一些。但是LSTM和GRU哪个更好尚无定论,一般来说RNN可以先采用LSTM,再根据情况确定是否改成GRU。
梯度消失进一步讨论-ResNet和DenseNet
梯度消失的问题不仅仅在RNN里有,在任何层数多的神经网络都存在这个问题,导致底层的参数迭代速度很慢。因此,有人提出改进方法,ResNet,可以将输入的参数叠加到中间层中。
而DenseNet和ResNet相似,是将底层的输出叠加到高层的输出上。
双向RNN
在n-gram语言模型中,预测的词只和该词之前的词相关。因此采用普通的RNN是合适的。但是在句子的情感分析中,词的情感其实取决于前后文。比如对下文的情感做出判断:
我 高兴 个头 !
在单向RNN中,当处理到"高兴"时,"高兴“对应输出的
h
(
2
)
\mathbf h^{(2)}
h(2)为正面情绪,因为
h
(
2
)
\mathbf h^{(2)}
h(2)只和前面的“我”相关(见前面的RNN结构图)。只有模型发现“个头”时,才会意识到“高兴”实际对应的
h
(
2
)
\mathbf h^{(2)}
h(2)应输出的是负面情绪。这样也就引入了双向RNN的结构,如图所示
多层RNN
RNN也可以构建为多层结构,底层可用于识别语句的语法等低级特性。高层可以用于识别语句的语义等高级特性。
但是RNN和CNN等其它神经网络不同,即使是多层RNN一般层数也不多。比如用作自动翻译的RNN,作为encoder一般也就2-4层,作为decoder最佳也是4层。这是由于RNN本身是属于串行结构,因此计算起来速度较慢,因此能够支持的层数也较少。