文章目录
一、简介
TextCNN擅长捕获更短的序列信息,但是TextRNN擅长捕获更长的序列信息。具体到文本分类任务中,BiLSTM从某种意义上可以理解为可以捕获变长且双向的N-Gram信息。
二、先验知识:LSTM详解
2.1 RNN
随着人慢慢成长,其认知能力也在不断的成熟。当看到一个事物的时候,人们并不是用一片空白的大脑在思考,而是基于自己已经拥有的认知去推断新鲜事物。可见人们的思想具有持久性。但是传统神经网络并不具有这个能力,这是一大弊端。但是RNN就可以完美的解决这个问题。RNN作为循环网络,允许消息的持久性。
将RNN模型展开后,如下图所示,神经网络的模块
A
A
A,正在读取某个输入
x
i
x_i
xi,并输出一个值
h
i
h_i
hi。循环可以使得信息可以从当前步传递到下一步。
所有递归神经网络都具有神经网络重复模块链的形式。 在标准RNN中,该重复模块将具有非常简单的结构,例如单个tanh层。
描述如何在每个时间步骤上计算输出的方程式,如下所示:
但是,循环神经网络的缺点是,随着时间步骤长度的增大,它无法从差得很远的时间步骤中获得上下文环境。
为了理解时间步骤t+1的上下文环境,我们有可能需要了解时间步骤0和1中的表示。但是,由于它们相差很远,因此它们所学的表示无法在时间步骤t+1上向前移动,进而对其起作用。“我在法国长大……我能说一口流利的法语”,要理解你说的法语,网络就必须远远地往后查找。但是,它不能这么做,这个问题可以归咎于梯度消失的原因。因此,循环神经网络只能记住短期存储序列。
为了解决这个问题,Hochreiter & Schmidhuber提出了一种称为长短期记忆网络。
2.2 长短期记忆网络(LSTM)
LSTM网络的结构与循环神经网络保持一致,而重复模块会进行更多的操作,有四个不同结构,而不是一个神经网络层,如下图所示。增强重复模块使LSTM网络能够记住长期依赖关系。让我们试着分解每个操作,来帮助网络更好地记忆。
在图中,我们所使用的符号的含义如下所示:
下面,详细来剖析一下LSTM的内部结构,分为细胞状态、遗忘门、输入门、输出门四个方面进行介绍。
(1)细胞状态(Cell State)
在序列中的每一个时刻
t
t
t向前传播的信息,除了和朴素RNN一样的隐藏状态
h
t
h_t
ht之外,还有另外一个隐藏状态,如下图中的横线。这个隐藏状态即细胞状态,记为
C
t
C_t
Ct。这个细胞状态可以保持信息在上面流动时不会发生改变。
另外,在LSTM中能够移除或添加信息到结点来改变信息流状态,由称为门(gate)的结构精心调节。
门是一种可选择通过信息的节点。 它们由
σ
\sigma
σ(Sigmoid)神经网络层和逐点乘法运算组成。
sigmoid层输出
0
0
0到
1
1
1之间的数字,描述每个信息向量应该通过多少。 值为零意味着“不让任何东西通过”,而值为1则意味着“让一切都通过!”
LSTM具有三个这样的门,用于保护和控制信息流向量状态。
(2)遗忘门
在LSTM中第一步是:从细胞状态之中,决定是否丢弃信息、丢弃什么样的信息。做决定的结构即:遗忘门。该门控开关会读取上一个时刻的隐藏状态
h
t
−
1
h_{t-1}
ht−1和当前的输入
x
t
x_t
xt作为遗忘门的输入,然后通过一个诸如sigmoid的激活函数,输出
f
t
f_t
ft。其中
f
t
∈
[
0
,
1
]
f_t \in [0,1]
ft∈[0,1],即代表了遗忘上一个时刻的细胞状态的概率,1代表“完全保留”,0代表“完全舍弃”。数学表达为
f
t
=
σ
(
W
f
h
t
−
1
+
U
f
x
t
+
b
f
)
{f_t} = \sigma ({W_f}{h_{^{t - 1}}} + {U_f}{x_t} + {b_f})
ft=σ(Wfht−1+Ufxt+bf)
其中,
W
f
,
U
f
,
b
f
{W_f},{U_f},{b_f}
Wf,Uf,bf是线性关系系数与偏置,和RNN中类似。
σ
\sigma
σ是sigmoid激活函数。如图所示,为遗忘门的结构:
我们从当前时间步骤获取输入,并从前一时间步骤获取学习的表示,之后将它们连接起来。我们将连接后的值传递给一个sigmoid函数,该函数输出一个介于0和1之间的值(
f
t
f_t
ft)。我们在
f
t
f_t
ft和
c
t
−
1
c_{t-1}
ct−1之间做元素的乘积。如果这个值为0,那么从
c
t
−
1
c_{t-1}
ct−1中去掉,如果这个值为1,则完全通过。因此,这种操作也被称为“忘记门操作”。
(3)输入门
在LSTM中第二步是:决定在细胞状态中,应存储什么样的新信息。负责的是当前时刻序列的输入,结构如图:
输入门结构有两部分构成。第一个是使用sigmoid函数,输出
i
t
i_t
it;第二个是使用
t
a
n
h
tanh
tanh函数,输出为
a
t
a_t
at。然后用
i
t
i_t
it和
a
t
a_t
at相乘去更新细胞状态。数学表达为:
i t = σ ( W i h t − 1 + U i x t + b i ) {i_t} = \sigma ({W_i}{h_{t - 1}} + {U_i}{x_t} + {b_i}) it=σ(Wiht−1+Uixt+bi)
a t = tanh ( W a h t − 1 + U a x t + b a ) {a_t} = \tanh ({W_a}{h_{t - 1}} + {U_a}{x_t} + {b_a}) at=tanh(Waht−1+Uaxt+ba)
其中, W i , U i , b i , W a , U a , b a {W_i},{U_i},{b_i},{W_a},{U_a},{b_a} Wi,Ui,bi,Wa,Ua,ba是线性关系系数与偏置,与RNN中的类似。 σ \sigma σ是sigmoid激活函数。
(4)更新门
先前介绍的遗忘门、输入门得到的结果都会直接或者间接地作用于细胞状态 C t C_t Ct。如何将 C t − 1 C_{t-1} Ct−1更新为 C t C_t Ct呢?
如图所示,为细胞状态的更新示意图:
新的细胞状态有两部分构成。第一个是
C
t
−
1
C_{t-1}
Ct−1和遗忘门的输出
f
t
f_t
ft的乘积,即可丢弃决定要丢弃的内容。第二个是输入门的
i
t
i_t
it和
a
t
a_t
at的乘积,这是新候选值,根据模型决定更新状态的程度来变化。乘指的是是Hadamard积。
我们将来自当前时间步骤中的值和前一时间步骤中已学习的表示连接起来。将连接的值通过一个tanh函数进行传递,我们生成一些候选值,并通过一个sigmoid函数传递,从候选值中选择一些值,所选的候选值将会被更新到 c t − 1 c_{t-1} ct−1
(5)输出门
我们将当前时间步骤的值和前一时间步骤已学习的表示连接起来,并经由一个sigmoid函数传递来选择将要用作输出的值。我们获取单元状态并请求一个tanh函数,然后执行元素方式操作,其只允许选定的输出通过。
2.3 双向RNN
所有上述双向RNN网络的一个主要问题是,它们从之前的时间步骤中学习表示。有时,你有可能需要从未来的时间步骤中学习表示,以便更好地理解上下文环境并消除歧义。通过接下来的列子,“He said, Teddy bears are on sale” and “He said, Teddy Roosevelt was a great President。在上面的两句话中,当我们看到“Teddy”和前两个词“He said”的时候,我们有可能无法理解这个句子是指President还是Teddy bears。因此,为了解决这种歧义性,我们需要往前查找。这就是双向RNN所能实现的。
双向RNN中的重复模块可以是常规RNN、LSTM或是GRU。双向RNN的结构和连接如图10所示。有两种类型的连接,一种是向前的,这有助于我们从之前的表示中进行学习,另一种是向后的,这有助于我们从未来的表示中进行学习。
正向传播分两步完成:
-
我们从左向右移动,从初始时间步骤开始计算值,一直持续到到达最终时间步骤为止;
-
我们从右向左移动,从最后一个时间步骤开始计算值,一直持续到到达最终时间步骤为止;
2.4 双向LSTM【Bi-LSTM】
前向的LSTM与后向的LSTM结合成BiLSTM。比如,我们对“我爱中国”这句话进行编码,模型如图所示。
前向的
L
S
T
M
L
LSTM_L
LSTML依次输入“我”,“爱”,“中国”得到三个向量
{
h
L
0
,
h
L
1
,
h
L
2
}
\{h_{L0}, h_{L1}, h_{L2}\}
{hL0,hL1,hL2}。后向的
L
S
T
M
R
LSTM_R
LSTMR依次输入“中国”,“爱”,“我”得到三个向量
{
h
R
0
,
h
R
1
,
h
R
2
}
\{h_{R0}, h_{R1}, h_{R2}\}
{hR0,hR1,hR2}。最后将前向和后向的隐向量进行拼接得到
{
[
h
L
0
,
h
R
2
]
,
[
h
L
1
,
h
R
1
]
,
[
h
L
2
,
h
R
0
]
}
\{[h_{L0}, h_{R2}], [h_{L1}, h_{R1}], [h_{L2}, h_{R0}]\}
{[hL0,hR2],[hL1,hR1],[hL2,hR0]},即
{
h
0
,
h
1
,
h
2
}
{\{h_0,h_1 ,h_2 \}}
{h0,h1,h2}。
三、textRNN模型结构
3.1 结构1
TextRNN的结构分为:1. embeddding layer, 2.Bi-LSTM layer, 3.concat output, 4.FC layer, 5.softmax
一般取前向/反向LSTM在最后一个时间步长上隐藏状态,然后进行拼接,在经过一个softmax层(输出层使用softmax激活函数)进行一个多分类;或者取前向/反向LSTM在每一个时间步长上的隐藏状态,对每一个时间步长上的两个隐藏状态进行拼接,然后对所有时间步长上拼接后的隐藏状态取均值,再经过一个softmax层(输出层使用softmax激活函数)进行一个多分类(2分类的话使用sigmoid激活函数)。
上述结构也可以添加dropout/L2正则化或BatchNormalization 来防止过拟合以及加速模型训练。
3.2 结构2
与之前结构不同的是,在双向LSTM(上图不太准确,底层应该是一个双向LSTM)的基础上又堆叠了一个单向的LSTM。把双向LSTM在每一个时间步长上的两个隐藏状态进行拼接,作为上层单向LSTM每一个时间步长上的一个输入,最后取上层单向LSTM最后一个时间步长上的隐藏状态,再经过一个softmax层(输出层使用softamx激活函数,2分类的话则使用sigmoid)进行一个多分类。
四、总结
- 代码实现过程,参考:https://blog.csdn.net/yyy430/article/details/88591918#%E6%A8%A1%E5%9E%8B%E7%BB%93%E6%9E%84
- TextRNN的结构非常灵活,可以任意改变。比如把LSTM单元替换为GRU单元,把双向改为单向,添加dropout或BatchNormalization以及再多堆叠一层等等。TextRNN在文本分类任务上的效果非常好,与TextCNN不相上下,但RNN的训练速度相对偏慢,一般2层就已经足够多了。