Recurrent Neural Networks
循环神经网络的应用
1.会议识别:输入一段会议的语音信息,输出语音中的内容
2. 音乐生成:根据输入生成音乐,也可以输入空生成音乐
3. 句子分类:根据句子的内容,将句子归类。比如根据用户的评论归类到评价星级
4. DNA序列分析
5. 机器翻译
6. 视频动作识别
7. 名字识别
特点都是输入带有前后或者时间顺序的输入进行识别
符号
对输入来说,我们使用
x
<
t
>
x^{<t>}
x<t> 表示输入序列的每一部分,以输入一个句子为例,每个单词为一个
x
<
t
>
x^{<t>}
x<t>,我们构造一个单词表,假设单词表中包含10000个单词,那么每个
x
<
t
>
x^{<t>}
x<t> 为10000维的列向量,单词在单词表对应位置处为1,其他所有位置为0,如果碰到不在单词表中的单词,那么用UNK表示。
对输出来说,如果我们的任务是人名检测,那么当该单词为人名时输出为1,其他为0。我们用
y
<
t
>
y^{<t>}
y<t> 表示第
t
t
t个单词的输出。
接下来使用的符号总结:
x
(
i
)
<
t
>
:第
  
i
  
个样本中的第
  
t
  
个元素
x^{(i)<t>}\text{:第}\;i\;\text{个样本中的第}\;t\;\text{个元素}
x(i)<t>:第i个样本中的第t个元素
y
(
i
)
<
t
>
:第
  
i
  
个样本中的第
  
t
  
个元素的输出
y^{(i)<t>}\text{:第}\;i\;\text{个样本中的第}\;t\;\text{个元素的输出}
y(i)<t>:第i个样本中的第t个元素的输出
T
x
(
i
)
:第
  
i
  
个样本的长度
T_x^{(i)} \text{:第}\;i\;\text{个样本的长度}
Tx(i):第i个样本的长度
T
y
(
i
)
:第
  
i
  
