第一周:循环序列模型
本文是序列模型的笔记。
1.0 重点:
- 在通常的版本中,我们在
Output Gate
会包含3项: a < t − 1 > a^{<t-1>} a<t−1>, x < t > x^{<t>} x<t>, c < t − 1 > c^{<t-1>} c<t−1>其中最后一项被称为偷窥孔连接(peephole connection),即 Γ o = σ ( W o [ a < t − 1 > , x < t > , c < t − 1 > ] + b o ) \Gamma_o=\sigma(W_o[a^{<t-1>},x^{<t>},c^{<t-1>}]+b_o) Γo=σ(Wo[a<t−1>,x<t>,c<t−1>]+bo) - 所有的Gate都是用Sigma计算,可以类比门0/1来记忆。
- 所有的参量 a , c a,c a,c都是用tanh来计算。
1.1 为什么选择序列模型(Sequence Models)
序列的例子:
- 语音识别
- 音乐生成
- 评分预测
- DNA序列分析
- 机器翻译
- 视频中动作的识别
- 命名实体识别
1.2 数学符号定义
记号
一种简单的做法,对于每一个词有一个输出。
-
输入:
x < t > x^{<t>} x<t>输入中的第t个输入, T x T_x Tx输入的长度
x ( i ) < t > x^{(i)<t>} x(i)<t>表示第i个样本的第t个输入, T x ( i ) T^{(i)}_x Tx(i)表示第i个输入样本的长度 -
输出:
t < t > t^{<t>} t<t>输出中的第t个输出, T y T_y Ty输出的长度,我们下面的例子中 T x = = T y T_x==T_y Tx==Ty
同理也有 t ( i ) < t > t^{(i)<t>} t(i)<t>和 T y ( i ) T^{(i)}_y Ty(i)
怎样表示句中的words
- One-hot向量
例如选取一个10,000大小的字典,每一个词都在这个字典里面。
则每一个输入 x < t > x^{<t>} x<t>都是一个(10,000,1)的One-hot向量,即只在对应词的序号处为1。
例子
1.3 循环神经网络
为什么不用一个常规的全链接神经网络?
- 输入尺寸的问题,用Padding也感觉不太对。
- 没有共享特征,参数数量比卷积神经网络大(我们也需要对1维序列找一个类似的网络架构)
🌟 网络结构
关键的公式为:
a
<
t
>
=
g
(
W
a
a
a
<
t
−
1
>
+
W
a
x
x
<
t
>
+
b
a
)
a^{<t>}=g(W_{aa}a^{<t-1>}+W_{ax}x^{<t>}+b_a)
a<t>=g(Waaa<t−1>+Waxx<t>+ba)
y
^
<
t
>
=
g
(
W
y
a
a
<
t
>
+
b
y
)
\hat{y}^{<t>}=g(W_{ya}a^{<t>}+b_y)
y^<t>=g(Wyaa<t>+by)
Rq:
- 在RNN中tanh作为激活函数比较常见,用Sigmoid作为输出 y ^ < i > \hat{y}^{<i>} y^<i>比较常见。
- 一个缺点是它只考虑了之前的信息,这在一些场合中是不太行的。
“Teddy Roosevelt was as great President.”
“Teddy bears are on sale!”
Sol: Bidirected - RNN (BRNN)
1.4 通过时间的反向传播(Backpropagation through time)
1.5 不同类型的循环神经网络
T x T_x Tx不一定等于 T y T_y Ty
比如:
- 音乐生成
- 评分预测
- 机器翻译
总结:
模型 | One to One | One to Many | Many to One | Many to Many |
---|---|---|---|---|
应用场景 | - | 音乐生成 | 电影评论预测评分 | 注意这里的 T x T_x Tx不一定和 T y T_y Ty相同,比如机器翻译里面 |
1.6 语言模型和序列生成
什么是Language modeling?
即测量某一句话出现的概率:
P
(
y
^
(
1
)
,
…
,
y
^
(
n
)
)
\mathbb{P}(\hat{y}^{(1)},\dots,\hat{y}^{(n)})
P(y^(1),…,y^(n))
例如下面第二句话出现的概率就比第一句话要高:
- The apple and pair salad.
- The apple and pear salad.
Language modeling with an RNN
训练集:英语语料库
工具:词典
我们要做的第一件事情就是标记(tokenize
)一个句子:
将每一个词都转化为one-hot向量并在句子结尾加上标记<EOS>
表示End of Sentence,对于一些字典中没有的词,我们可以用<UNK>
(Unkown words)来表示。换言之,加入我们之前找的一个字典有10,000个词,则此时每一个词的标签就可以用
y
<
i
>
∈
R
10
,
002
×
1
y^{<i>}\in \mathbb{R}^{10,002\times 1}
y<i>∈R10,002×1来表示,表示每一个词出现的概率。
⚠️ 这里和之前判断人名不太一样,之前我们是判断一个位置上出现的是否人名,所以输出的是0/1。而这里我们输出的是当前位置10,002个词出现的概率,所以应该用SoftMax输出,并采用SoftMax损失函数:
🌟
对于单个词向量:
L
(
y
^
<
t
>
,
y
<
t
>
)
=
−
∑
i
=
1
10
,
002
y
i
<
t
>
l
o
g
(
y
^
i
<
t
>
)
L(\hat{y}^{<t>},y^{<t>})=-\sum_{i=1}^{10,002} y_i^{<t>}log(\hat{y}_i^{<t>})
L(y^<t>,y<t>)=−i=1∑10,002yi<t>log(y^i<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>)
训练一个语言模型:
1.7 对新序列进行采样
这里目的是调用1.6中已经训练好的语言模型来产生一个句子。每词我们调用模型的时候实际上类似于计算一个条件概率 y ^ < t > = P ( x n ∣ x 1 , . . . , x n − 1 ) \hat{y}^{<t>} = \mathbb{P}(x_n | x_1,...,x_{n-1}) y^<t>=P(xn∣x1,...,xn−1)
当然我们也可以训练一个基于字符的语言模型,这样我们就可以产生一些不认识的词语,但是计算成本更高。(现在主流还是基于词语的语言模型,但是随着计算机性能的提升,我们也可以尝试基于字符的语言模型)
Rq:
- 终止条件
我们可以手动设置输出若干个词,也可以等到这句话自动到<EOS>
自动停止。 - 对于
<UNK>
的处理
我们可以手动去除输出<UNK>
。
基于字符的语言模型
此时我们的词典不再是一个个词,而是:
[
a
,
b
,
c
.
.
,
z
,
空格, 句号,逗号,
0
,
1
,
.
.
.
,
9
,
A
,
.
.
.
,
Z
]
[a,b,c..,z,\text{ 空格, 句号,逗号, }0,1,...,9,A,...,Z]
[a,b,c..,z, 空格, 句号,逗号, 0,1,...,9,A,...,Z]
按照同样的逻辑我们可以生成一个句子,只不过这里是一个字母一个字母打的,所以计算量会大一些。
1.8 RNN梯度消失的问题
-
梯度消失产生的原因:
因为一旦句子过长,则相当于网络的层数太深了,就不容易将梯度传递到前面的层。 -
例如:
The cat, which …, was full.
The cats, which …, were full.
如果中间插入语过多,则网络可能无法认识到"cat was"和“cats were”这个语法规则。 -
Sol: GRU(Gated Recurrent Unit)
-
如果发现梯度爆炸,我们可以尝试Gradient Clipping,即当一个梯度大于一定的阈值的时候我们做一下Scaling。
1.9 GRU(Gated Recurrent Unit) 与 GRNN
可以解决梯度消失的问题
GRU和LSTM都是一些比较常用的单元。
- Recap:
a < t > = g ( W a [ a < t − 1 > , x < t > ] + b a ) a^{<t>}=g(W_a[a^{<t-1>},x^{<t>}]+b_a) a<t>=g(Wa[a<t−1>,x<t>]+ba)
GRU(Simplified)
引入
- Memory cell :
c
c
c
- 对于GRU,我们有 c < t > = a < t > c^{<t>}=a^{<t>} c<t>=a<t>,即我们利用 c < t > c^{<t>} c<t>来代替之前 a < t > a^{<t>} a<t>在RNN中的地位。
- 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),其实就是之前 a < t > a^{<t>} a<t>的计算公式。
- Update Gate:
Γ
u
∈
[
0
,
1
]
\Gamma_u \in [0,1]
Γu∈[0,1]
- Γ 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)
- 一个直观的理解, Γ u \Gamma_u Γu可以看成一个标记,比如当我们碰见“cat”这个词我们标记为1,即记住这个值。当我们碰见一个动词的时候,我们就需要调用主语。
GRU(Full)
- “Relevance Gate”: Γ r ∈ [ 0 , 1 ] \Gamma_r \in [0,1] Γr∈[0,1]
总结:
1.10 LSTM(Long-short Term Memory) unit 与LSTM
比GRU更powerful,一般LSTM会作为优先选项。
GRU因为只有两个门,所以可以构建更大规模的网络,计算速度也会快一点。
- 引入了三个门Update, Forget, Output (UFO)。
Rq:
在通常的版本中,我们在Output Gate
会包含3项:
a
<
t
−
1
>
a^{<t-1>}
a<t−1>,
x
<
t
>
x^{<t>}
x<t>,
c
<
t
−
1
>
c^{<t-1>}
c<t−1>其中最后一项被称为偷窥孔连接(peephole connection)。
1.11 双向神经网络(BRNN)
为了解决之前模型无法考虑后续输入的问题。
这里并不是改进对 a < t > a^{<t>} a<t>的计算,而是提出了一种新的网络结构。这个新的网络结构也可以运用GRU或者LSTM
- Recap:
图片里面的a块,要么是传统RNN,要么是GRU,要么是LSTM。尽管我们在GRU里面引入了Memory Cell c c c,但是它只能解决如同"The cat, which …, was …"的从左到右的问题。但无法解决前面对于"Teddy"含义的问题。
BRNN
Rq:
- 引入了 a → < t > , a ← < t > \overrightarrow{a}^{<t>},\overleftarrow{a}^{<t>} a<t>,a<t>,这两个都是正向传播。
- 构成了一个无环图(Acyclic Graph)
- 这里的a块,也要么是传统RNN,要么是GRU,要么是LSTM。
- 一般在自然语言处理(NLP )中,用LSTM+BRNN比较常见。
- 但在语音识别中,如果使用BRNN则需要等到这句话结束。
1.12 深层循环神经网络(Deep RNN)
- 引入
a
[
l
]
<
t
>
a^{[l]<t>}
a[l]<t>表示第l层的序列中的第t个元素。
- 这里展示了一个三层的RNN网络。
- a [ 2 ] < 3 > = g ( W a [ 2 ] [ a [ 2 ] < 2 > , a [ 1 ] < 2 > ] + b a [ 2 ] ) a^{[2]<3>}=g(Wa^{[2]}[a^{[2]<2>},a^{[1]<2>}]+b^{[2]}_a) a[2]<3>=g(Wa[2][a[2]<2>,a[1]<2>]+ba[2])
Rq:
-
一般3层就够了,或者后面取消了水平连接
-
我们也可以用Deep BRNN,每一个bloc也可以用GRU、LTSM或普通的RNN。
第一周测试重点:
这个RNN正在试着根据前面所有的知识来预测下一步,即
P
(
y
<
t
>
∣
y
<
1
>
,
y
<
2
>
,
…
,
y
<
t
−
1
>
)
P(y^{<t>}∣y^{<1>},y^{<2>},…,y^{<t−1>})
P(y<t>∣y<1>,y<2>,…,y<t−1>)
2. 权重与激活值都是“NaN”,意味着梯度爆炸了。
3.
Γ
u
\Gamma_u
Γu 的向量维度等于LSTM中隐藏单元的数量。
4. GRU和LTSM的方程
🌟🌟 在LSTM中的更新门和遗忘门在GRU中扮演类似
Γ
u
\Gamma_u
Γu与
1
−
Γ
u
1-\Gamma_u
1−Γu的角色
5. 我们可以移除GRU中的
Γ
r
\Gamma_r
Γr,即令其为1。这种情况下,如果我们有
Γ
u
≈
0
\Gamma_u \approx 0
Γu≈0,则
c
<
t
>
=
c
<
t
−
1
>
c^{<t>}=c^{<t-1>}
c<t>=c<t−1>,对于一个时间步而言,梯度可以通过时间步反向传播而不会衰减。