1.经典RNN
2.结构
在Seq2Seq结构中,编码器Encoder把所有的输入序列都编码成一个统一的语义向量Context,然后再由解码器Decoder解码。在解码器Decoder解码的过程中,不断地将前一个时刻
t
?
1
t-1
t?1 的输出作为后一个时刻
t
t
t 的输入,循环解码,直到输出停止符为止。
与经典RNN结构不同的是,Seq2Seq结构不再要求输入和输出序列有相同的时间长度!
机器翻译Decoder端
t
t
t 时刻数据流:
- 首先对 RNN 输入大小为
[
n
i
,
1
]
[n_i,1]
[ni?,1] 的向量
x
t
x_t
xt?(红点);
- 然后经过 RNN 输出大小为
[
n
o
,
1
]
[n_o,1]
[no?,1] 的向量
y
t
y_t
yt?(蓝点);
- 接着使用全连接 fc 将
y
t
y_t
yt? 变为大小为
[
n
c
,
1
]
[n_c,1]
[nc?,1] 的向量
y
t
′
y^{\prime}_t
yt′? ,其中
n
c
n_c
nc? 代表类别数量;
- 再
y
t
′
y^{\prime}_t
yt′? 经过 softmax 和 argmax 获取类别 index,再经过 int2str 获取输出字符;
- 最后将类别 index 输入到下一状态,直到接收到
标志符停止。
为解决one-hot编码进行嵌入过于稀疏,使用一种更加优雅的办法:使用embedding随机矩阵。
3.Seq2Seq训练问题
为防止某一时刻输出
y
t
y_t
yt? 错误就会导致后面全错,Google提出了大名鼎鼎的Scheduled Sampling(即在训练中
x
t
x_t
xt? 按照一定概率选择输入
y
t
?
1
y_{t-1}
yt?1? 或
t
?
1
t-1
t?1 时刻对应的真实值,即标签),既能加快训练速度,也能提高训练精度。
设置一个概率p,每一步,以概率 p 靠自己上一步的输入来预测,以概率 1-p 根据老师的提示来预测,这种方法称为「计划采样」(scheduled sampling)。
4.seq2seq+Attention
在 Decoder 解码的过程中向量 c 都是不变的。这存在着不少缺陷:
- 对于比较长的句子,很难用一个定长的向量 c 完全表示其意义。
- RNN 存在长序列梯度消失的问题,只使用最后一个神经元得到的向量 c 效果不理想。
- 与人类的注意力方式不同,即人类在阅读文章的时候,会把注意力放在当前的句子上。
所以如果要改进Seq2Seq结构,最好的切入角度就是:利用Encoder所有隐藏层状态
h
t
h_t
ht? 解决Context长度限制问题。
attention model用来帮助解决机器翻译在句子过长时效果不佳的问题。(LSTM和RNN都难以解决)
基本思路: Context vector c_{i}是透过 attention score
α
α
α 乘上 input 的序列加权求和。Attention/Alignment score是attention model中提出一个很重要的概念,可以用来衡量输入句中的每个文字对目标句中的每个文字所带来重要性的程度。
在计算score中,
α
α
α 代表
A
l
i
g
n
m
e
n
t
m
o
d
e
l
Alignment model
Alignmentmodel 会根据输入字位置
j
j
j 和输出字位置
i
i
i 这两者的关联程度,计算出一个score
e
i
j
e_{ij}
eij?。换言之,
e
i
,
j
e_{i,j}
ei,j?是衡量RNN decoder中的
h
i
d
d
e
n
s
t
a
t
e
s
i
?
1
hidden state s_{i-1}
hiddenstatesi?1? 和输入句中的第
j
j
j 个文字hidden state
h
j
h_{j}
hj? 的关系所计算出的权重。 注意力机制具体实现方式:
- 计算Decoder的
t
t
t 时刻隐藏层状态
h
t
h_{t}
ht? 对Encoder每一个隐藏层状态
h
ˉ
s
\bar{h}_{s}
hˉs? 权重
a
t
(
s
)
a_{t}(s)
at?(s) 数值:
这里的
s
c
o
r
e
score
score 可以通过以下三种方式计算: - 利用权重
a
t
(
s
)
a_{t}(s)
at?(s) 计算所有隐藏层状态
h
ˉ
s
\bar{h}_{s}
hˉs? 加权之和
c
t
c_{t}
ct? ,即生成新的大小为
[
n
h
,
1
]
[n_h,1]
[nh?,1] 的Context状态向量:
- 将通过权重
a
t
(
s
)
a_{t}(s)
at?(s) 生成的
c
t
c_{t}
ct? 与原始Decoder隐藏层
t
t
t 时刻状态
h
t
h_{t}
ht? 拼接在一起:
这里
c
t
c_{t}
ct? 和
h
t
h_{t}
ht? 大小都是
[
n
h
,
1
]
[n_h,1]
[nh?,1] ,拼接后会变大。由于需要恢复为原来形状,所以乘以全连接
W
c
W_{c}
Wc? 矩阵。当然不恢复也可以,但是会造成Decoder RNN cell变大。 - 对加入“注意力”的Decoder状态
h
ˉ
t
\bar{h}_{t}
hˉt? 乘以
W
h
o
W_{ho}
Who? 矩阵即可获得输出:
其中
W
a
W_{a}
Wa? 和
W
c
W_{c}
Wc? 参数需要通过学习获得。整个Attention机制通过通过 score 函数计算的注意力向量
c
t
c_{t}
ct? ,给Decoder RNN加入额外信息,提高性能。
Attention model虽然解决了输入句仅有一个context vector的缺点,但依旧存在不少问题。 Attention未解决的问题:
- context vector计算的是输入句、目标句间的关联,却忽略了输入句中文字间的关联,和目标句中文字间的关联性。
- 不管是Seq2seq或是Attention model,其中使用的都是RNN,RNN的缺点就是无法平行化处理,导致模型训练的时间很长,有些论文尝试用CNN去解决这样的问题,像是Facebook提出的Convolutional Seq2seq learning,但CNN实际上是透过大量的layer去解决局部信息的问题,在2017年,Google提出了一种叫做”The transformer”的模型,透过self attention、multi-head的概念去解决上述缺点,完全舍弃了RNN、CNN的构架。
自注意力:self-attention会丧失序列数据的位置信息,因此在使用self-attention的Transformer会在将位置信息通过位置编码(Positional Encoding)的形式融合进输入数据之中
5.Seq2Seq的预处理
- 首先我们假设有10000个问答对,统计得到1000个互异的字以及每个字对于出现的次数。
- 根据统计得到的这1000个字,按照次数从多到少进行排序,序号从0开始到999结束(得到我们的字典表ids)。
- 对于问答对,进行One-Hot编码。
- 由于One-Hot编码的维度较大且0较多,因此我们进行embedding降维(具体维数自定义)得到我们的特征矩阵。
6.应用领域
- 机器翻译。Encoder-Decoder的最经典应用,事实上这一结构就是在机器翻译领域最先提出的
- 文本摘要。输入是一段文本序列,输出是这段文本序列的摘要序列。
- 阅读理解。将输入的文章和问题分别编码,再对其进行解码得到问题的答案。
- 语音识别。输入是语音信号序列,输出是文字序列。
7.seq2seq+CNN
基本思想: CNN可以并行,改善了lstm的性能瓶颈。 用CNN分别抽取原句和目标句的句向量表达,在decode的输出中利用attention机制考虑和原句的对应关系,利用attention score来动态改变输入句子的向量表达,对decode词汇相关性大的占用大的权重,最后decode的输出是综合attention后的原句的向量加上CNN抽取的decode的向量。
模型结构的具体说明如下: 上左encoder部分:通过一层卷积抽取原句子的特征,之后经过GLU激活做为encoder输出。 下左decoder部分:采用层叠卷积抽取输出目标语言的特征,经过GLU激活做为decoder输出。 中左attention部分:把decoder和encoder的输出做点乘,做为输入源语言中每个词权重。 中右Residual connection:把attention计算的权重与输入序列相乘,加入到decoder的输出中输出输出序列。
8.seq2seq+transformer
transformer是充分利用了attention,达到并行的目的。前后词的向量表达不再用lstm,rnn,gru等来依次输出。在encoder端采用的self attention机制,对每个词和其它词进行attention操作,每个词的向量表达能包含了其它词,相关性大的信息量大,相关性小的信息量小。
- 编码器:编码器为相同的6个encoder堆叠得到,每个encoder参数不同;每个encoder两个子层,分别为多头的自注意力和前馈神经网络(每个位置的单词对应的前馈神经网络都完全一样,另一种解读就是一层窗口为一个单词的一维卷积神经网络),这里采用了ResNet的思想建立了一个short-cut。Encoder的输入,最底层为句子的embedding,之后每层的输入为上一层的输出。
- 解码器:解码器同样为6个相同的decoder进行堆叠得到。和encoder不同的是,这里有两个多头注意力。masked multi-head self-attention是为了保证输出只能看到当前时刻之前的输出结果。另一个multi-head attention也叫encoder-decoder attention,是用decode当前时刻的输出作为Q,encoder的输入作为K和V,这样每次decoder的输出都携带了各个位置的输入信息,类似于传统的seq2seq的attetnion机制。每个解码器和编码器一样也都有一个前馈神经网络和layer norm;最后解码器通过softmax转换为概率分布,决定输出哪个单词。
在transformer之前,seq2seq后续的改进基本上是三个方向:
- 魔改encoder和decoder的结构,例如encoder部分使用LSTM,双向LSTM,CNN等;
- 在encoder或者decoder中加入各种网络组件帮助训练,例如resnet+deep lstm作为encoder来保证深层的lstm拥有更强大的抽象能力的同时,训练的效率也得到提升;
- encoder和decoder部分的不同设计策略
decoder的设计模式
greedy search
greed search的思路很贪心,解码的过程中,选择一个 softmax 预测的概率输出最高的词作为当前的翻译结果,然后再将这个词作为下一个目标词的输入和上一个词的 LSTM 对应的 step 阶段的 hidden state 一起预测下一个目标词,贪心搜索的缺点比较明显,就是误差累积的问题,这个和基于 seq2seq的时间序列预测任务存在的问题也是一样,一旦某一步 decode 的预测出错,则后面所有的decode的预测都是在上一步误差的基础上进行累计,从而使得整体的误差很高。
beam search
取top-k个预测概率最高的目标词同时进入下一个的decode,然后在最终的输出中才进行最终的top-1的选择。而与时间序列相关的seq2seq结构无法使用beam search,因为回归型的seq2seq的输出没有概率分布的概念而是输出一个单值,针对于这个问题实际上时间序列预测 seq2seq 舍弃了beam search的思路,使用了teacher forcing的扩展方法——curriculum learning,对应的采样方法叫做「计划采样」scheduled sampling。
公式流程
https://zhuanlan.zhihu.com/p/115210317
输入:
x
=
(
x
1
,
.
.
.
,
x
T
x
)
x= (x_1,...,x_{T_x})
x=(x1?,...,xTx??) 输出:
y
=
(
y
1
,
.
.
.
,
y
T
y
)
y= (y_1,...,y_{T_y})
y=(y1?,...,yTy??)
- Encoder方面接受的是每一个单词word embedding,和上一个时间点的hidden state。输出的是这个时间点的hidden state。
- Decoder方面接受的是目标句子里单词的word embedding,和上一个时间点的hidden state。
- context vector是一个对于encoder输出的hidden states的一个加权平均。
- 每一个encoder的hidden states对应的权重。
- 通过decoder的hidden states加上encoder的hidden states来计算一个分数,用于计算权重(4)
- 将context vector 和 decoder的hidden states 串起来。
- 计算最后的输出概率。
详细图:
代码解读
|