深度学习之Encoder-Decoder架构
一、背景简介
深度学习中Sequence to Sequence (Seq2Seq) 模型的目标是将一个序列转换成另一个序列。包括机器翻译(machine translate)、会话识别(speech recognition)和时间序列预测(time series forcasting)等任务都可以理解成是Seq2Seq任务。RNN(Recurrent Neural Networks)是深度学习中最基本的序列模型。
Seq2Seq最基本的特点是输入数据和输出数据的长度并不是固定的,例如对于翻译来说,中文可能是“很 高兴 见 到 你”,而英文是“Nice to meet you”,这种情况就是输入和输出的长度不一样。同时,换一个例句之后,其输入和输出的长度也会变化。因此,一般的深度学习网络是无法处理这个问题的。
但是,基础RNN模型(以及相关的变种模型如GRU神经网络、LSTM神经网络)虽然可以处理序列数据,然而就精度而言并不是很好(论文的对比试验结论)。为此,在2014年有很多研究者在几乎同一时间都提出了Encoder-Decoder的深度学习架构来处理Seq2Seq的问题。
Sutskever et al., Sequence to Sequence Learning with Neural Networks. NIPS. 2014
Cho et al., On the Properties of Neural Machine Translation: Encoder–Decoder Approaches. arXiv. 2014
Bahdanau et al., Neural machine translation by jointly learning to align and translate. arXiv. 2014
Encoder-Decoder网络架构的一般思想是整个网络结构中使用两个网络来处理Seq2Seq任务。第一个网络将输入的Seq转换成一个固定长度的内部表示向量,第二个网络则是将该向量作为输入,用以预测输出的序列。两个网络之间的连接就是中间的一个向量。
二、问题描述
在这里,我们以Cho的论文(Sequence to Sequence Learning with Neural Networks)为例,描述一下问题。
假设我们有个原始序列:
\{x_1,\cdots,x_T\}
目标是转换成对应的序列:
\{y_1,\cdots,y_{T'}\}
注意,这里的两个序列并不一定是等长的。那么,一般我们可以构造如下形式的RNN Encoder-Decoder模型:

我们第一步先构造一个RNN,将原始序列作为输入,产生一个向量C。也就是说,我们第一步是要把原始序列转换成一个固定长度的向量,这里可以理解为一个特征抽取过程,即将原始不定长序列转换成一组固定长度的特征向量。其实,这里的结构可以是基本的RNN模型、GRU网络或者是LSTM,或者是Bi-RNN、Bi-LSTM(双向)。这个阶段就是Encoding阶段。
下一个阶段就是Decoding阶段,其目标是将特征向量C转换成目标序列\{y_1,\cdots,y_{T` }\}。这两个阶段的目标是最大化如下的条件概率:
\max_{\theta} \frac{1}{N} \sum_{n=1}^N\log p_\theta(\bold{y}_n|\bold{x}_n)
这里的\theta就是模型的参数集合,每一个(\bold{x}_n,\bold{y}_n)对都是一个训练集。模型的求解可以使用梯度下降。
三、Encoder-Decoder代码示例
假设我们要构造的Enocder-Decoder模型结构如下:

那么上述模型的代码结构如下:
vocab_size = ...
src_txt_length = ...
sum_txt_length = ...
# encoder input model
inputs = Input(shape=(src_txt_length,))
encoder1 = Embedding(vocab_size, 128)(inputs)
encoder2 = LSTM(128)(encoder1)
encoder3 = RepeatVector(sum_txt_length)(encoder2)
# decoder output model
decoder1 = LSTM(128, return_sequences=True)(encoder3)
outputs = TimeDistributed(Dense(vocab_size, activation='softmax'))(decoder1)
# tie it together
model = Model(inputs=inputs, outputs=outputs)
model.compile(loss='categorical_crossentropy', optimizer='adam')
欢迎大家关注DataLearner官方微信,接受最新的AI技术推送
