seq2seq 的 keras 实现

上一篇 seq2seq 入门 提到了 cho 和 Sutskever 的两篇论文,今天来看一下如何用 keras 建立 seq2seq。

第一个 LSTM 为 Encoder,只在序列结束时输出一个语义向量,所以其 "return_sequences" 参数设置为 "False"

使用 "RepeatVector" 将 Encoder 的输出(最后一个 time step)复制 N 份作为 Decoder 的 N 次输入

第二个 LSTM 为 Decoder, 因为在每一个 time step 都输出,所以其 "return_sequences" 参数设置为 "True"

from keras.models import Sequential
from keras.layers.recurrent import LSTM
from keras.layers.wrappers import TimeDistributed
from keras.layers.core import Dense, RepeatVector

def build_model(input_size, max_out_seq_len, hidden_size):
    
    model = Sequential()
    
    # Encoder(第一个 LSTM)     model.add( LSTM(input_dim=input_size, output_dim=hidden_size, return_sequences=False) )
    
    
    model.add( Dense(hidden_size, activation="relu") )
    
    # 使用 "RepeatVector" 将 Encoder 的输出(最后一个 time step)复制 N 份作为 Decoder 的 N 次输入
    model.add( RepeatVector(max_out_seq_len) )
    
    # Decoder(第二个 LSTM) 
    model.add( LSTM(hidden_size, return_sequences=True) )
    
    # TimeDistributed 是为了保证 Dense 和 Decoder 之间的一致
    model.add( TimeDistributed(Dense(output_dim=input_size, activation="linear")) )
    
    model.compile(loss="mse", optimizer='adam')

    return model

也可以用 GRU 作为 RNN 单元,代码如下,区别就是将 LSTM 处换成 GRU:

from keras.layers.recurrent import GRU
from keras.layers.wrappers import TimeDistributed
from keras.models import Sequential, model_from_json
from keras.layers.core import Dense, RepeatVector    

def build_model(input_size, seq_len, hidden_size):
    """建立一个 sequence to sequence 模型"""
    model = Sequential()
    model.add(GRU(input_dim=input_size, output_dim=hidden_size, return_sequences=False))
    model.add(Dense(hidden_size, activation="relu"))
    model.add(RepeatVector(seq_len))
    model.add(GRU(hidden_size, return_sequences=True))
    model.add(TimeDistributed(Dense(output_dim=input_size, activation="linear")))
    model.compile(loss="mse", optimizer='adam')

    return model

上面是一个最简单的 seq2seq 模型,因为没有将 Decoder 的每一个时刻的输出作为下一个时刻的输入。


当然,我们可以直接用 keras 的 seq2seq 模型:

https://github.com/farizrahman4u/seq2seq

下面是几个例子:

简单的 seq2seq 模型:

import seq2seq
from seq2seq.models import SimpleSeq2Seq

model = SimpleSeq2Seq(input_dim=5, hidden_dim=10, output_length=8, output_dim=8)
model.compile(loss='mse', optimizer='rmsprop')

深度 seq2seq 模型:encoding 有 3 层, decoding 有 3 层

import seq2seq
from seq2seq.models import SimpleSeq2Seq

model = SimpleSeq2Seq(input_dim=5, hidden_dim=10, output_length=8, output_dim=8, depth=3)
model.compile(loss='mse', optimizer='rmsprop')

encoding 和 decoding 的层数也可以不同:encoding 有 4 层, decoding 有 5 层

import seq2seq
from seq2seq.models import SimpleSeq2Seq

model = SimpleSeq2Seq(input_dim=5, hidden_dim=10, output_length=8, output_dim=20, depth=(4, 5))
model.compile(loss='mse', optimizer='rmsprop')

上面几种也是最简单的 SimpleSeq2Seq 的应用。


在论文 Sequence to Sequence Learning with Neural Networks 给出的 seq2seq 中,encoder 的隐藏层状态要传递给 decoder,而且 decoder 的每一个时刻的输出作为下一个时刻的输入,而且这里内置的模型中,还将隐藏层状态贯穿了整个 LSTM:

import seq2seq
from seq2seq.models import Seq2Seq

model = Seq2Seq(batch_input_shape=(16, 7, 5), hidden_dim=10, output_length=8, output_dim=20, depth=4)
model.compile(loss='mse', optimizer='rmsprop')

cho 的这篇论文 Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation 中的 seq2seq 模型实现为:decoder 在每个时间点的语境向量都会获得一个 'peek'

import seq2seq
from seq2seq.models import Seq2Seq

model = Seq2Seq(batch_input_shape=(16, 7, 5), hidden_dim=10, output_length=8, output_dim=20, depth=4, peek=True)
model.compile(loss='mse', optimizer='rmsprop')

在论文 Neural Machine Translation by Jointly Learning to Align and Translate 中带有注意力机制的 seq2seq:没有隐藏状态的传播,而且 encoder 是双向的 LSTM

import seq2seq
from seq2seq.models import AttentionSeq2Seq

model = AttentionSeq2Seq(input_dim=5, input_length=7, hidden_dim=10, output_length=8, output_dim=20, depth=4)
model.compile(loss='mse', optimizer='rmsprop')

参考: https://github.com/farizrahman4u/seq2seq http://www.zmonster.me/2016/05/29/sequence_to_sequence_with_keras.html http://jacoxu.com/encoder_decoder/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏菜鸟程序员

Java中在特定区间产生随机数

11220
来自专栏个人分享

旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2...

9540
来自专栏郭耀华‘s Blog

TensorFlow 常用函数汇总

75220
来自专栏小樱的经验随笔

容斥原理

容斥原理 对容斥原理的描述 容斥原理是一种重要的组合数学方法,可以让你求解任意大小的集合,或者计算复合事件的概率。 描述 容斥原理可以描述如下: 要计算几个...

47170
来自专栏Bingo的深度学习杂货店

最小方差划分

给一个数组,求一个k值,使得前k个数的方差 + 后面n-k个数的方差最小 解题思路: 如果不考虑方差的概念,这题可以简化为 “给一个数组,求一个k值,使得前k个...

53730
来自专栏数据结构与算法

27:单词翻转

27:单词翻转 总时间限制: 1000ms 内存限制: 65536kB描述 输入一个句子(一行),将句子中的每一个单词翻转后输出。 输入只有一行,为一个...

43370
来自专栏余林丰

9.动态规划(2)——子集和问题

注:因为对“子集和问题”的学习不够深入,所以本文在讲解动态规划递推公式中可能存在叙述不清,或者错误的地方,如有发现望能不吝赐教。   子集和问题可描述如下:给定...

39280
来自专栏杂七杂八

matlab中的函数介绍(max,min,unidrnd,norm)

遇到不知道的函数时,可以使用help 函数名来查看帮助 1 求矩阵A的最大值的函数有3种调用格式,分别是: max(A):返回一个行向量,向量的第i个元...

41150
来自专栏Bingo的深度学习杂货店

Q221 Maximal Square

Given a 2D binary matrix filled with 0's and 1's, find the largest square contai...

39750
来自专栏趣学算法

数据结构 第9讲 数组与广义表

LOC(a00)表示第一个元素的存储位置,即基地址,LOC(aij)表示aij的存储位置。 授人以鱼不如授人以渔,告诉你记住公式,就像送你一条鱼,不如交给你捕...

13920

扫码关注云+社区

领取腾讯云代金券