文章目录
- 第五课:序列模型(Sequence Models)
- 第一周:循环神经网络(Recurrent Neural Networks)【序列模型、语言模型+序列生成、对新序列采样。RNN、GRU、LSTM、双向RNN、深度RNN】
- 第二周:自然语言处理与词嵌入(Natural Language Processing and Word Embeddings)【词嵌入、嵌入矩阵、学习词嵌入、Word2Vec + Skip-Gram、负采样、GloVe 词向量、情感分类、词嵌入消除偏见】
- 第三周:序列模型和注意力机制(Sequence models & Attention mechanism)【seq2seq模型(编码器解码器架构=编码解码)、集束搜索、Bleu 得分、注意力模型+编码解码架构、语音识别、触发字检测】
第五课:序列模型(Sequence Models)
第一周:循环神经网络(Recurrent Neural Networks)【序列模型、语言模型+序列生成、对新序列采样。RNN、GRU、LSTM、双向RNN、深度RNN】
- 对新序列采样(Sampling novel sequences)
在你训练一个序列模型之后,要想了解到这个模型学到了什么,一种非正式的方法就是进行一次新序列采样。
记住一个序列模型模拟了任意特定单词序列的概率,我们要做的就是对这些概率分布进行采样来生成一个新的单词序列。
已有一个训练好的模型如上图。在已经训练好的序列模型上采样新序列,具体步骤如下:
时间步1:输入 a < 0 > = 0 ⃗ , x < 1 > = 0 ⃗ a^{<0>}=\vec{0}, x^{<1>}=\vec{0} a<0>=0,x<1>=0,得到采样前的 y ^ < 1 > \hat{y}^{<1>} y^<1>,输出采样后的 y ^ < 1 > \hat{y}^{<1>} y^<1>。采样前, y ^ < 1 > \hat{y}^{<1>} y^<1>是个概率向量(所有分量都是0.xx这样的小数);采样后, y ^ < 1 > \hat{y}^{<1>} y^<1>是个单位向量(只有1个分量是1,其他分量都是0)。
采样前的 y ^ < 1 > \hat{y}^{<1>} y^<1>是词典中每个单词在这一步出现的概率,然后根据每个单词出现的概率进行随机采样,得到一个单词,即得到采样后的 y ^ < 1 > \hat{y}^{<1>} y^<1>。
numpy的函数np.random.choice:根据向量中这些概率的分布进行采样。概率高的单词,采样出来的概率大,概率低的单词采样出来的概率小,但都有可能被采样出来,最终采样出一个单词。
时间步2:输入 a < 1 > = ? , x < 2 > = 采样后 y ^ < 1 > a^{<1>}=?, x^{<2>}=采样后\hat{y}^{<1>} a<1>=?,x<2>=采样后y^<1>,得到采样前的 y ^ < 2 > \hat{y}^{<2>} y^<2>,输出采样后的 y ^ < 2 > \hat{y}^{<2>} y^<2>。
时间步3:输入 a < 2 > = ? , x < 3 > = 采样后 y ^ < 2 > a^{<2>}=?, x^{<3>}=采样后\hat{y}^{<2>} a<2>=?,x<3>=采样后y^<2>,得到采样前的 y ^ < 3 > \hat{y}^{<3>} y^<3>,输出采样后的 y ^ < 3 > \hat{y}^{<3>} y^<3>。
以此类推。
序列结束:采样到<EOS>
标志,就代表结束。如果字典中没有<EOS>
标志,就自己指定一个时间步,认为到达这个时间步就是结束。
就是时间步1(根据每个词出现的概率)随机生成一个单词,时间步2输入时间步1已经生成的单词,然后(根据已有序列+在已有序列后每个词出现的概率)随机生成新的单词,时间步3输入时间步2已经生成的单词,然后(根据已有序列+在已有序列后每个词出现的概率)随机生成新的单词。以此类推。
RNN模型分为:基于词汇的,基于字符的。之前我们讲的都是基于词汇的RNN模型,基于字符的RNN模型训练起来计算成本比较高昂,很少用。
- 循环神经网络的梯度消失(Vanishing gradients with RNNs)
训练很深的神经网络时,随着层数的增加,导数/梯度 有可能指数型的下降(梯度消失)或者指数型的增加(梯度爆炸)。RNN随着层数的增加,也会有梯度消失和梯度爆炸问题。
RNN中的梯度消失问题,会导致RNN会不擅长处理长期依赖(长期依赖:最前面的单词对句子很后面的单词有影响),举例:
“The cat, which already ate ……, was full.”,因为cat是单数,所以应该用was。
“The cats, which already ate ……, were full.”,因为cats是复数,所以应该用were。
很难让一个神经网络记住主语是单数名词还是复数名词,然后在序列后面生成依赖单复数形式的was或者were。
梯度爆炸很容易发现,因为参数会大到崩溃,你会看到很多NaN。
GRU (Gated Recurrent Unit, 门控循环单元) :梯度消失的解决方法。
梯度裁剪 gradient clipping:梯度爆炸的解决方法。如果梯度向量大于某个阈值,缩放梯度向量,保证它不会太大。
- GRU单元(Gated Recurrent Unit (GRU) )
GRU (Gated Recurrent Unit, 门控循环单元) :梯度消失的解决方法。
本篇内容很多来自论文:
On the Properties of Neural Machine Translation: Encoder-Decoder Approaches
Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling
之前学的RNN单元的公式和图如下:
在时间步t(位置t)上,有公式:
a < t > = g 1 ( W a a a < t − 1 > + W a x x < t > + b a ) a^{< t >} = g_{1}(W_{aa}a^{< t - 1 >} + W_{ax}x^{< t >} + b_{a}) a<t>=g1(Waaa<t−1>+Waxx<t>+ba)
y ^ < t > = g 2 ( W y a a < t > + b y ) \hat{y}^{< t >} = g_{2}(W_{ya}a^{< t >} + b_{y}) y^<t>=g2(Wyaa<t>+by)
公式简化为:
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)
y ^ < t > = g ( W y a < t > + b y ) \hat{y}^{< t >} = g(W_{y}a^{< t >} +b_{y}) y^<t>=g(Wya<t>+by)
上图 RNN unit 是为了和后面的 GRU unit (simplified) 图 进行对比。
简化了的GRU:
c = memory cell 记忆细胞
c < t > = a < t > c^{<t>} = a^{<t>} c<t>=a<t>
公式1、 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)
公式2、 Γ 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)
公式3、 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 = 1 \Gamma_{u} = 1 Γu=1 时,简化为 c < t > = c ~ < t > c^{<t>} = \tilde{c}^{<t>} c<t>=c~<t> ;在 Γ u = 0 \Gamma_{u} = 0 Γu=0 时,简化为 c < t > = c < t − 1 > c^{<t>} = c^{<t-1>} c<t>=c<t−1> 。
Γ u \Gamma_{u} Γu 的u表示update更新。因为 Γ u = σ ( x x x ) \Gamma_{u} = \sigma(xxx) Γu=σ(xxx),所以 Γ u \Gamma_{u} Γu 在大多数的情况下非常接近0或1。 Γ u \Gamma_{u} Γu的作用就是决定什么时候你会更新 c < t > c^{<t>} c<t>( Γ u = 1 \Gamma_{u}=1 Γu=1时更新, Γ u = 0 \Gamma_{u}=0 Γu=0时维持)。
细节:因为 c < t > c^{<t>} c<t>是一个向量,而 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu是由 c < t − 1 > c^{<t-1>} c<t−1>计算得到的,所以 c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu 是同一个纬度的向量,所以公式3的乘是元素积element-wise product(2个向量相乘得到1个向量)不是点积dot product(2个向量相乘得到1个数字)。
细节:记忆细胞 c < t > c^{<t>} c<t>、更新值 c ~ < t > {\tilde{c}}^{<t>} c~<t>、更新门 Γ u \Gamma_{u} Γu 是同一个纬度的向量。举例:假设 c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu都是100维的向量,那么 c < t > c^{<t>} c<t>中的每个元素都可以记录一件事,比如 c < t > c^{<t>} c<t>中的第1个元素表示主语cat是单数还是复数, c < t > c^{<t>} c<t>中的第2个元素表示宾语是单数还是复数, c < t > c^{<t>} c<t>中的第3个元素表示这句话是在说吃这件事,之类。而 Γ u \Gamma_{u} Γu中的每个元素都是一个门(也可以理解成开关), Γ u \Gamma_{u} Γu中的每个元素都用来决定更新还是维持记忆细胞 c < t > c^{<t>} c<t>中的对应的元素( Γ u \Gamma_{u} Γu向量中的第1个元素决定更新/维持 c < t > c^{<t>} c<t>向量中的第1个元素, Γ u \Gamma_{u} Γu向量中的第2个元素决定更新/维持 c < t > c^{<t>} c<t>向量中的第2个元素,以此类推)。 c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu都是100维的向量,保证了同一维度(100维向量中的第1维、第2维,。。。,第100维,这个维度)的 c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu 元素的一一对应+根据公式相互影响。不同维度的 c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu 元素无法根据公式相互影响。
例子:
“The cat, which already ate ……, was full.”,因为cat是单数,所以应该用was。
cat处, Γ u = 1 \Gamma_{u} = 1 Γu=1, c < t > = c ~ < t > c^{<t>} = \tilde{c}^{<t>} c<t>=c~<t>,即更新 c < t > c^{<t>} c<t> 值。记忆细胞 c < t > c^{<t>} c<t> 将被设定为0(复数)或者1(单数),这里 c < t > = 1 c^{<t>} = 1 c<t>=1 单数。
which、already、ate处: Γ u = 0 \Gamma_{u} = 0 Γu=0 , c < t > = c < t − 1 > c^{<t>} = c^{<t-1>} c<t>=c<t−1>,即维持 c < t > c^{<t>} c<t> 值,于是 c < t > = 1 c^{<t>} = 1 c<t>=1 单数。
was处, c < t > = 1 c^{<t>} = 1 c<t>=1 单数,从cat处维持到了was处,所以这里使用was而不是were。
上图是公式1到公式3画的图,tanh是公式1, σ \sigma σ 是公式2,紫色框是公式3。
上图,输入 c < t − 1 > = a < t − 1 > c^{<t-1>} = a^{<t-1>} c<t−1>=a<t−1>、 x < t > x^{<t>} x<t>,输出 c < t > = a < t > c^{<t>} = a^{<t>} c<t>=a<t>、 y ^ < t > \hat{y}^{<t>} y^<t>。
GRU解决了梯度消失问题的原因:公式3,在 Γ u = 0 \Gamma_{u} = 0 Γu=0 时,简化为 c < t > = c < t − 1 > c^{<t>} = c^{<t-1>} c<t>=c<t−1>。即使经过很多很多的时间步, c < t > c^{<t>} c<t>的值也很好地被维持了。这使得RNN可以处理长期依赖问题。
完整的GRU(在简化了的GRU的基础上,修改了 c ~ < t > \tilde{c}^{<t>} c~<t>的公式,增加了 Γ r \Gamma_{r} Γr的公式, Γ u \Gamma_{u} Γu和 c < t > c^{<t>} c<t>的公式不变。):
c < t > = a < t > c^{<t>} = a^{<t>} c<t>=a<t>
公式1、 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)
公式2、 Γ 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)
公式3、 Γ 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)
公式4、 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>
完整的GRU对比简化了的GRU,添加了一个门 Γ r \Gamma_{r} Γr,你可以认为 r 代表相关性(relevance)。这个 Γ r \Gamma_{r} Γr门告诉你计算出的下一个 c < t > c^{<t>} c<t>的候选值 c ~ < t > \tilde{c}^{<t>} c~<t>跟 c < t − 1 > c^{<t-1>} c<t−1>有多大的相关性。
更新门 Γ u \Gamma_{u} Γu (the update gate)
相关门 Γ r \Gamma_{r} Γr (the relevance gate)
c ~ < t > \tilde{c}^{<t>} c~<t>,这是代替记忆细胞 c < t > c^{<t>} c<t>的候选值,然后我们使用更新门 Γ u \Gamma_{u} Γu来决定是否要用 c ~ < t > \tilde{c}^{<t>} c~<t> 更新 c < t > c^{<t>} c<t>。
学术文章上,有些人用另一种符号表示这些完整的GRU的公式。
吴恩达版本 | 学术界版本 |
---|---|
c ~ < t > \tilde{c}^{<t>} c~<t> | h ~ \tilde{h} h~ |
Γ u \Gamma_{u} Γu | u |
Γ r \Gamma_{r} Γr | r |
c < t > c^{<t>} c<t> | h h h |
我找的一个网站,上面有图:RNN, LSTM & GRU
下方的是完整的GRU的公式,和上方吴恩达版本的完整的GRU公式,在计算之类的方面是完全一样的,只是符号表示不一样。
公式1、 h ~ t = t a n h ( W h [ r t ∗ h t − 1 , x t ] + b h ) \tilde{h}_{t} = tanh( W_{h} [ r_{t} * h_{t-1}, x_{t} ] + b_{h} ) h~t=tanh(Wh[rt∗ht−1,xt]+bh)
公式2、 z t = σ ( W z [ h t − 1 , x t ] + b z ) z_{t} = \sigma( W_{z} [h_{t-1}, x_{t}] + b_{z} ) zt=σ(Wz[ht−1,xt]+bz)
公式3、 r t = σ ( W r [ h t − 1 , x t ] + b r ) r_{t} = \sigma( W_{r} [h_{t-1}, x_{t}] + b_{r} ) rt=σ(Wr[ht−1,xt]+br)
公式4、 h t = z t ∗ h ~ t + ( 1 − z t ) ∗ h t − 1 h_{t} = z_{t} * \tilde{h}_{t} + ( 1 - z_{t} ) * h_{t-1} ht=zt∗h~t+(1−zt)∗ht−1
- 长短期记忆(LSTM (long short term memory) unit)
RNN的两个优化后的版本:GRU (Gated Recurrent Unit, 门控循环单元)、LSTM (long short term memory, 长短期记忆)。
本篇内容很多来自论文:
Long Short-Term Memory | IEEE Xplore
GRU和LSTM公式对比:
GRU | LSTM |
---|---|
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 > = t a n h ( W c [ a < t − 1 > , x < t > ] + b c ) \tilde{c}^{<t>} = tanh(W_{c} [a^{<t-1>},x^{<t>}] + b_{c} ) c~<t>=tanh(Wc[a<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) 。更新门 Γ u \Gamma_{u} Γu (the update gate) | Γ u = σ ( W u [ a < t − 1 > , x < t > ] + b u ) \Gamma_{u} = \sigma( W_{u} [a^{<t-1>}, x^{<t>}] +b_{u} ) Γu=σ(Wu[a<t−1>,x<t>]+bu) 。更新门 Γ u \Gamma_{u} Γu (the update gate) |
Γ 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) 。相关门 Γ r \Gamma_{r} Γr (the relevance gate) | Γ f = σ ( W f [ a < t − 1 > , x < t > ] + b f ) \Gamma_{f} = \sigma( W_{f} [a^{<t-1>}, x^{<t>}] + b_{f} ) Γf=σ(Wf[a<t−1>,x<t>]+bf) 。遗忘门 Γ f \Gamma_{f} Γf (the forget gate) |
Γ o = σ ( W o [ a < t − 1 > , x < t > ] + b o ) \Gamma_{o} = \sigma( W_{o} [a^{<t-1>}, x^{<t>}] + b_{o} ) Γo=σ(Wo[a<t−1>,x<t>]+bo) 。输出门 Γ o \Gamma_{o} Γo (the output gate) | |
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> | 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 > = c < t > a^{<t>} = c^{<t>} a<t>=c<t> | a < t > = Γ o ∗ t a n h ( c < t > ) a^{<t>} = \Gamma_{o} * tanh(c^{<t>}) a<t>=Γo∗tanh(c<t>) |
LSTM的图(符号和运算都符合上方LSTM公式):
窥视孔连接 (peephole connection) :最常用的版本的LSTM。门值不仅取决于 a < t − 1 > a^{<t-1>} a<t−1>和 x < t > x^{<t>} x<t>,也取决于上一个记忆细胞的值 ( c < t − 1 > c^{<t-1>} c<t−1>) ,即:上方LSTM的 Γ u \Gamma_{u} Γu、 Γ f \Gamma_{f} Γf、 Γ o \Gamma_{o} Γo的公式里的 [ a < t − 1 > , x < t > ] [a^{<t-1>}, x^{<t>}] [a<t−1>,x<t>]变成 [ a < t − 1 > , x < t > , c < t − 1 > ] [a^{<t-1>}, x^{<t>}, c^{<t-1>}] [a<t−1>,x<t>,c<t−1>]。
细节: c < t > c^{<t>} c<t>、 c ~ < t > {\tilde{c}}^{<t>} c~<t>、 Γ u \Gamma_{u} Γu、 Γ f \Gamma_{f} Γf、 Γ o \Gamma_{o} Γo 是同一个纬度的向量。举例:在偷窥孔连接的LSTM下, c < t − 1 > c^{<t-1>} c<t−1>是100维的向量,那么 Γ u \Gamma_{u} Γu、 Γ f \Gamma_{f} Γf、 Γ o \Gamma_{o} Γo 也是100维的向量,那么向量 c < t − 1 > c^{<t-1>} c<t−1>里的第1个元素,只能影响门 Γ u \Gamma_{u} Γu、 Γ f \Gamma_{f} Γf、 Γ o \Gamma_{o} Γo 的第1个元素;向量 c < t − 1 > c^{<t-1>} c<t−1>里的第2个元素,只能影响门 Γ u \Gamma_{u} Γu、 Γ f \Gamma_{f} Γf、 Γ o \Gamma_{o} Γo 的第2个元素;以此类推。
LSTM和GRU对比:
LSTM | GRU | |
---|---|---|
发明时间 | 1997 | 2014 |
常用程度 | 更常用 | 没LSTM常用 |
其他 | 更强大和灵活 | GRU是LSTM的简化,更简单、速度更快 |
- 双向循环神经网络(Bidirectional RNN)
双向循环神经网络(Bidirectional recurrent neural networks,BRNN):输入 x < 1 > x^{<1>} x<1>…… x < t > x^{<t>} x<t>…… x < T x > x^{< T_{x}>} x<Tx>的信息,即输入整句话的信息,来预测 y ^ < t > \hat{y}^{<t>} y^<t>。
需要BRNN的原因,举例:
命名实体识别,下面2句话,只看前3个单词,无法判断第3个单词Teddy是否是人名。所以,需要双向循环神经网络。
He said, “Teddy bears are on sale!”
He said, “Teddy Roosevelt was a great President!”
在时间步t(位置t)上, a → < t > \overrightarrow{a}^{< t >} a<t>、 a ← < t > \overleftarrow{a}^{< t >} a<t> 块是标准RNN单元时,BRNN双向循环神经网络 有公式:
y ^ < t > = g ( W y [ a → < t > , a ← < t > ] + b y ) \hat{y}^{<t>} = g( W_{y} [ \overrightarrow{a}^{< t >}, \overleftarrow{a}^{< t >} ] +b_{y} ) y^<t>=g(Wy[a<t>,a<t>]+by)
a → < t > = g ( W a → [ a → < t − 1 > , x < t > ] + b a → ) \overrightarrow{a}^{<t>} = g( W_{\overrightarrow{a}} [ \overrightarrow{a}^{< t-1 >}, x^{<t>} ] + b_{\overrightarrow{a}} ) a<t>=g(Wa[a<t−1>,x<t>]+ba)
a ← < t > = g ( W a ← [ a ← < t + 1 > , x < t > ] + b a ← ) \overleftarrow{a}^{<t>} = g( W_{\overleftarrow{a}} [ \overleftarrow{a}^{< t+1 >}, x^{<t>} ] + b_{\overleftarrow{a}} ) a<t>=g(Wa[a<t+1>,x<t>]+ba)
BRNN双向循环神经网络 的图(acyclic graph 无环图):
第1个图和第2个图是完全一样的,只是使用的符号不同。
BRNN的图,就是一个前向RNN隐层,一个反向RNN隐层,合并两个隐状态得到输出。
举例:输入为 x < 1 > x^{<1>} x<1>…… x < 5 > x^{<5>} x<5>,输出为 y ^ < 1 > \hat{y}^{<1>} y^<1>…… y ^ < 5 > \hat{y}^{<5>} y^<5>,想要得到 y ^ < 3 > \hat{y}^{<3>} y^<3>。根据公式来,计算 y ^ < 3 > \hat{y}^{<3>} y^<3>需要 a → < 3 > , a ← < 3 > \overrightarrow{a}^{<3>}, \overleftarrow{a}^{<3>} a<3>,a<3>;计算 a → < 3 > \overrightarrow{a}^{<3>} a<3>需要从左到右走前向RNN隐层,即依次计算 a → < 1 > \overrightarrow{a}^{<1>} a<1>、 a → < 2 > \overrightarrow{a}^{<2>} a<2>、 a → < 3 > \overrightarrow{a}^{<3>} a<3>;计算 a ← < 3 > \overleftarrow{a}^{<3>} a<3>需要从右到左走反向RNN隐层,即依次计算 a ← < 5 > \overleftarrow{a}^{<5>} a<5>、 a ← < 4 > \overleftarrow{a}^{<4>} a<4>、 a ← < 3 > \overleftarrow{a}^{<3>} a<3>。
第1个图中 a → < t > \overrightarrow{a}^{< t >} a<t>、 a ← < t > \overleftarrow{a}^{< t >} a<t> 块,这个块不仅仅可以是标准RNN单元,也可以是GRU单元或者LSTM单元。即:双向RNN的改进可以用于RNN、GRU、LSTM。
对于大量有自然语言处理问题的文本,有LSTM单元的双向RNN模型是用的最多的。
双向RNN的优点和缺点:
优点 | 缺点 |
---|---|
预测句中任意位置的信息,都会使用整句话的信息,使得预测更加精准。 | 需要得到整句话,才能预测任意位置。举例:语音识别系统,使用双向RNN的话,需要用户一句话说完,才会进行语音识别。 |
- 深层循环神经网络(Deep RNNs)
Deep RNNs:就是堆叠了多层RNN。
图中的 a [ 几 ] < 几 > a^{[几]<几>} a[几]<几>的块不仅仅可以是标准RNN单元、双向RNN单元,也可以是GRU单元或者LSTM单元。即:Deep RNN的改进可以用于RNN、GRU、LSTM、双向RNN。
下图是一个有3个隐层的Deep RNN。只有1个隐层的RNN,就是我们之前学的标准RNN网络。有2个及2个以上的隐层的RNN网络,就叫Deep RNN。
图中, a [ 2 ] < 3 > a^{[2]<3>} a[2]<3>有两个输入,一个是从左边来的,一个是从下面来的。所以, a [ 2 ] < 3 > = g ( W a [ 2 ] [ a [ 2 ] < 2 > , a [ 1 ] < 3 > ] + b a [ 2 ] ) a^{[2]<3>} = g( W_{a}^{[2]} [ a^{[2]<2>}, a^{[1]<3>} ] + b_{a}^{[2]} ) a[2]<3>=g(Wa[2][a[2]<2>,a[1]<3>]+ba[2])。
第1层所有块的计算 公用同一参数 W a [ 1 ] W_{a}^{[1]} Wa[1]和 b a [ 1 ] b_{a}^{[1]} ba[1]来计算,第2层所有块的计算 公用同一参数 W a [ 2 ] W_{a}^{[2]} Wa[2]和 b a [ 2 ] b_{a}^{[2]} ba[2]来计算,以此类推。
很少会看到Deep RNN网络堆叠到100层。一种常见的网络,是在上图Deep RNN的基础上,把 y ^ < t > \hat{y}^{<t>} y^<t>替换成 深层网络(如神经网络)+ y ^ < t > \hat{y}^{<t>} y^<t>,每个 y ^ < t > \hat{y}^{<t>} y^<t>都这么替换,而这些替换得到的深层网络间并不水平相连。
第二周:自然语言处理与词嵌入(Natural Language Processing and Word Embeddings)【词嵌入、嵌入矩阵、学习词嵌入、Word2Vec + Skip-Gram、负采样、GloVe 词向量、情感分类、词嵌入消除偏见】
- 词汇表征(Word Representation)
之前使用one-hot编码来表达单词,这种表示方法,无法展示词汇间的关系,比如orange和apple都是水果,导致机器无法举一反三。
特征化表示每个词,提高算法对相关词的泛化能力。
如果我们能够学习到一个300维的特征向量,或者说300维的词嵌入,通常我们可以做一件事,把这300维的数据嵌入到一个二维空间里,这样就可以可视化了。常用的可视化算法是t-SNE算法,来自于论文 Visualizing data using t-SNE.pdf。
- 使用词嵌入(Using Word Embeddings)
Transfer learning and word embeddings
1、Learn word embeddings from large text corpus.(1-100B words) (Or download pre-trained embedding online.)
2、Transfer embedding to new task with smaller training set. (say, 100k words)
3、Optional: Continue to finetune the word embeddings with new data.
迁移学习与词嵌入
1.从大型文本语料库中学习单词嵌入。(1-100B单词)(或在线下载预先训练的嵌入。)
2.将嵌入转移到具有较小训练集的新任务。(比如100k单词)【比如用300维的词嵌入,代替10000维的one-hot向量。】
3.可选:继续使用新数据微调单词嵌入。【只有第2步中有很大的数据集你才会这样做,通常不需要做这步。】
词嵌入的迁移学习,用于任务的训练集较小的情况,如NLP的命名实体识别,用在文本摘要,用在文本解析、指代消解;不用于有大量数据的任务,如语言模型、机器翻译。原因:迁移学习,你从某一任务A迁移到某个任务B,如果B中有大量数据,B任务自己直接训练就好,没必要迁移学习。
词嵌入和人脸编码之间有一定相似,每个单词都有一个向量(比如300维的词嵌入),每个人脸都有一个向量(编码);不同在于,没出现过的单词,会记为未知单词,没出现过的人脸,我们也会生成一个编码。
- 词嵌入的特性(Properties of Word Embeddings)
类比推理:如果man对应woman,那么king应该对应什么?king应该对应queen。
Man(5391) | Woman(9853) | King(4914) | Queen(7157) | Apple(7157) | Orange(6257) | |
---|---|---|---|---|---|---|
Gender | -1 | 1 | -0.95 | 0.97 | 0.00 | 0.01 |
Royal | 0.01 | 0.02 | 0.93 | 0.95 | -0.01 | 0.00 |
Age | 0.03 | 0.02 | 0.70 | 0.69 | 0.03 | -0.02 |
Food | 0.09 | 0.01 | 0.02 | 0.01 | 0.95 | 0.97 |
上表用4维向量表示每个单词。
e m a n − e w o m a n = [ − 1 0.01 0.03 0.09 ] − [ 1 0.02 0.02 0.01 ] = [ 2 0.01 0.01 0.08 ] ≈ [ 2 0 0 0 ] e_{man} - e_{woman} = \begin{bmatrix} -1 \\ 0.01 \\ 0.03 \\ 0.09 \\ \end{bmatrix} - \begin{bmatrix} 1 \\ 0.02 \\ 0.02 \\ 0.01 \\ \end{bmatrix} = \begin{bmatrix} 2 \\ 0.01 \\ 0.01 \\ 0.08 \\ \end{bmatrix} ≈ \begin{bmatrix} 2 \\ 0 \\ 0 \\ 0 \\ \end{bmatrix} eman−ewoman= −10.010.030.09 − 10.020.020.01 = 20.010.010.08 ≈ 2000
e k i n g − e q u e e n = [ − 0.95 0.93 0.70 0.02 ] − [ 0.97 0.95 0.69 0.01 ] = [ 1.92 0.02 0.01 0.01 ] ≈ [ 2 0 0 0 ] e_{king} - e_{queen} = \begin{bmatrix} -0.95 \\ 0.93 \\ 0.70 \\ 0.02 \\ \end{bmatrix} - \begin{bmatrix} 0.97 \\ 0.95 \\ 0.69 \\ 0.01 \\ \end{bmatrix} = \begin{bmatrix} 1.92 \\ 0.02 \\ 0.01 \\ 0.01 \\ \end{bmatrix} ≈ \begin{bmatrix} 2 \\ 0 \\ 0 \\ 0 \\ \end{bmatrix} eking−equeen= −0.950.930.700.02 − 0.970.950.690.01 = 1.920.020.010.01 ≈ 2000
这个结果表示,man和woman主要的差异是gender(性别)上的差异,而king和queen之间的主要差异也是gender(性别)上的差异, e m a n − e w o m a n = e k i n g − e q u e e n e_{man} - e_{woman} = e_{king} - e_{queen} eman−ewoman=eking−equeen。
结论:当类比推理算法被问及man对woman相当于king对什么时,算法所做的就是计算 e m a n − e w o m a n e_{man}-e_{woman} eman−ewoman,然后找出一个向量也就是找出一个词,使得 e m a n − e w o m a n ≈ e k i n g − e ? e_{man} - e_{woman} ≈ e_{king} - e_{?} eman−ewoman≈eking−e?。当这个新词是queen时,式子的左边会近似地等于右边。
上方发现最先由论文 Linguistic Regularities in Continuous Space Word Representations 提出。
计算当man对woman,那么king对什么,就是找到单词w来让式子 e m a n − e w o m a n ≈ e k i n g − e w e_{man} - e_{woman} ≈ e_{king} - e_{w} eman−ewoman≈eking−ew成立,即:找到单词w来最大化 e w e_{w} ew与 e k i n g − e m a n + e w o m a n e_{king} - e_{man} + e_{woman} eking−eman+ewoman的相似度,即:
F i n d w o r d w : a r g m a x S i m ( e w , e k i n g − e m a n + e w o m a n ) Find\ word\ w: argmax \ Sim( e_{w}, e_{king} - e_{man} + e_{woman} ) Find word w:argmax Sim(ew,eking−eman+ewoman)
argmax:返回最大值的索引。
通过这种方法来做类比推理准确率大概只有30%~75%。
在向量 u u u和 v v v之间的余弦相似度(cosine similarity): C o s i n e S i m i l a r i t y ( u , v ) = u T v ∣ ∣ u ∣ ∣ 2 ∣ ∣ v ∣ ∣ 2 Cosine Similarity(u, v) = \frac{u^{T} v}{||u||_{2} \ ||v||_{2}} CosineSimilarity(u,v)=∣∣u∣∣2 ∣∣v∣∣2uTv = cos(Ф)。 u T v u^{T} v uTv是两个向量的内积, ∣ ∣ u ∣ ∣ 2 ||u||_2 ∣∣u∣∣2是向量 u u u的范数(或长度),Ф是向量 u u u和向量 v v v之间的角度。夹角是0度时,余弦相似度是1;夹角是90度时余弦相似度是0;夹角是180度时,余弦相似度是-1。
上方Sim()可以使用余弦相似度(cosine similarity)来表示,也可以使用 欧几里得距离 = 欧式距离 = 平方距离 (Euclidean distance = Euclidian distance = square distance) ∣ ∣ u − v ∣ ∣ 2 ||u-v||^{2} ∣∣u−v∣∣2 来表示相异度, − ∣ ∣ u − v ∣ ∣ 2 - ||u-v||^{2} −∣∣u−v∣∣2 来表示相似度Sim()。两种方法都可以,用余弦相似度表示Sim()更常见。
词嵌入算法可以学习的类比关系的一般性。比如Man : Woman as Boy : Girl , Big : Bigger as Tall : Taller , Ottawa : Canada as Beijin : China。只要你在大型的文本语料库上实现一个词嵌入学习算法,只要从足够大的语料库中进行学习,词嵌入算法就能自主地发现这些模式。
- 嵌入矩阵(Embedding Matrix)
E:嵌入矩阵(Embedding Matrix),包含了词汇表中所有单词的嵌入向量。
O j O_{j} Oj:只有第j个位置是1的one-hot向量。
e j e_{j} ej:字典中单词j的嵌入向量。
E × O j = e j E × O_{j} = e_{j} E×Oj=ej
如果有10000个单词,每个单词有300个特征,那么E就是个300×10000的矩阵, O j O_{j} Oj是个10000×1的向量, e j e_{j} ej是个300×1的向量。如上图, e j e_{j} ej其实就是E的第j列。
In practice, use specialized function to look up an embedding.
在实践中,使用专门的函数来查找嵌入向量。
我们的目标是学习一个嵌入矩阵E。可以随机地初始化矩阵E,然后使用梯度下降法来学习矩阵E中的各个参数,E乘以这个one-hot向量会得到嵌入向量。
在实践中你会使用一个专门的函数来单独查找矩阵E的某列,而不是用图中的矩阵乘法来做。例如在Keras中就有一个嵌入层,可以用这个嵌入层更有效地从嵌入矩阵中提取出你需要的列。
- 学习词嵌入(Learning Word Embeddings)
建立一个语言模型是学习词嵌入的好方法。该想法来自论文:A neural probabilistic language model
上图实现语言模型,预测句子"I want a glass of orange ___."的下一个词。随机生成一个嵌入矩阵E(对所有的单词用的都是同一个矩阵E,即上图6个E是同一个E),用E得到 e j e_{j} ej,每个 e j e_{j} ej是300维的向量,有6个 e j e_{j} ej,神经网络的输入是6×300=1800维的向量。经过神经网络以后再通过softmax层,softmax分类器会在10000个可能的输出中预测结尾这个单词。通过反向传播+梯度下降法,学习训练集,得到更好的E中各个参数。
总结上段:我们的目标是学习一个嵌入矩阵E(可以理解成单词与单词之间的在不同角度的关系)。可以随机地初始化矩阵E,然后使用梯度下降法来学习矩阵E中的各个参数,E乘以这个one-hot向量会得到嵌入向量。
实际上更常见的是有一个固定的历史窗口。用一个固定的历史窗口就意味着你可以处理任意长度的句子(用不同长度的句子来训练),因为输入的维度总是固定的。举例,你总是想预测给定4个单词后的下一个单词,a glass of orange ___。举例,不管来多长的句子,每个 e j e_{j} ej是300维的向量,输入有4个 e j e_{j} ej,神经网络的输入是4×300=1200维的向量。
这就是早期最成功的学习词嵌入,学习这个矩阵E的算法之一。
目标词 target:要预测出来的单词。
上下文 context:目标词的上下文,用于推断目标词。
研究人员已经尝试过很多不同类型的上下文。如果你要建立一个语言模型,那么一般选取目标词之前的几个词作为上下文。但如果你的目标是学习词嵌入,那么你可以选择其他的上下文。
- Word2Vec
本节内容大多来自论文:Efficient Estimation of Word Representations in Vector Space 。该论文讲了2个不同版本的Word2Vec模型,即:Skip-Gram、CBOW(Continuous Bag-Of-Words Model,连续词袋模型)。我们只讲使用Skip-Gram模型得到词嵌入模型(嵌入矩阵E)。
在Skip-Gram模型中,我们要做的是抽取上下文和目标词配对,来构造一个监督学习问题。具体是,给定上下文词,要求你预测在这个词正负10个词距或者正负5个词距内随机选择的某个目标词。构造这个监督学习问题的目标并不是想要解决这个监督学习问题本身,而是想要使用这个学习问题来学到一个好的词嵌入模型。
下面是Skip-Gram模型的细节:
vocabulary size=10000k,即词汇表10000个单词的情况下,
模型输入context,输出target。
模型: O c O_{c} Oc——》E——》 e c e_{c} ec——》神经网络+softmax——》 y ^ \hat{y} y^。
O c O_{c} Oc:就是输入的context的one-hot向量。之前讲过, O j O_{j} Oj,只有第j个位置是1的one-hot向量, E × O j = e j E × O_{j} = e_{j} E×Oj=ej,这里公式是一样的,只是把j写成c。
y ^ \hat{y} y^:是10000维的向量,是所有可能目标词的概率,里面都是0.xx的小数。
这是softmax模型,预测不同目标词的概率:
S o f t m a x : p ( t ∣ c ) = e θ t T e c ∑ j = 1 10000 e θ j T e c Softmax : p(t | c) = \frac{ e^{ θ_{t}^{T} e_{c} } }{ \sum_{j = 1}^{10000} e^{ θ_{j}^{T} e_{c} } } Softmax:p(t∣c)=∑j=110000eθjTeceθtTec
这里 θ t θ_{t} θt是一个与输出t有关的参数,即某个词t和标签相符的概率是多少。公式中省略了softmax中的偏差项,想要加上的话也可以加上。p(t|c),p表示概率,t是target,c是context。
softmax的损失函数就像之前一样:
L ( y ^ , y ) = − ∑ i = 1 10000 y i log y ^ i L(\hat{y}, y) = - \sum_{i = 1}^{10000} y_{i} \log \hat{y}_{i} L(y^,y)=−i=1∑10000yilogy^i
y是只有一个1其他都是0的one-hot向量,表示目标词, y ^ \hat{y} y^是10000维的向量,是所有可能目标词的概率,里面都是0.xx的小数。
通过Skip-Gram模型,优化参数的损失函数,你就会得到一个较好的嵌入向量集。
softmax分类的问题,实际上使用这个算法会遇到一些问题,
问题1:计算速度。每次你想要计算概率p(t|c),你需要对你词汇表中的所有10,000个词做求和计算。
解决方案:如分级(hierarchical)的softmax分类器和负采样(Negative Sampling)。
问题2:怎么对上下文context进行采样?
答:如果你对语料库均匀且随机地采样,你会经常采样到the、of、a、and、to这样的词,而不是orange、apple这样的词,这会导致你花大部分的力气来更新这些频繁出现的单词的 e c e_{c} ec。(我们的目标是学习一个嵌入矩阵E,可以理解成单词与单词之间的在不同角度的关系。)实际上 p ( c ) p(c) p(c)词的分布并不是单纯的在训练集语料库上均匀且随机的采样得到的,而是采用了不同的分级来平衡更常见的词和不那么常见的词。
- 负采样(Negative Sampling)
本节内容很多来自论文:Distributed Representations of Words and Phrases and their Compositionality 。
Skip-Gram模型构造一个监督学习任务,用于学习词嵌入,它的缺点就在于softmax计算起来很慢。负采样能做到与Skip-Gram模型相似的事情,但是用了一个更加有效的学习算法。
如图,第一行是正样本,即在句中选择1个上下文词,再在这个词正负10个词距或者正负5个词距内随机选择1个目标词,y=1,作为正样本;下面K行是负样本,用与正样本相同的上下文词,再从字典中随机选取词作为目标词,y=0,作为负样本。
出现以下情况也没关系,就是如果负样本从字典中随机选到的词,正好出现在了句中词距内,如图中的of。
构造一个监督学习问题,输入是(上下文词,目标词),输出是1/0。因此问题就是给定一对词,它们会在一句话中同时出现吗?
如何选取K?小数据集,K=5到20。大数据集,K=2到5。数据集越小K就越大。
S o f t m a x : p ( t ∣ c ) = e θ t T e c ∑ j = 1 10000 e θ j T e c Softmax : p(t | c) = \frac{ e^{ θ_{t}^{T} e_{c} } }{ \sum_{j = 1}^{10000} e^{ θ_{j}^{T} e_{c} } } Softmax:p(t∣c)=∑j=110000eθjTeceθtTec
为了定义模型,我们将使用记号c表示上下文词,记号t表示可能的目标词,我再用y表示0和1,表示是否是一对上下文-目标词。我们要做的就是定义一个逻辑回归模型,给定输入的c,t对的条件下,y=1的概率,即:
P ( y = 1 ∣ c , t ) = σ ( θ t T e c ) P( y = 1 | c,t ) = σ(θ_{t}^{T} e_{c}) P(y=1∣c,t)=σ(θtTec)
这个模型将一个sigmoid函数作用于 θ t T e c θ_{t}^{T} e_{c} θtTec,参数和之前一样。
Skip-Gram模型使用softmax分类器,每次迭代更新10000维(整个词典),而负样本模型,把softmax的多分类换成了10000个sigmoid二分类,每次迭代只训练它们其中的5个,就是K+1个,其中K个负样本和1个正样本。这也是为什么这个算法计算成本更低,因为只需更新K+1个逻辑单元,K+1个二分类问题。
如何选取负样本?
极端方法1:通过词出现的频率对其进行采样。但这会导致在like、the、of、and这样的词上有很高的频率。极端方法2:用1除以词汇表总词数,即 1 ∣ v ∣ \frac{1}{|v|} ∣v∣1,均匀且随机地抽取负样本,这对于英文单词的分布是非常没有代表性的。
所以论文的作者Mikolov等人根据经验,他们发现这个经验值的效果最好,它位于这两个极端的采样方法之间,既不用经验频率,也不用均匀分布,他们采用以下方式:
P ( w i ) = f ( w i ) 3 4 ∑ j = 1 10 , 000 f ( w j ) 3 4 P(w_{i}) = \frac{ f(w_{i})^{\frac{3}{4}} }{ \sum_{j = 1}^{10,000} f(w_{j})^{\frac{3}{4}} } P(wi)=∑j=110,000f(wj)43f(wi)43
f ( w i ) f(w_{i}) f(wi)是观测到的在语料库中的某个英文词的词频,通过 3 4 \frac{3}{4} 43次方的计算,使其处于完全独立的分布和训练集的观测分布两个极端之间。
- GloVe 词向量(GloVe Word Vectors)【没看懂,也不重要,就没怎么做笔记】
本节内容很多来自论文:Glove: Global Vectors for Word Representation 。
GloVe算法的优点是简便,该算法不如Word2Vec或是Skip-Gram模型用的多。
X i j X_{ij} Xij就是一个能够获取单词i和单词j出现位置相近时或是彼此接近的频率的计数器,GloVe算法公式:
m i n i m i z e ∑ i = 1 10 , 000 ∑ j = 1 10 , 000 f ( X i j ) ( θ i T e j + b i − b j ′ − l o g X i j ) 2 minimize \sum_{i = 1}^{10,000} \sum_{j = 1}^{10,000} f(X_{ij}) ( θ_{i}^{T} e_{j} + b_{i} - b_{j}^{'} - log X_{ij} )^{2} minimize∑i=110,000∑j=110,000f(Xij)(θiTej+bi−bj′−logXij)2
计算机学出来的特征不是我们认识的特征。轴的意义不一定明确,并且轴之间不一定正交。
- 情感分类(Sentiment Classification)
情感分类一个最大的挑战就是标记的训练集没有那么多。对于情感分类任务来说,训练集大小从10,000到100,000个单词都很常见,甚至有时会小于10,000个单词,采用了词嵌入能够带来更好的效果,尤其是只有很小的训练集时。
简单的情感分类的模型:
已有嵌入矩阵E,输入句子,使用 E × O j = e j E × O_{j} = e_{j} E×Oj=ej把句中所有单词都转化为嵌入向量 e j e_{j} ej,假设嵌入向量 e j e_{j} ej是300维度,把这句话的所有嵌入向量求和或者求平均,会得到一个300维的特征向量,把这个特征向量送进softmax分类器,然后输出 y ^ \hat{y} y^, y ^ \hat{y} y^是一星到五星这5个结果的概率值。
这个算法有一个问题就是没考虑词序,比如这句一星的差评,“Completely lacking in good taste, good service, and good ambiance.”,句中有3个good,该算法忽略词序,仅仅把所有单词的词嵌入加起来或者平均下来,分类器很可能认为这是一个好的评论。
复杂的情感分类的模型:
如图是一个多对一的RNN,它可以考虑词的顺序,区分"not good"与"good"。
图中的E是在更大的数据集上训练的,然后再使用情感分类的训练集来训练该情感分类模型。这样,如果情感分类模型训练过"lacking in good"是个负面评价,那么,情感分类模型能通过嵌入矩阵E进行举一反三,知道"absent of good"是个负面评价。
- 词嵌入除偏(Debiasing Word Embeddings)
本节内容很多来自论文:Man is to Computer Programmer as Woman is to Homemaker? Debiasing Word Embeddings 。
偏见比如说性别歧视、种族歧视等等,本节讲消除 已经训练完成的词嵌入 中的偏见的办法。
1、Identify bias direction.
2、Neutralize: For every word that is not definitional, project to get rid of bias.
3、Equalize pairs.
1、 确定偏差方向。
2、 中立:对于每一个没有定义的词,计划消除偏见。
3、 均衡配对。
用性别歧视举例,第一步使用有性别的词汇,如he-she、male-female,取平均,找到中轴线。此时确定了坐标轴,即:bias direction(1维)、non-bias direction(299维)。第二步,把定义不确切的词,即定义中没有性别内容的词,如doctor-babysitter,中和到中轴线上。第三步,即使把babysitter放到中轴线上,然而babysitter距离grandmother、grandfather的距离不相等,仍然有歧视,所以移动grandmother-grandfather,让这两个词距离中轴线的距离相等,其他明确定义性别的词汇也这样做,如he-she。
减少或消除学习算法中的偏见问题是个十分重要的问题,因为这些算法会用来辅助制定越来越多的社会中的重要决策。
第三周:序列模型和注意力机制(Sequence models & Attention mechanism)【seq2seq模型(编码器解码器架构=编码解码)、集束搜索、Bleu 得分、注意力模型+编码解码架构、语音识别、触发字检测】
- 基础模型(Basic Models)
seq2seq(sequence to sequence)、集束搜索(Beam search)和注意力模型(Attention Model)。
上图来自论文:
Sequence to Sequence Learning with Neural Networks
Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation
上图是:seq2seq模型。
上图是一个用于机器翻译的RNN模型,RNN单元可以用GRU或LSTM,它分为两部分:编码网络encoder network(黑色部分)、解码网络decoder network(蓝色部分)。
上图来自论文,这几篇论文同一时间出现且内容基本一致:
Deep Captioning with Multimodal Recurrent Neural Networks (m-RNN)
Show and Tell: A Neural Image Caption Generator
Deep visual-semantic alignments for generating image descriptions
上图是:image to sequence模型 ,也叫 图像描述模型。
上图是图像描述功能的模型,图片进行卷积,图片走过 去掉最后的softmax单元的预训练的AlexNet,得到4096维的特征向量,向量表示的就是这只猫的图片,这个预训练网络是图像的编码网络。把向量输入到RNN中,生成一个输出序列,即图片描述。
- 选择最可能的句子(Picking the most likely sentence)
把机器翻译想成是建立一个条件语言模型(conditional language model)。原因如下:
语言模型: P ( y < 1 > , . . . , y < T y > ) P(y^{<1>}, ..., y^{<T_{y}>}) P(y<1>,...,y<Ty>) 。
机器翻译模型: P ( y < 1 > , . . . , y < T y > ∣ x < 1 > , . . . , x < T x > ) P(y^{<1>}, ..., y^{<T_{y}>} | x^{<1>}, ..., x^{<T_{x}>}) P(y<1>,...,y<Ty>∣x<1>,...,x<Tx>) 。
一句话会有多种可能的翻译,你需要找到最优的翻译。在开发机器翻译系统时,你需要想出一个算法,用来找出合适的y值,使得条件概率P最大化,而解决这种问题最通用的算法就是束搜索(Beam Search)。
a r g m a x y < 1 > , . . . , y < T y > P ( y < 1 > , . . . , y < T y > ∣ x ) argmax_{y^{<1>}, ..., y^{<T_{y}>}} P(y^{<1>}, ..., y^{<T_{y}>} | x) argmaxy<1>,...,y<Ty>P(y<1>,...,y<Ty>∣x)
为什么不用贪心搜索(Greedy Search)呢?
原因:贪心搜索得到的是局部最优,局部最优不一定是全局最优,而机器翻译希望达到全局最优。
机器翻译模型和之前的语言模型一个主要的区别就是,相比语言模型随机地生成句子,在机器翻译模型中你要找到最有可能的翻译句子,但是可能的句子组合数量过于巨大(字典有10000个单词,如果一句话10个词,那么就是 1000 0 10 10000^{10} 1000010个组合),无法一一列举,所以我们需要一种合适的搜索算法。
- 集束搜索(Beam Search)
集束搜索算法会有一个参数B,叫做集束宽(beam width),比如B=3。每个单词位置,都只考虑最可能的B个单词,并沿着这B个单词往下走。
B=1时,集束搜索就变成了贪心搜索,贪心搜索每个单词位置,都只考虑最可能的那1个单词,并沿着这1个单词往下走。
下面以机器翻译举例,已经输入要翻译的原文x,并走了encoder网络,接下来要走decoder网络,用RNN一步步翻译译文。
上图,第1个单词位。
输出的 y ^ < 1 > \hat{y}^{<1>} y^<1>是10000个概率值,对应 P ( y < 1 > ∣ x ) P(y^{<1>} | x) P(y<1>∣x) 是在已知x(要翻译的原文)后 第1个单词的概率。因为B=3,所以选3个概率值最高的单词,沿着这3个单词往下走。
上图,前2个单词位。
第1个单词位有3个单词,沿着这3个单词往下走,有3×10000=30000个选择,再在这30000个选择中,选3个 前2个单词的概率值总体最高的组合,沿着这3种组合往下走。
y ^ < 1 > \hat{y}^{<1>} y^<1> 对应 P ( y < 1 > ∣ x ) P(y^{<1>} | x) P(y<1>∣x) 是第1个单词的概率, y ^ < 2 > \hat{y}^{<2>} y^<2> 对应 P ( y < 2 > ∣ x , y < 1 > ) P(y^{<2>} | x, y^{<1>}) P(y<2>∣x,y<1>) 是第2个单词的概率。
y ^ < 1 > \hat{y}^{<1>} y^<1>和 y ^ < 2 > \hat{y}^{<2>} y^<2> 一起对应 P ( y < 1 > , y < 2 > ∣ x ) = P ( y < 1 > ∣ x ) × P ( y < 2 > ∣ x , y < 1 > ) P(y^{<1>}, y^{<2>} | x) = P(y^{<1>} | x) × P(y^{<2>} | x, y^{<1>}) P(y<1>,y<2>∣x)=P(y<1>∣x)×P(y<2>∣x,y<1>),是第1个和第2个单词对的概率,即是前2个单词组合的总体概率值。
因为B=3,每一步我们都复制3个,同样的这种网络来评估部分句子和最后的结果,我们有3个网络副本,每个网络的第1个单词不同。
以此类推。
- 改进集束搜索(Refinements to Beam Search)
使用 长度归一化(Length normalization)改进集束搜索。
用该式子来理解公式1:
P ( y < 1 > . . . y < T y > ∣ X ) P(y^{<1>} ... y^{<T_{y}>} | X) P(y<1>...y<Ty>∣X)
= P ( y < 1 > ∣ X ) P ( y < 2 > ∣ X , y < 1 > ) P ( y < 3 > ∣ X , y < 1 > , y < 2 > ) … P ( y < T y > ∣ X , y < 1 > , y < 2 > . . . y < T y − 1 > ) P(y^{<1>}|X) P(y^{<2>} | X, y^{<1>}) P(y^{<3>} | X, y^{<1>}, y^{< 2>}) … P(y^{< T_{y} >}| X, y^{<1>},y^{<2>} ... y^{< T_{y} - 1 >}) P(y<1>∣X)P(y<2>∣X,y<1>)P(y<3>∣X,y<1>,y<2>)…P(y<Ty>∣X,y<1>,y<2>...y<Ty−1>)
下方是公式改进过程,从公式1,改进到公式2,改进到公式3。
公式1: a r g m a x y ∏ t = 1 T y P ( y < t > ∣ x , y < 1 > , . . . , y < t − 1 > ) argmax_{y} \prod_{t=1}^{T_{y}} P(y^{<t>}| x, y^{<1>}, ..., y^{<t- 1>}) argmaxy∏t=1TyP(y<t>∣x,y<1>,...,y<t−1>)
公式2: a r g m a x y ∑ t = 1 T y l o g P ( y < t > ∣ x , y < 1 > , . . . , y < t − 1 > ) argmax_{y} \sum_{t=1}^{T_{y}} log \ P(y^{<t>}| x, y^{<1>}, ..., y^{<t- 1>}) argmaxy∑t=1Tylog P(y<t>∣x,y<1>,...,y<t−1>)
公式3: 1 T y a ∑ t = 1 T y l o g P ( y < t > ∣ x , y < 1 > , . . . , y < t − 1 > ) \frac{1}{{T_{y}}^a} \sum_{t=1}^{T_{y}} log \ P(y^{<t>}| x, y^{<1>}, ..., y^{<t- 1>}) Tya1∑t=1Tylog P(y<t>∣x,y<1>,...,y<t−1>)
公式1改进到公式2:
公式1是很多概率P相乘,这些概率都是小于1的,很多小于1的数乘起来,会得到很小很小的数字,会造成数值下溢(numerical underflow)。数值下溢就是数值太小了,导致电脑的浮点表示不能精确地储存。
所以把公式1改进成公式2,原理是 l o g a ( M N ) = l o g a M + l o g a N log_{a}(MN) = log_{a}M + log_{a}N loga(MN)=logaM+logaN,且log函数是个单调递增函数,所以最大化 l o g P ( y ∣ x ) log \ P(y|x) log P(y∣x)和最大化 P ( y ∣ x ) P(y|x) P(y∣x)结果一样。通过该改进,会得到一个数值上更稳定的算法,不容易出现四舍五入的误差。
公式2改进到公式3:
公式1是很多小于1的概率P的乘积,所以如果句子越长,要乘的P就会越多,而乘积就会越小,所以该公式更偏向短的输出。公式2也是如此,公式2是很多 log P 相加,P都是小于1的数,log P 就是个复数,所以句子越长,累加得到的结果就越小,所以该公式更偏向短的输出。
所以把公式2改进成公式3,使用 长度归一化(Length normalization)来改进,就是除以 T y T_{y} Ty,明显地减少了对输出长的结果的惩罚。
在实践中,会设置超参数a,把除以 T y T_{y} Ty变成除以除以 T y a {T_{y}}^a Tya,如果a等于1,就相当于完全用长度来归一化,如果a等于0, T y 0 {T_{y}}^0 Ty0 = 1,就相当于完全没有归一化。a是算法的超参数(hyper parameter),需要调整大小来得到最好的结果。
如何运行束搜索算法?
比如束宽B=3,运行集束搜索算法得到3个句子,如果运行束搜索30步,那这3个句子的长度会在[1,30]都有可能。然后用公式3给这3个句子打分,挑选出得分最高的一个句子,这个句子作为最终翻译结果。
公式3也叫做:归一化的对数似然目标函数(a normalized log likelihood objective)。
束宽B的长度讨论:
large B: better result, slower.
small B: worse result, faster.
大B:结果更好,速度更慢。
小B:结果更差,速度更快。
在商业产品中,经常可以看到把束宽设到10。在科研中,为了得到更好的结果来发表论文,经常看到大家用束宽为1000或者3000。
当B很大的时候,性能提高会越来越少。就是说,从束宽1,也就是贪心算法,到束宽为3、到10,你会看到一个很大的改善。但是当束宽从1000增加到3000时,效果就没那么明显了。
集束搜索不是精确搜索,不能保证一定能找到准确的最大值 a r g m a x y P ( y ∣ x ) argmax_{y} \ P(y|x) argmaxy P(y∣x)。
精确的搜索算法比如:广度优先搜索(BFS, Breadth First Search algorithms)、深度优先搜索(DFS, Depth First Search)。
- 集束搜索的误差分析(Error analysis in beam search)
通过误差分析,可以知道预测结果出错,是束搜索算法、RNN模型,哪一方的错误,好更有针对性的解决。
上图,人工翻译记为y*,算法翻译记为 y ^ \hat{y} y^。例子中的算法翻译改变了句子的本意,是个不好的翻译。
机器翻译的模型有2部分:RNN模型(神经网络模型,序列到序列模型,编码器和解码器)、束搜索算法。我们想要知道2部分中是哪部分造成这个错误。
情况1: P ( y ∗ ∣ x ) > P ( y ^ ∣ x ) P(y^{*}|x) > P(\hat{y}|x) P(y∗∣x)>P(y^∣x),束算法出错。
情况2: P ( y ∗ ∣ x ) ≤ P ( y ^ ∣ x ) P(y^{*}|x) ≤ P(\hat{y}|x) P(y∗∣x)≤P(y^∣x),RNN模型出错。
这里略过了有关长度归一化(length normalizations)的细节,如果你用了某种长度归一化,那么就不是比较这两种可能性大小,而是比较长度归一化后的最优化目标函数值,即比较:公式3: 1 T y a ∑ t = 1 T y l o g P ( y < t > ∣ x , y < 1 > , . . . , y < t − 1 > ) \frac{1}{{T_{y}}^a} \sum_{t=1}^{T_{y}} log \ P(y^{<t>}| x, y^{<1>}, ..., y^{<t- 1>}) Tya1∑t=1Tylog P(y<t>∣x,y<1>,...,y<t−1>)。
误差分析过程:遍历开发集,并在其中找出算法产生的错误,对于每个错误,都计算 P ( y ∗ ∣ x ) P(y^{*}|x) P(y∗∣x) 与 P ( y ^ ∣ x ) P(\hat{y}|x) P(y^∣x),得到束算法出错还是RNN模型出错。最终得出束搜索算法和RNN模型出错的比例是多少,哪个是产生大部分错误的原因。
束搜索算法出错解决方案:增大集束宽度B。
RNN模型出错解决方案:进行更深层次的分析,来决定是需要增加正则化还是获取更多的训练数据,或是尝试一个不同的网络结构,或是其他方案。你在第三门课中,了解到各种技巧都能够应用在这里。
- Bleu 得分(选修)(Bleu Score (optional))
本节内容很多来自论文:BLEU: a Method for Automatic Evaluation of Machine Translation 。
BLEU:bilingual evaluation understudy (双语评估替补)。
BLEU得分做的就是,给定一个机器生成的翻译,它能够自动地计算一个分数来衡量机器翻译的好坏。由机器打分,替代人力劳动。
精确度 = 机器翻译中有几个词出现在参考翻译中 机器翻译长度 \frac{机器翻译中有几个词出现在参考翻译中}{机器翻译长度} 机器翻译长度机器翻译中有几个词出现在参考翻译中
改进后的精确度 = 机器翻译中有几个词出现在参考翻译中,把每一种单词的记分上限定为它在参考句子中出现的最多次数 机器翻译长度 \frac{机器翻译中有几个词出现在参考翻译中,把每一种单词的记分上限定为它在参考句子中出现的最多次数}{机器翻译长度} 机器翻译长度机器翻译中有几个词出现在参考翻译中,把每一种单词的记分上限定为它在参考句子中出现的最多次数
一元词组(unigrams)就是单个单词,二元词组(bigrams)就是成对的词。
先提取机器翻译的所有二元词组(二元词组列),并得到机器翻译中每个二元词组出现的次数(Count列)。然后得到二元词组列中每个词组在参考翻译中出现的次数,上限值为二元词组出现在参考1或2中的最大次数( C o u n t c l i p Count_{clip} Countclip列),这是截取计数 the clipped count。
改进后的精确度 = ∑ C o u n t c l i p 列 ∑ C o u n t 列 \frac{\sum Count_{clip}列}{\sum Count列} ∑Count列∑Countclip列
机器翻译结果记为 y ^ \hat{y} y^。
P n P_n Pn:n元词组n-grams 的精确度。
P n = ∑ n − g r a m s ∈ y ^ C o u n t c l i p ( n − g r a m ) ∑ n − g r a m s ∈ y ^ C o u n t ( n − g r a m ) P_{n} = \frac{ \sum_{n-grams∈\hat{y}} Count_{clip}(n-gram) }{ \sum_{n-grams∈\hat{y}} Count(n-gram) } Pn=∑n−grams∈y^Count(n−gram)∑n−grams∈y^Countclip(n−gram)
如果机器翻译输出与参考翻译1或是参考翻译2完全一致的话,那么 P 1 P_1 P1、 P 2 P_2 P2… P n P_n Pn的值都会等于1.0。不过有时即使输出结果并不完全与参考相同, P 1 P_1 P1、 P 2 P_2 P2… P n P_n Pn的值都会等于1.0,也是有可能实现的。
综合Bleu分数: B P × e x p ( 1 4 ∑ n = 1 4 P n ) BP × exp (\frac{1}{4} \sum_{n=1}^{4} P_{n}) BP×exp(41∑n=14Pn)
BP:brevity penalty,简短惩罚。事实表明,如果你输出了一个非常短的翻译,那么它会更容易得到一个高精确度,因为输出的大部分词可能都出现在参考之中。不过我们并不想要特别短的翻译结果,因此简短惩罚(BP)就是一个调整因子,它能够惩罚输出了太短翻译结果的翻译系统。
BLEU得分被用来评估许多生成文本的系统(systems that generate text),比如说机器翻译系统(machine translation systems)、图像描述系统(image captioning systems)。但它不用于语音识别(speech recognition),因为在语音识别当中,通常只有一个答案,你可以用其他的评估方法,来评估你的语音识别结果,是否十分相近或是字字正确。
对于机器翻译来说,有多个一样好的翻译结果,BLEU得分就给了你一个能够自动评估的方法,帮助加快算法开发进程。
- 注意力模型直观理解(Attention Model Intuition)
本节内容很多来自论文,注意力模型源于:Neural Machine Translation by Jointly Learning to Align and Translate
使用编码解码架构(a Encoder-Decoder architecture)来完成机器翻译。我们要对编码解码架构做一些改变,称为注意力模型(the Attention Model),这会使机器翻译工作得更好。
注意力机制的直观理解就是:翻译每个词时要联系这个词前后的句子上下文,而这个句子上下文不要太长。
注意力模型让一个神经网络只注意到一部分的输入句子。当它在生成句子的时候,更像人类翻译。
机器翻译,使用编码解码架构,输入整个句子,整句话一起翻译,再输出。
人工翻译,看一部分句子,翻译一部分句子,不断重复,直到翻译完成整句话。因为句子太长时,人无法记忆整句话,也就无法做到整句话一起翻译。
机器翻译的Bleu分数,句子短时,分数高,句子长时,分数低。
注意力模型,它翻译得很像人类,一次翻译句子的一部分。注意力模型的Bleu分数,不管句子长短,得分都高,不会在句子长时有一个巨大的下倾,这个下倾实际上衡量了神经网络记忆一个长句子的能力。
上图,是用于机器翻译的编码解码架构。下方一行是编码器网络,是双向RNN网络,上方一行是解码器网络,是单向RNN网络。
解码器网络,每个单元输入3部分:上个单元输出的状态S,上个单元输出的翻译单词,上下文(context)C。
注意力权重(attention weights): a < 3 , t > a^{<3, t>} a<3,t>表示,要生成翻译的第3个词时,放多少注意力在原文第t个词上。比如,生成第3个词时,要放多少注意力在原文第2、3、4个词上。
- 注意力模型(Attention Model)
上图,是用于机器翻译的编码解码架构。下方一行是编码器网络,是双向RNN网络,上方一行是解码器网络,是单向RNN网络。
用 t’ 来索引要原文句子的词,用 t 来索引译文句子的词。
有公式 a < t > = ( a → < t > , a ← < t > ) a^{<t>} = (\overrightarrow{a}^{< t >}, \overleftarrow{a}^{< t >}) a<t>=(a<t>,a<t>),所以图中编码器网络的激活值 a < t ′ > = ( a → < t ′ > , a ← < t ′ > ) a^{<t'>} = (\overrightarrow{a}^{< t' >}, \overleftarrow{a}^{< t' >}) a<t′>=(a<t′>,a<t′>)。
a < t , t ′ > a^{<t, t'>} a<t,t′> = amount of attention y < t > y^{<t>} y<t> should pay to a < t ′ > a^{<t'>} a<t′> = y < t > y^{<t>} y<t> 花费在 a < t ′ > a^{<t'>} a<t′> 上的注意力的数量。
假如目前翻译到译文的第 t 个词,那么有:
∑ t ′ a < t , t ′ > = 1 \sum_{t'} a^{<t, t'>} = 1 ∑t′a<t,t′>=1
c < t > = ∑ t ′ a < t , t ′ > a < t ′ > c^{<t>} = \sum_{t'} a^{<t, t'>} a^{<t'>} c<t>=∑t′a<t,t′>a<t′>。 c < t > c^{<t>} c<t>是解码器第 t 个单元的输入, a < t , t ′ > a^{<t, t'>} a<t,t′>是注意力权重, a < t ′ > a^{<t'>} a<t′>是编码器学习得到的激活值。
注意力机制就是加权求和, a < t , t ′ > a^{<t, t'>} a<t,t′>就是权重。
注意力模型公式: a < t , t ′ > = e x p ( e < t , t ′ > ) ∑ t ′ = 1 T x e x p ( e < t , t ′ > ) a^{<t, t'>} = \frac{ exp(e^{<t, t'>}) }{ \sum_{t'=1}^{T_{x}} exp(e^{<t, t'>}) } a<t,t′>=∑t′=1Txexp(e<t,t′>)exp(e<t,t′>)
使用softmax来确保 ∑ t ′ a < t , t ′ > = 1 \sum_{t'} a^{<t, t'>} = 1 ∑t′a<t,t′>=1 。
上图左下角, a < t , t ′ > a^{<t, t'>} a<t,t′>和 e < t , t ′ > e^{<t, t'>} e<t,t′>应该取决于 s < t − 1 > s^{<t-1>} s<t−1>和 a < t ′ > a^{<t'>} a<t′>。但是我们不知道具体函数是什么,所以我们可以做的事情就是训练一个很小的神经网络,去学习这个函数到底是什么。
这个算法的一个缺点就是它要花费2次方的时间,就是说这个算法的复杂是 O ( n 2 ) O(n^{2}) O(n2)的,如果你有 T x T_x Tx个输入单词和 T y T_y Ty个输出单词,于是注意力参数的总数就会是 T x × T y T_x × T_y Tx×Ty,所以这个算法有着2次方的消耗。
但是在机器翻译的应用上,输入和输出的句子一般不会太长,可能2次方的消耗可以接受,但也有很多研究工作,尝试去减少这样的消耗。
把注意力机制应用到图片加标题(image captioning)上的论文,当你在写图片标题的时候,一次只花注意力在一部分的图片上面:Show, Attend and Tell: Neural Image Caption Generation with Visual Attention 。
注意力模型可以用于日期标准化。
可视化 a < t , t ′ > a^{<t, t'>} a<t,t′>,这显示了当注意力模型生成某个输出词时,通常会花注意力在这个输出词对应的输入词上面。
- 语音识别(Speech recognition)
语音识别,输入音频片段x,输出文本y。
上图,左侧中间的图,横轴是时间,纵轴是气压。左下方的图,是声谱图(a spectrogram),横轴是时间,纵轴是声音的频率,不同颜色是声波能量的大小,也就是在不同的时间和频率上这些声音有多大。
音频数据的常见预处理步骤,就是运行左中图的原始的音频片段,然后生成一个左下图的声谱图(a spectrogram)。伪空白输出(the false blank outputs),也经常应用于预处理步骤。
过去的语音识别系统是用音位(phonemes)来构建的,音位是人工设计的基本音节单元。
不过在end-to-end模型中,不需要音位这种人工设计的表示方法,可以构建系统,向系统输入音频片段,直接输出文本。end-to-end模型需要一个很大的数据集,所以语音识别的数据集可能长达300个小时,在学术界,甚至3000小时的文本音频数据集,都被认为是合理的大小。
构建语音识别系统的两种方法:方法1:注意力机制+编码解码架构。方法2:CTC损失函数(CTC cost)。这两种方法构建的语音识别系统的效果都不错。
CTC:Connectionist Temporal Classification 联结主义时间分类,来自论文 Connectionist temporal classification: labelling unsegmented sequence data with recurrent neural networks 。
算法思想:
使用输入长度和输出长度一致的RNN(可以是双向LSTM、双向GRU等),输入音频(举例:10秒的音频,并且特征(features)是100赫兹的,即每秒有100个样本,10×100=1000,所以有1000个输入),输出文本(举例:ttt_h_eee_ _ _□_ _ _qqq_ _
= the q,□表示空格space,_表示空白符blank。CTC损失函数的一个基本规则是将空白符blank之间的重复的字符折叠起来。)。
因为输出里有很多空白符blank,使得输出长度和输入长度一致。处理输出的文本后得到最终需要的文本,处理步骤是:折叠空白符blank之间的重复的字符,然后去除空白符blank。
- 触发字检测(Trigger Word Detection)
触发字系统的例子包括Amazon echo,它通过单词Alexa唤醒;还有百度DuerOS设备,通过"小度你好"来唤醒。假如你在卧室中,有一台Amazon echo,你可以在卧室中简单说一句: Alexa, 现在几点了?就能唤醒这个设备。它将会被单词"Alexa"唤醒,并回答你的询问。
使用一个RNN网络,输入是音频的声谱图特征(音频片段(an audio clip),计算出它的声谱图特征(spectrogram features)(声谱图: 横轴是时间,纵轴是声音的频率),得到特征向量 x < 1 > x^{<1>} x<1>、 x < 2 > x^{<2>} x<2>、 x < 3 > x^{<3>} x<3>…),输出是0/1。
在触发词后输出一个1,其他地方都输出0,这种输出的缺点是,它构建了一个很不平衡的训练集,0的数量比1多太多了。
所以,在触发词后输出多个1,其他地方都输出0。
- 结论和致谢(Conclusion and thank you)
Specialization outline
1、Neural Networks and Deep Learning.
2、Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization.
3、Structuring Machine Learning Projects.
4、Convolutional Neural Networks.
5、Sequence Models.
专业化大纲
1、 神经网络与深度学习。
2、 改进深度神经网络:超参数调整、正则化和优化。
3、 构建机器学习项目。
4、 卷积神经网络。
5、 序列模型。
- Transformer网络直觉(Transformer Network Intuition)
提出Transformer的论文:Attention is all you need 。
RNN中的梯度消失问题,会导致RNN会不擅长处理长期依赖(长期依赖:最前面的单词对句子很后面的单词有影响),GRU和LSTM解决了梯度消失问题。
RNN——》GRU——》LSTM,模型越来越复杂,计算量也越来越大。这些都是序列模型,要计算最终单元的输出,必须先计算之前出现的所有单元的输出。
Transformer 架构,可以并行计算整个序列。能同时处理一个完整的句子,而不是从左到右逐词处理。
上图右下角,CNN可以接收很多像素/单词,能够并行计算它们的特征。
Transformer 架构的主要创新在于:结合使用 基于注意力的特征 和 CNN 卷积神经网络处理方式。
自注意力机制(Self-Attention):如果你有5个单词的句子,最终将计算出这5个单词的词特征(1个单词对应1个词特征),将写成 A < 1 > 、 A < 2 > 、 A < 3 > 、 A < 4 > 、 A < 5 > A^{<1>}、A^{<2>}、A^{<3>}、A^{<4>}、A^{<5>} A<1>、A<2>、A<3>、A<4>、A<5>。这将是一种基于注意力的并行计算句子中所有词特征的方式。
多头注意力机制(Multi-Head Attention):基本上是自注意力机制的for循环,即多次计算自注意力。所以你最终得到多个版本的词向量。事实证明,这些词向量,是非常丰富的词向量,可用于机器翻译或其他NLP任务,以提高效率。
representation=词特征=词向量。课程中,同一个英文单词的不同中文翻译。
- 自注意力机制(Self-Attention)
要使用更像 CNN 风格的注意力,您需要计算自注意力,即为输入句子中的每个单词创建基于注意力的特征。
RNN Attention(RNN注意力模型) 公式: a < t , t ′ > = e x p ( e < t , t ′ > ) ∑ t ′ = 1 T x e x p ( e < t , t ′ > ) a^{<t, t'>} = \frac{ exp(e^{<t, t'>}) }{ \sum_{t'=1}^{T_{x}} exp(e^{<t, t'>}) } a<t,t′>=∑t′=1Txexp(e<t,t′>)exp(e<t,t′>)
Transformers Attention(Transformer自注意力模型) 公式: A ( q , K , V ) = ∑ i e x p ( q ⋅ k < i > ) ∑ j e x p ( q ⋅ k < j > ) v < i > A(q, K, V) = \sum_{i} \frac{ exp(q·k^{<i>}) }{ \sum_{j} exp(q·k^{<j>}) } v^{<i>} A(q,K,V)=∑i∑jexp(q⋅k<j>)exp(q⋅k<i>)v<i>
RNN注意力模型公式和Transformer自注意力模型公式,都使用了softmax。
A(q, K, V) = attention-based vector representation of a word = 基于注意力的单词向量表示,可以理解为单词的注意力值。
为每个单词计算A(q, K, V)。例句有5个单词,计算出这5个单词的词特征(1个单词对应1个词特征),将写成 A < 1 > 、 A < 2 > 、 A < 3 > 、 A < 4 > 、 A < 5 > A^{<1>}、A^{<2>}、A^{<3>}、A^{<4>}、A^{<5>} A<1>、A<2>、A<3>、A<4>、A<5>。
使用词嵌入时,表示一个单词Africa的方式,是从特征矩阵中取出该单词对应的嵌入向量。
Africa可以看成历史名胜、度假胜地、世界第二大洲,根据你对Africa的看法,你可能选择不同的表达方式,这正是 A < 3 > A^{<3>} A<3>特征的作用,它将查看周围单词,试图找出我们在这句话中谈论Africa的实际情况,并为此找到最合适的词特征。
就实际计算而言,它与 在RNN上下文中应用的注意力机制 没有太大区别,除了对句中所有单词 并行计算词特征。
A(q, K, V) 。query(q), key(k), value(v)。举例: A < 3 > A^{<3>} A<3>是由 q < 3 > 、 k < 3 > 、 v < 3 > q^{<3>}、k^{<3>}、v^{<3>} q<3>、k<3>、v<3>这3个向量计算得到的。
x < 3 > x^{<3>} x<3>是单词Africa的词嵌入, q < 3 > = W Q ⋅ x < 3 > q^{<3>} = W^{Q} · x^{<3>} q<3>=WQ⋅x<3>, k < 3 > = W K ⋅ x < 3 > k^{<3>} = W^{K} · x^{<3>} k<3>=WK⋅x<3>, v < 3 > = W V ⋅ x < 3 > v^{<3>} = W^{V} · x^{<3>} v<3>=WV⋅x<3>。
这些矩阵 W Q 、 W K 、 W V W^{Q}、W^{K} 、 W^{V} WQ、WK、WV 是此学习算法的参数,它们允许你为每个单词提取这些query、key、value 的向量。
上图,左下角图展示了使用右上角公式 A ( q , K , V ) = ∑ i e x p ( q ⋅ k < i > ) ∑ j e x p ( q ⋅ k < j > ) v < i > A(q, K, V) = \sum_{i} \frac{ exp(q·k^{<i>}) }{ \sum_{j} exp(q·k^{<j>}) } v^{<i>} A(q,K,V)=∑i∑jexp(q⋅k<j>)exp(q⋅k<i>)v<i> 来计算 A < 3 > = A ( q < 3 > , K , V ) A^{<3>} = A(q^{<3>}, K, V) A<3>=A(q<3>,K,V)的计算过程。
query、key、value存在类似数据库的关系。举例: q < 3 > q^{<3>} q<3>是一个关于Africa的问题,“Africa发生了什么?” 然后计算 q < 3 > ⋅ k < 1 > q^{<3>}·k^{<1>} q<3>⋅k<1>、 q < 3 > ⋅ k < 2 > q^{<3>}·k^{<2>} q<3>⋅k<2>、。。。、 q < 3 > ⋅ k < 5 > q^{<3>}·k^{<5>} q<3>⋅k<5>。 q < 3 > ⋅ k < 1 > q^{<3>}·k^{<1>} q<3>⋅k<1>表明对于问题 q < 3 > q^{<3>} q<3>来说,Jane这个单词作为答案有多好; q < 3 > ⋅ k < 2 > q^{<3>}·k^{<2>} q<3>⋅k<2>表明对于问题 q < 3 > q^{<3>} q<3>来说,visit这个单词作为答案有多好。其中 k < 1 > k^{<1>} k<1>是个人名, k < 2 > k^{<2>} k<2>是个动作,那么你可能会发现5个计算结果中 q < 3 > ⋅ k < 2 > q^{<3>}·k^{<2>} q<3>⋅k<2>最大,这可能表明 visit 是问题 q < 3 > q^{<3>} q<3>“Africa发生了什么?” 最相关的上下文。也就是说,Africa被视为访问(visit)的目的地。
然后,取这5个值 q < 3 > ⋅ k < i > q^{<3>}·k^{<i>} q<3>⋅k<i> 并计算它们的 Softmax(结果是,第i个单词与问题 q < 3 > q^{<3>} q<3>的相关性,简单理解为第 i 个单词与第3个单词的相关性),把这些 Softmax 值与 v < i > v^{<i>} v<i> 相乘,最后将所有这些值相加,得到 A < 3 > A^{<3>} A<3>。
单词Africa的固定词嵌入是 x < 3 > x^{<3>} x<3>。在句子中,单词Africa不是固定的词嵌入,Self-Attention自注意力 学习到,Africa是访问(visit)的目的地,从而为单词Africa计算出更针对这句话的词特征。
A < 3 > = A ( q < 3 > , K , V ) A^{<3>} = A(q^{<3>}, K, V) A<3>=A(q<3>,K,V),前者是后者的简写。
前面讲了用公式 A ( q , K , V ) = ∑ i e x p ( q ⋅ k < i > ) ∑ j e x p ( q ⋅ k < j > ) v < i > A(q, K, V) = \sum_{i} \frac{ exp(q·k^{<i>}) }{ \sum_{j} exp(q·k^{<j>}) } v^{<i>} A(q,K,V)=∑i∑jexp(q⋅k<j>)exp(q⋅k<i>)v<i> 来计算 A < 3 > = A ( q < 3 > , K , V ) A^{<3>} = A(q^{<3>}, K, V) A<3>=A(q<3>,K,V)的计算过程。用该公式计算句中所有单词的词特征,记作 A t t e n t i o n ( Q , K , V ) Attention(Q, K, V) Attention(Q,K,V)。其中Q指 q < 1 > 、。。。、 q < n > q^{<1>}、。。。、q^{<n>} q<1>、。。。、q<n>,K指 k < 1 > 、。。。、 k < n > k^{<1>}、。。。、k^{<n>} k<1>、。。。、k<n>,V指 v < 1 > 、。。。、 v < n > v^{<1>}、。。。、v^{<n>} v<1>、。。。、v<n>。
使用Self-Attention计算句中所有n个单词的词特征 (1个单词对应1个词特征) A < 1 > 、 A < 2 > 、。。。、 A < n > A^{<1>}、A^{<2>}、。。。、A^{<n>} A<1>、A<2>、。。。、A<n>,文献中用该公式表示: A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q, K, V) = softmax( \frac{ QK^{T} }{ \sqrt{d_{k}} } )V Attention(Q,K,V)=softmax(dkQKT)V。 s o f t m a x ( Q K T d k ) V softmax( \frac{ QK^{T} }{ \sqrt{d_{k}} } )V softmax(dkQKT)V只是 ∑ i e x p ( q ⋅ k < i > ) ∑ j e x p ( q ⋅ k < j > ) v < i > \sum_{i} \frac{ exp(q·k^{<i>}) }{ \sum_{j} exp(q·k^{<j>}) } v^{<i>} ∑i∑jexp(q⋅k<j>)exp(q⋅k<i>)v<i> 的压缩或矢量化的版本; d k \sqrt{d_{k}} dk只是为了减少点积值,以避免梯度爆炸。
Self-Attention = scaled dot-product attention,自注意力 = 缩放点积注意力。scaled dot-product attention是 论文Attention is all you need中,给Self-Attention起的另一个名字。
总结:
句中每个单词,都会得到自己的query、key、value。query提出有关该单词的问题;如"Africa发生了什么?"。key查看其他所有词,并根据与query 的相似性,找出哪些单词给出与该问题最相关的答案;如visit是"Africa发生了什么?"的最佳答案,有人访问非洲 visit Africa。value允许词特征插入: A < 3 > A^{<3>} A<3>(Africa的词特征)中应如何表示visit;即在 A < 3 > A^{<3>} A<3>(Africa的词特征)中插入visit应如何表示的信息。使得单词Africa提取出这样的词特征:有人访问非洲 visit Africa。
固定词嵌入无法根据单词前后内容来调整单词含义,自注意力不是为每个单词提取固定不变的词嵌入,而是为每个单词提取更针对这句话的词嵌入。
我的理解:自注意力可以根据句子整体含义,来得到句中所有词的具体含义(句中某词是一词多义,也能得到该词最符合该句子的含义),从而对句子进行更好的翻译。
- 多头注意力机制(Multi-Head Attention)
每次计算序列的自注意力时称之为 ‘头’(head)。多头注意力是自注意力机制的for循环,即多次计算自注意力。
h = number of head = 头的数量。
和自注意力一样, x < 3 > x^{<3>} x<3>是单词Africa的词嵌入, q < 3 > = W Q ⋅ x < 3 > q^{<3>} = W^{Q} · x^{<3>} q<3>=WQ⋅x<3>, k < 3 > = W K ⋅ x < 3 > k^{<3>} = W^{K} · x^{<3>} k<3>=WK⋅x<3>, v < 3 > = W V ⋅ x < 3 > v^{<3>} = W^{V} · x^{<3>} v<3>=WV⋅x<3>。
将 W i Q W_{i}^{Q} WiQ、 W i K W_{i}^{K} WiK、 W i V W_{i}^{V} WiV视为被习得的参数,用来帮助提问和回答问题"xxx?"。
W 1 Q W_{1}^{Q} W1Q、 W 1 K W_{1}^{K} W1K、 W 1 V W_{1}^{V} W1V是一组矩阵,用于计算第1个头; W 2 Q W_{2}^{Q} W2Q、 W 2 K W_{2}^{K} W2K、 W 2 V W_{2}^{V} W2V是一组新的矩阵,用于计算第2个头;。。。; W h Q W_{h}^{Q} WhQ、 W h K W_{h}^{K} WhK、 W h V W_{h}^{V} WhV是一组新的矩阵,用于计算第h个头,这h组矩阵互不相等。
W 1 Q W_{1}^{Q} W1Q、 W 1 K W_{1}^{K} W1K、 W 1 V W_{1}^{V} W1V,用来帮助提问和回答第1个问题,也许第1个问题是 “what’s happening 发生了什么?”。图中最长的蓝箭头:计算第1个头的[Africa]的词特征时,最大的内积是[visit]的key与[Africa]的query产生的,[visit]的value对第1个头的[Africa]的词特征起到重要作用。
该例子中,计算多头注意力中的第1个头,需要习得参数 W 1 Q W_{1}^{Q} W1Q、 W 1 K W_{1}^{K} W1K、 W 1 V W_{1}^{V} W1V (这些参数表示1个问题,也许这个问题是 “what’s happening 发生了什么?”)。在习得参数 W 1 Q W_{1}^{Q} W1Q、 W 1 K W_{1}^{K} W1K、 W 1 V W_{1}^{V} W1V 的前提下(在问题"what’s happening 发生了什么?" 的前提下),计算所有单词(Jane、visit、Africa、in、september)的词特征。最终用5个向量表示序列中5个单词。
W 2 Q W_{2}^{Q} W2Q、 W 2 K W_{2}^{K} W2K、 W 2 V W_{2}^{V} W2V,用来帮助提问和回答第2个问题,也许第2个问题是"when 什么时候发生?"。图中最长的红箭头:计算第2个头的[Africa]的词特征时,最大的内积是[september]的key和[Africa]的query产生的,[september]的value对第2个头的[Africa]的词特征起到重要作用。
W 3 Q W_{3}^{Q} W3Q、 W 3 K W_{3}^{K} W3K、 W 3 V W_{3}^{V} W3V,用来帮助提问和回答第3个问题,也许第3个问题是 “who 谁?”。图中最长的黑箭头:计算第3个头的[Africa]的词特征时,最大的内积是[Jane]的key和[Africa]的query产生的,[Jane]的value对第3个头的[Africa]的词特征起到重要作用。
M u l t i H e a d ( Q , K , V ) = c o n c a t ( h e a d 1 , h e a d 2 , . . . , h e a d h ) W 0 MultiHead(Q, K, V) = concat(head_{1}, head_{2},..., head_{h})W_{0} MultiHead(Q,K,V)=concat(head1,head2,...,headh)W0 。最终结果,是串联concatenation这h个头得到的h个值,再乘以 W 0 W_{0} W0。
头与头之间不相互依赖,所以可以并行计算所有头,不需要顺序计算。
在有n个单词的序列(句子)上应用 多头注意力机制,我的总结:
for h次 (h是多头注意力机制中,number of head 头的数量),用 i 表示当前次数。for n次 (n是句子中的单词数量),用 j 表示当前次数。习得参数$W_{i}^{Q}$、$W_{i}^{K}$、$W_{i}^{V}$,获得在角度 i 时(角度比如what、when、who),句中第 j 个单词的词特征。记为向量。
假如列向量符号是|。计算第1个头时,得到5个列向量(因为句中有5个单词);计算第2个头时,得到5个列向量;计算第3个头时,得到5个列向量。串联得到3行5列的矩阵,如下。矩阵第 i 行 j 列的列向量,表示第 i 个头第 j 个单词得到的词特征,是个列向量。该矩阵第1列(3个列向量串联)表示句中第1个单词的词特征,第 j 列(3个列向量串联)表示句中第j个单词的词特征。
| | | | |
| | | | |
| | | | |
上图,右边那个小图(Multi-Head Attention外面套3个框),作为简化的图标,用于表示左边整个图(输入Q、K、V,输出 M u l t i H e a d ( Q , K , V ) MultiHead(Q, K, V) MultiHead(Q,K,V))。
多头注意力:对每个单词提出多个问题,从而为每个单词学习更丰富、更好的词特征。
- Transformer网络(Transformer Network)
<SOS>
是句子开头标记,<EOS>
是句子结尾标记。
上图,执行seq2seq(序列到序列)的翻译任务。
左侧Encoder,右侧Decoder,Encoder和Decoder都运行N次,一般N=6,过程是Encoder先自己运行N次,然后Decoder自己运行N次。Decoder每次运行,都会把Decoder输出的翻译完成的译文,传给Decoder输入。
Decoder里的第2个多头注意力,输入的Q(query)来自已经翻译完成的译文序列,输入的K(key)、V(value)来自经过Encoder的原文。
Feed Forward Neural Network:前馈神经网络,也叫作多层感知机(Multilayer Perceptron,MLP),就是普通的全连接神经网络(Full Connect Neural Network),可以反向传播。
Transformer 细节:
细节1、positional encoding of the input 输入的位置编码。
自注意力机制的方程中,没有东西可以表示一个词的位置(单词在句子开头、中间、末尾)。
T x T_{x} Tx:序列长度,句子长度。
x < 1 > 、 x < 2 > 、。。。、 x < T x > x^{<1>}、x^{<2>}、。。。、x^{<T_{x}>} x<1>、x<2>、。。。、x<Tx>:序列中第1个词到第 T x T_{x} Tx个词的,词嵌入的嵌入向量。
p < 1 > 、 p < 2 > 、。。。、 p < T x > p^{<1>}、p^{<2>}、。。。、p^{<T_{x}>} p<1>、p<2>、。。。、p<Tx>:序列中第1个词到第 T x T_{x} Tx个词的,位置编码。
位置编码是向量,由 P E ( p o s , 2 i ) PE_{(pos, 2i)} PE(pos,2i)、 P E ( p o s , 2 i + 1 ) PE_{(pos, 2i+1)} PE(pos,2i+1) 的公式计算得到。
p < 1 > 、 p < 2 > 、。。。、 p < T x > p^{<1>}、p^{<2>}、。。。、p^{<T_{x}>} p<1>、p<2>、。。。、p<Tx> 这些位置编码间互不相等,就是位置编码(向量)间,不会所有维度的数字都相等。
举例:位置编码 p < 1 > p^{<1>} p<1>,编码了句中第1个单词Jane的位置。
举例:位置编码 p < 1 > p^{<1>} p<1>的维度是4,那么需要计算 P E ( 1 , 0 ) 、 P E ( 1 , 1 ) 、 P E ( 1 , 2 ) 、 P E ( 1 , 3 ) PE_{(1, 0)}、PE_{(1, 1)}、PE_{(1, 2)}、PE_{(1, 3)} PE(1,0)、PE(1,1)、PE(1,2)、PE(1,3),来得到4维向量的4个数字。 P E ( 1 , 0 ) PE_{(1, 0)} PE(1,0),前一个数字1是 单词在句中的位置,后一个数字0是 当前计算4维向量的第0维数字。
Positional Encoding 位置编码:
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 ( 2 i d ) ) PE_{(pos, 2i)} = sin( \frac{ pos }{ 10000^{ (\frac{2i}{d}) } } ) PE(pos,2i)=sin(10000(d2i)pos)
P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 ( 2 i d ) ) PE_{(pos, 2i+1)} = cos( \frac{ pos }{ 10000^{ (\frac{2i}{d}) } } ) PE(pos,2i+1)=cos(10000(d2i)pos)
上方公式的变量:
pos:position,单词在句子中的位置,从1开始。比如Jane的pos=1。
d:词嵌入的嵌入向量的维度。比如d=4。
i:位置编码(向量)的不同维度,从0开始。比如位置编码 p < 1 > p^{<1>} p<1>是4维向量,那么 p < 1 > p^{<1>} p<1>有:i=0、i=1、i=2、i=3。
假如词嵌入 x < 1 > x^{<1>} x<1>的维度d=4,那么,创建一个维度相同(维度=4)的位置嵌入向量(位置编码),记为 p < 1 > p^{<1>} p<1>。
此时有,位置编码 p < 1 > p^{<1>} p<1>的维度 = 词嵌入 x < 1 > x^{<1>} x<1>的维度 = 4。把 位置编码 p < 1 > p^{<1>} p<1> 添加到 词嵌入 x < 1 > x^{<1>} x<1> 上(同维度的向量相加,就是2个向量把相同维度的数字相加)。因此,每个词嵌入也受到单词在句中出现的位置的影响。
编码块Encoder的输出包含上下文语义嵌入(contextual semantic embedding)和位置编码信息。
嵌入层的输出是d(在本例中d=4) 乘以 模型可以采用的最大序列长度,所有这些层的输出也是这种情况(图中画深蓝箭头的层,即:Encoder的Multi-Head Attention、Feed Forward Neural Network,Decoder的Masked Multi-Head Attention、Multi-Head Attention、Feed Forward Neural Network)。
除了将这些位置编码添加到词嵌入,你还可以将位置编码通过具有残差连接的网络进行传递,这些残差连接类似残差网络ResNet中的连接。在这种情况下,残差连接的目的是,在整个架构中传递位置信息。
细节2、
Transformer使用了一个名为Add&Norm的层,类似于批量归一化层(batch norm layer)。
批量归一化层(batch norm layer):对数据做归一化处理,目的是为了加快学习速度。浅层模型只需要对输入数据做归一化处理就好;深层模型靠近输出层的输出容易出现剧烈变化,所以会给深层模型中插入批量归一化层,以加快学习速度。
解码器Decoder的输出处,还有一个 线性层Linear layer(线性层Linear Layer 又称 全连接层Full-connected Layer) 和 softmax layer,来预测下一个词,一次一词 。
上图,右侧Decoder的第1个多头注意力机制,其实是掩码多头注意力机制。
masked multi-head attention:掩码多头注意力。它仅在训练过程中很重要,在训练时,网络已知正确的原文和正确的译文,掩码屏蔽句子的后半部分,以模拟网络在测试时(预测时)需要做的事。就是说,掩码多头注意力反复假定网络对句子前面部分已经做出完美翻译,隐藏剩下的译文,看下,网络是否可以准确的预测下一个单词,是否可以翻译好 尚未翻译的部分。
Transformer模型有许多其他的迭代,如:Bert、Bert distill。
BERT:Bidirectional Encoder Representations from Transformers,基于变换器的双向编码器表示技术。是用于自然语言处理(NLP)的预训练技术,由Google在2018年提出。
DistilBERT (Distilled version of BERT) 是一种压缩BERT模型的方法,它可以在保证模型性能不降很多的情况下,大幅度压缩模型大小。