Encoder-Decoder综述理解(推荐)
⽂章⽬录
⼀、Encoder-Decoder(编码-解码)
介绍
Encoder-Decoder是⼀个模型构架,是⼀类算法统称,并不是特指某⼀个具体的算法,在这个框架下可以使⽤不同的算法来解决不同的任务。⾸先,编码(encode)由⼀个编码器将输⼊序列转化成⼀个固定维度的稠密向量,解码(decode)阶段将这个激活状态⽣成⽬标译⽂。
回顾⼀下,算法设计的基本思路:将现实问题转化为⼀类可优化或者可求解的数学问题,利⽤相应的算法来实现这⼀数学问题的求解,然后再应⽤到现实问题中,从⽽解决了现实问题。(⽐如,我们想解决⼀个词性标注的任务(现实问题),我们转化成⼀个BIO序列标注问题(数学模型),然后设计⼀系列的算法进⾏求解,如果解决了这个数学模型,从⽽也就解决了词性标注的任务)。
Encoder :编码器,如下。
Decoder:解码器,如下。
合并起来,如下:
更具体⼀点的表达如下所⽰:
⼏点说明
不论输⼊和输出的长度是什么,中间的“向量c”长度都是固定的(这是它的缺陷所在)。
根据不同的任务可以选择不同的编码器和解码器(例如,CNN、RNN、LSTM、GRU等)
Encoder-Decoder的⼀个显著特征就是:它是⼀个end-to-end的学习算法。
只要符合这种框架结构的模型都可以统称为Encoder-Decoder模型。
信息丢失的问题
通过上⽂可以知道编码器和解码器之间有⼀个共享的向量(上图中的向量c),来传递信息,⽽且它的长度是固定的。这会产⽣⼀个信息丢失的问题,也就是说,编码器要将整个序列的信息压缩进⼀个固定长度的向量中去。但是这样做有两个弊端,⼀是语义向量⽆法完全表⽰整个序列的信息,还有就是先输⼊的内容携带的信息会被后输⼊的信息稀释掉,或者说,被覆盖了。输⼊序列越长,这个现象就越严重。这就使得在解码的时候⼀开始就没有获得输⼊序列⾜够的信息,那么解码的准确度⾃然也就要打个折扣了。如果编码过程产⽣的不是⼀个固定长度的向量⽽是⼀系列向量,是不是会保留更多的信息呢。
便于理解,我们把“编码-解码”的过程类⽐为“压缩-解压”的过程:
将⼀张 800X800 像素的图⽚压缩成 100KB,看上去还⽐较清晰。⽽将⼀张 3000X3000 像素的图⽚也压缩到 100KB,看上去就模糊了。
基础的Encoder-Decoder是存在很多弊端的,最⼤的问题就是信息丢失。Encoder将输⼊编码为固定⼤⼩的向量的过程实际上是⼀个“信息有损的压缩过程”,如果信息量越⼤,那么这个转化向量的过程对信息的损失就越⼤,同时,随着序列长度(sequence length)的增加,意味着时间维度上的序列很长,RNN模型就会出现梯度弥散的问题。由于基础的Encoder-Decoder模型链接Encoder和Decoder的组件仅仅是⼀个固定⼤⼩的状态向量,这就使得Decoder⽆法直接⽆关注输⼊信息的更多细节。为了解决这些缺陷,随后⼜引⼊了Attention 机制以及Bi-directional encoder layer等。Attention模型的特点是En
coder不再将整个输⼊序列编码为固定长度的中间向量,⽽是编码成⼀个【向量序列】。这样,在产⽣每⼀个输出的时候,都能够做到充分利⽤输⼊序列携带的信息。⽽且这种⽅法在翻译任务中取得了⾮常不错的成果。如下图所⽰
应⽤
⼀般情况下,输⼊端的形式各种各样(例如图⽚,⽂本、语⾳等),输出端的形式⼀般是⽂本格式,输⼊序列和输出序列的长度可能会有较⼤的差异(例如,⼀对⼀,多对多,多对⼀,⼀对多等)。
Seq2Seq就是该模型框架的⼀个典型代表。
⼆、Seq2Seq(序列到序列)
介绍
所谓的Sequence2Sequence任务主要是泛指⼀些Sequence到Sequence的映射问题,Sequence在这⾥可以理解为⼀个字符串序列,当我们在给定⼀个字符串序列后,希望得到与之对应的另⼀个字符串序列(如 翻译后的、如语义上对应的)时,这个任务就可以称为Sequence2Sequence了。这种结构最重要的地⽅在于输⼊序列和输出序列的长度是可变的。
Seq2Seq与Encoder-Decoder
Seq2Seq可以看作是Encoder-Decoder针对某⼀类任务的模型框架,它们的范围关系如下所⽰:
Encoder-Decoder强调的是模型设计(编码-解码的⼀个过程),Seq2Seq强调的是任务类型(序列到序列的问题)。decoder
三、代码实现
任务描述
给定⼀个输⼊单词(字母序列),例如,python,设计模型,使得输出为:按照字母顺序排序,例如hnopty
数据集
source_data数据集:每⼀⾏是⼀个单词
target_data数据集:每⼀⾏是经过字母排序后的“单词”
source_data和target_data中每⼀⾏是⼀⼀对应的
设计模型
Seq2Seq模型:主要包括Encoder、Decoder以及连接两者的国定⼤⼩的状态向量(State Vector)。
模型的实现过程
数据预处理
在神经⽹络中,对于⽂本的数据预处理⽆⾮是将⽂本转化为模型可理解的数字,这⾥都⽐较熟悉,不作过多解释。但在这⾥我们需要加⼊以下四种字符,<PAD>主要⽤来进⾏字符补全,<EOS>和<GO>都是⽤在Decoder端的序列中,告诉解码器句⼦的起始与结束,<UNK>则⽤来替代⼀些未出现过的词或者低频词。
< PAD>: 补全字符。
< EOS>: 解码器端的句⼦结束标识符。
< UNK>: 低频词或者⼀些未遇到过的词等。
< GO>: 解码器端的句⼦起始标识符。
代码如下:
encoder-decoder.py
#参考:zhuanlan.zhihu/p/27608348
import numpy as np
import time
import tensorflow as tf
from tensorflow. import Dense
#数据加载
with open('data/','r',encoding='utf-8')as fs:
source_ad()
with open('data/','r',encoding='utf-8')as ft:
target_ad()
#数据预处理
def extract_character_vocab(data):
special_words=['<PAD>','<UNK>','<GO>','<EOS>']
set_words=list(set([character for line in data.split('\n')for character in line]))
#构造映射表
int_to_vocab={idx:word for idx,word in enumerate(special_words+set_words)}
vocab_to_int={word:idx for idx,word in int_to_vocab.items()}
return int_to_vocab,vocab_to_int
#print(source_int[:10])
#建⽴模型
#输⼊层
def get_inputs():
'''
模型输⼊tensor
:return:
'''
inputs=tf.placeholder(tf.int32,[None,None],name='inputs')

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。