个样本的输出长度
T_y^{(i)} \text{:第}\;i\;\text{个样本的输出长度}
Ty(i):第i个样本的输出长度
循环神经网络模型
为什么不直接使用一般的神经网络:
- 输入输出在不同样本中长度可以不同,一般神经网络不同样本的输入输出大小相同
- 在文档的不同位置没有可以共享的特征
循环神经网络结构:
这里假设输入输出大小相同,
a
<
0
>
a^{<0>}
a<0> 存在多种初始化方法,通常将其初始化为全0。根据结构我们可以知道,循环神经网络后边的输出是与前边的结果相关的,这就构建了前后文本的联系。
一种简单的表示法为:
详细计算公式为:设
a
<
0
>
a^{<0>}
a<0> 为全0向量
a
<
1
>
=
g
1
(
W
a
a
a
<
0
>
+
W
a
x
x
<
1
>
+
b
)
a^{<1>} = g_1(W_{aa}a^{<0>}+ W_{ax}x^{<1>} + b)
a<1>=g1(Waaa<0>+Waxx<1>+b)
y
^
<
1
>
=
g
2
(
W
y
a
a
<
1
>
+
b
)
\hat{y}^{<1>} = g_2(W_{ya}a^{<1>} + b)
y^<1>=g2(Wyaa<1>+b)
其中,
g
1
g_1
g1 通常使用tanh函数激活(也有使用ReLU激活的),
g
2
g_2
g2 根据输出来选择激活函数,如果输出为二分类问题,那么用sigmoid函数。上式更一般的表述为:
a
<
t
>
=
g
1
(
W
a
a
a
<
t
−
1
>
+
W
a
x
x
<
t
>
+
b
)
a^{<t>} = g_1(W_{aa}a^{<t-1>}+ W_{ax}x^{<t>} + b)
a<t>=g1(Waaa<t−1>+Waxx<t>+b)
y
^
<
t
>
=
g
2
(
W
y
a
a
<
t
>
+
b
)
\hat{y}^{<t>} = g_2(W_{ya}a^{<t>} + b)
y^<t>=g2(Wyaa<t>+b)
为了减少表示参数,我们将
W
a
x
W_{ax}
Wax 与
W
a
a
W_{aa}
Waa 合并,即
W
a
=
[
W
a
a
∣
W
a
x
]
W_a = \left[\begin{matrix}W_{aa}& | &W_{ax}\end{matrix}\right]
Wa=[Waa∣Wax]
那么
a
<
t
>
=
g
(
W
a
×
[
a
<
t
−
1
>
,
x
<
t
>
]
+
b
a
)
a^{<t>} = g(W_a\times [a^{<t-1>},x^{<t>}] + b_a)
a<t>=g(Wa×[a<t−1>,x<t>]+ba)
其中
[
a
<
t
−
1
>
,
x
<
t
>
]
=
[
a
<
t
−
1
>
x
<
t
>
]
[a^{<t-1>},x^{<t>}] = \left[\begin{matrix}a^{<t-1>} \\x^{<t>}\end{matrix}\right]
[a<t−1>,x<t>]=[a<t−1>x<t>]
令
W
a
y
=
W
y
W_{ay} = W_y
Way=Wy
y
^
<
t
>
=
g
(
W
y
a
<
t
>
+
b
y
)
\hat{y}^{<t>} = g(W_ya^{<t>} + b_y)
y^<t>=g(Wya<t>+by)
反向传播
L
<
t
>
(
y
^
<
t
>
,
y
<
t
>
)
=
−
y
<
t
>
log
y
^
<
t
>
−
(
1
−
y
<
t
>
)
log
(
1
−
y
^
<
t
>
)
L^{<t>}(\hat{y}^{<t>},y^{<t>}) = -y^{<t>}\log\hat{y}^{<t>}-(1-y^{<t>})\log(1-\hat{y}^{<t>})
L<t>(y^<t>,y<t>)=−y<t>logy^<t>−(1−y<t>)log(1−y^<t>)
L
(
y
^
,
y
)
=
∑
t
=
1
T
y
L
<
t
>
(
y
^
<
t
>
,
y
<
t
>
)
L(\hat{y}, y) = \sum_{t=1}^{T_y}L^{<t>}(\hat{y}^{<t>},y^{<t>})
L(y^,y)=t=1∑TyL<t>(y^<t>,y<t>)
不同类型的循环神经网络
针对循环神经网络的不同任务引入了不同的循环神经网络
- many to many:
- one to one:一般的神经网络即为one to one
- many to one:
- one to many:
- many to many2(machine translation):
输入x的网络认为是在编码(encode),输出y的网络认为在解码(decode)。
语言模型(language modeling)
训练
语言模型的输出给出了一个句子中各个单词出现的概率。
Training set:一些英语文档
训练开始前需要搭建一个单词字典用于向量化输入和输出。
对于一个句子,我们需要在句子结尾添加一个终止标志符,对于未在字典中的词用 代替。
对于RNN的第一部分,输入为一个零向量,求解输出各个单词的概率构成一个矩阵,第二部分输入句子中的第一个单词,求解在输入第一个单词下预测第二个单词的概率,这个实质上是一个与第一部分输出一样大小的向量,同理,第三部分输入为句子中的第一个和第二个单词,求解在输入前两个单词下预测第三个单词的概率。
loss function和cost function与softmax求解方式相同。
取样
在训练了一个序列模型之后,我们想知道这个模型到底学习到了什么,可以采用sample novel sequence来验证。
x
<
1
>
x^{<1>}
x<1>我们输入一个零向量,
x
<
2
>
x^{<2>}
x<2> 我们选择一个一句话的第一个单词输入;对于
y
^
<
1
>
\hat{y}^{<1>}
y^<1>,我们使用一个基于概率的随机取样(如np.random.choice),将选择出的输出作为下一层的输入以此类推。
停止的方法:1. 当输出时停止;2. 当运行到一定步数后停止
如果在测试过程中不希望出现,那么设置输出 时持续采样直到输出不为 为止。
同样该方法也可用于用字符构建句子,但是这样存在以下几个缺点:
- 无法捕捉到句子单词间的前后依赖
- 句子一般包含多个character,因此训练成本高昂
GRU,LSTM
梯度消失和梯度爆炸
- 梯度爆炸:梯度修剪,限制梯度的上限来保证梯度不会过大
- 梯度消失:对于一般的神经网络而言,当网络很深时,反向传播很难影响到最前边层的参数。对于RNN来说,如果句子后边的某一个单词需要依据前边单词判定(如The cats ,which ate…, were full。were需要根据前边的cats判断),一般的RNN网络很难做到,于是造成了梯度消失。
Gated Recurrent Unit(GRU)
一般的RNN结构是将
a
<
t
−
1
>
a^{<t-1>}
a<t−1> 与
x
<
t
>
x^{<t>}
x<t> 结合之后经激活函数之后产生
a
<
t
>
a^{<t>}
a<t>,再由
a
<
t
>
a^{<t>}
a<t> 产生
y
^
\hat{y}
y^。GRU则是对
a
<
t
>
a^{<t>}
a<t> 的产生做了一些改变
设设一级传入的数据为
c
<
t
−
1
>
c^{<t-1>}
c<t−1>,对于 $c^{}和
x
<
t
>
x^{<t>}
x<t>,我们不仅要产生一个当前的输出,还要产生一个门函数,即
c
~
<
t
>
=
t
a
n
h
(
W
c
[
c
<
t
−
1
>
,
x
<
t
>
]
+
b
c
)
\tilde{c}^{<t>} = tanh(W_c[c^{<t-1>}, x^{<t>}] + b_c)
c~<t>=tanh(Wc[c<t−1>,x<t>]+bc)
Γ
u
=
σ
(
W
u
[
c
<
t
−
1
>
,
x
<
t
>
+
b
u
)
\Gamma_u = \sigma(W_u[c^{<t-1>}, x^{<t>} + b_u)
Γu=σ(Wu[c<t−1>,x<t>+bu)
c
<
t
>
=
Γ
u
∗
c
~
<
t
>
+
(
1
−
Γ
u
)
∗
c
<
t
−
1
>
c^{<t>} = \Gamma_u * \tilde{c}^{<t>} + (1-\Gamma_u)*c^{<t-1>}
c<t>=Γu∗c~<t>+(1−Γu)∗c<t−1>
Γ
u
\Gamma_u
Γu 是一个参数均接近0或1的向量,根据式子我们可以知道,记忆单元的某一位置的值是否更新是由门函数决定的,若门函数某一位置为0,那么记忆单元该位置不更新;若为1,那么记忆单元进行更新。以 The cat, which ate …, was full为例,门函数某一位置上的值记录cat的变化,这个值直到was之前均为0,当到was时,门函数的值发生变化,对记忆单元进行更新。
为了更好的捕捉长期依赖,使RNN更有效,提出了Full GRU,即
Γ
u
=
σ
(
W
u
[
c
<
t
−
1
>
,
x
<
t
>
+
b
u
)
\Gamma_u =\sigma(W_u[c^{<t-1>}, x^{<t>} + b_u)
Γu=σ(Wu[c<t−1>,x<t>+bu)
Γ
r
=
σ
(
W
r
[
c
<
t
−
1
>
,
x
<
t
>
+
b
r
)
\Gamma_r = \sigma(W_r[c^{<t-1>}, x^{<t>} + b_r)
Γr=σ(Wr[c<t−1>,x<t>+br)
c
~
<
t
>
=
t
a
n
h
(
W
c
[
Γ
r
∗
c
<
t
−
1
>
,
x
<
t
>
]
+
b
c
)
\tilde{c}^{<t>} = tanh(W_c[\Gamma_r * c^{<t-1>}, x^{<t>}] + b_c)
c~<t>=tanh(Wc[Γr∗c<t−1>,x<t>]+bc)
c
<
t
>
=
Γ
u
∗
c
~
<
t
>
+
(
1
−
Γ
u
)
∗
c
<
t
−
1
>
c^{<t>} = \Gamma_u * \tilde{c}^{<t>} + (1-\Gamma_u)*c^{<t-1>}
c<t>=Γu∗c~<t>+(1−Γu)∗c<t−1>
LSTM
GRU其实是LATM的一个简化版本,LSTM构造更复杂的单元来保证前后之前的依赖
LSTM的状态更新函数为:
c
~
<
t
>
=
t
a
n
h
(
W
c
[
c
<
t
−
1
>
,
x
<
t
>
]
+
b
c
)
\tilde{c}^{<t>} = tanh(W_c[c^{<t-1>}, x^{<t>}] + b_c)
c~<t>=tanh(Wc[c<t−1>,x<t>]+bc)
Γ
u
=
σ
(
W
u
[
c
<
t
−
1
>
,
x
<
t
>
+
b
u
)
\Gamma_u =\sigma(W_u[c^{<t-1>}, x^{<t>} + b_u)
Γu=σ(Wu[c<t−1>,x<t>+bu)
Γ
r
=
σ
(
W
r
[
c
<
t
−
1
>
,
x
<
t
>
+
b
r
)
\Gamma_r = \sigma(W_r[c^{<t-1>}, x^{<t>} + b_r)
Γr=σ(Wr[c<t−1>,x<t>+br)
Γ
o
=
σ
(
W
o
[
c
<
t
−
1
>
,
x
<
t
>
+
b
o
)
\Gamma_o = \sigma(W_o[c^{<t-1>}, x^{<t>} + b_o)
Γo=σ(Wo[c<t−1>,x<t>+bo)
c
<
t
>
=
Γ
u
∗
c
~
<
t
>
+
Γ
f
∗
c
<
t
−
1
>
c^{<t>} = \Gamma_u * \tilde{c}^{<t>} + \Gamma_f*c^{<t-1>}
c<t>=Γu∗c~<t>+Γf∗c<t−1>
a
<
t
>
=
Γ
o
∗
c
<
t
>
a^{<t>} = \Gamma_o*c^{<t>}
a<t>=Γo∗c<t>
GRU 与 LSTM对比
GRU更简单,更易构造大型网络且计算够快,便于扩大模型规模
LSTM更强大和灵活,就一般工程而言,使用LSTM的优先级更高
双向神经网络
在序列的某点处,不仅可以获取前面的信息,也可以获取将来的信息。
网络结构
这种网络的缺点是需要一个完整的数据序列
上图黄色线表示
y
^
<
3
>
\hat{y}^{<3>}
y^<3> 的输出
Deep RNN
对于深度循环神经网络,三层已经算很深的网络。
也可以对输出添加多层一般神经网络的隐藏层达到加深网络的目的。