TensorFlow实现seq2seq

原创 2017年09月14日 10:46:29

前言

前面在《深度学习的seq2seq模型》文章中已经介绍了seq2seq结构及其原理,接下去这篇文章将尝试使用TensorFlow来实现一个seq2seq网络结构,该例子能通过训练给定的训练集实现输入某个序列输出某个序列,其中输入序列和输出序列相同,这里选择使用LSTM模型。

训练样本集

为方便起见这里使用随机生成的序列作为样本,序列的长度也是随机的且在指定的范围内。

LSTM机制原理

关于LSTM机制原理可看之前的文章《LSTM神经网络》

随机序列生成器

def random_sequences(length_from, length_to, vocab_lower, vocab_upper, batch_size):
    def random_length():
        if length_from == length_to:
            return length_from
        return np.random.randint(length_from, length_to + 1)

    while True:
        yield [
            np.random.randint(low=vocab_lower, high=vocab_upper, size=random_length()).tolist()
            for _ in range(batch_size)
            ]

构建一个随机序列生成器方便后面生成序列,其中 length_from 和 length_to表示序列的长度范围从多少到多少,vocab_lower 和 vocab_upper 表示生成的序列值的范围从多少到多少,batch_size 即是批的数量。

填充序列

def make_batch(inputs, max_sequence_length=None):
    sequence_lengths = [len(seq) for seq in inputs]
    batch_size = len(inputs)
    if max_sequence_length is None:
        max_sequence_length = max(sequence_lengths)
    inputs_batch_major = np.zeros(shape=[batch_size, max_sequence_length], dtype=np.int32)
    for i, seq in enumerate(inputs):
        for j, element in enumerate(seq):
            inputs_batch_major[i, j] = element
    inputs_time_major = inputs_batch_major.swapaxes(0, 1)
    return inputs_time_major, sequence_lengths

生成的随机序列的长度是不一样的,需要对短的序列用来填充,而可设为0,取最长的序列作为每个序列的长度,不足的填充,然后再转换成time major形式。

构建图

encoder_inputs = tf.placeholder(shape=(None, None), dtype=tf.int32, name='encoder_inputs')
ecoder_inputs = tf.placeholder(shape=(None, None), dtype=tf.int32, name='decoder_inputs')
decoder_targets = tf.placeholder(shape=(None, None), dtype=tf.int32, name='decoder_targets')

创建三个占位符,分别为encoder的输入占位符、decoder的输入占位符和decoder的target占位符。

embeddings = tf.Variable(tf.random_uniform([vocab_size, input_embedding_size], -1.0, 1.0), dtype=tf.float32)
encoder_inputs_embedded = tf.nn.embedding_lookup(embeddings, encoder_inputs)
decoder_inputs_embedded = tf.nn.embedding_lookup(embeddings, decoder_inputs)

将encoder和decoder的输入做一个嵌入操作,对于大词汇量这个能达到降维的效果,嵌入操作也是很常用的方式了。在seq2seq模型中,encoder和decoder都是共用一个嵌入层即可。嵌入层的向量形状为[vocab_size, input_embedding_size],初始值从-1到1,后面训练会自动调整。

encoder_cell = tf.contrib.rnn.LSTMCell(encoder_hidden_units)
encoder_outputs, encoder_final_state = tf.nn.dynamic_rnn(
        encoder_cell, encoder_inputs_embedded,
        dtype=tf.float32, time_major=True,
    )
decoder_cell = tf.contrib.rnn.LSTMCell(decoder_hidden_units)
decoder_outputs, decoder_final_state = tf.nn.dynamic_rnn(
        decoder_cell, decoder_inputs_embedded,
        initial_state=encoder_final_state,
        dtype=tf.float32, time_major=True, scope="plain_decoder",
    )

创建encoder和decoder的LSTM神经网络,encoder_hidden_units 为LSTM隐层数量,设定输入格式为time major格式。这里我们不关心encoder的循环神经网络的输出,我们要的是它的最终状态encoder_final_state,将其作为decoder的循环神经网络的初始状态。

decoder_logits = tf.contrib.layers.linear(decoder_outputs, vocab_size)
decoder_prediction = tf.argmax(decoder_logits, 2)
stepwise_cross_entropy = tf.nn.softmax_cross_entropy_with_logits(
        labels=tf.one_hot(decoder_targets, depth=vocab_size, dtype=tf.float32),
        logits=decoder_logits,
    )
loss = tf.reduce_mean(stepwise_cross_entropy)
train_op = tf.train.AdamOptimizer().minimize(loss)

对于decoder的循环神经网络的输出,因为我们要一个分类结果,所以需要一个全连接神经网络,输出层神经元数量是词汇的数量。输出层最大值对应的神经元即为预测的类别。输出层的激活函数用softmax,损失函数用交叉熵损失函数。

创建会话

with tf.Session(graph=train_graph) as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(epochs):
        batch = next(batches)
        encoder_inputs_, _ = make_batch(batch)
        decoder_targets_, _ = make_batch([(sequence) + [EOS] for sequence in batch])
        decoder_inputs_, _ = make_batch([[EOS] + (sequence) for sequence in batch])
        feed_dict = {encoder_inputs: encoder_inputs_, decoder_inputs: decoder_inputs_,
                     decoder_targets: decoder_targets_,
                     }
        _, l = sess.run([train_op, loss], feed_dict)
        loss_track.append(l)
        if epoch == 0 or epoch % 1000 == 0:
            print('loss: {}'.format(sess.run(loss, feed_dict)))
            predict_ = sess.run(decoder_prediction, feed_dict)
            for i, (inp, pred) in enumerate(zip(feed_dict[encoder_inputs].T, predict_.T)):
                print('input > {}'.format(inp))
                print('predicted > {}'.format(pred))
                if i >= 20:
                    break

创建会话开始执行,每次生成一批数量,用 make_batch 分别创建encoder输入、decoder的target和decoder的输入。其中target需要在后面加上[EOS],它表示句子的结尾,同时输入也加上[EOS]表示编码开始。每训练1000词输出看看效果。

这里写图片描述

github

https://github.com/sea-boat/DeepLearning-Lab

========广告时间========

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。

为什么写《Tomcat内核设计剖析》

=========================

欢迎关注:

这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

计算机视觉-相机内参数和外参数

相机内参数是与相机自身特性相关的参数,比如相机的焦距、像素大小等; 相机外参数是在世界坐标系中的参数,比如相机的位置、旋转方向等。 相机标定(或摄像机标定): 在图像测量过程以及机器视觉应用中,为确...

如何根据相机的参数知道摄像机的内参数矩阵

摄像机的透视投影模型(即针孔成像模型):       设OXYZ为世界坐标系,uv为以像素为单位的图像坐标系。如果物点P在世界坐标系下的坐标为(X,Y,Z),对应的图像点p在图像坐标系的坐标为(u,v...

基于简单seq to seq 的聊天机器人+代码实现 (tensorfow 1.1版本)

一、seqto seq模型简介 基本Encoder-Decoder模型 输入的序列为['A','B', 'C', ''],输出序列为['W','X', 'Y', 'Z'...

深度学习的seq2seq模型

从rnn结构说起根据输出和输入序列不同数量rnn可以有多种不同的结构,不同结构自然就有不同的引用场合。如下图, one to one 结构,仅仅只是简单的给一个输入得到一个输出,此处并未体现序列的特征...

【tensorflow 学习】seq2seq模型代码解读

Reference: 1. https://www.tensorflow.org/tutorials/seq2seq 2. http://www.2cto.com/kf/201612/575911...

词向量源码解析:(5.2)ngram2vec源码解析之uni_uni

ngram2vec工具包的流程和hyperwords很像,都是一系列的##2##文件,最终从语料一步一步得到词向量。所以我们先通过脚本文件看一下整个的执行流程。一共有三个脚本文件,uni_uni,un...

tensorflow seq2seq模型 代码阅读分析

如果刚开始入门该模型请阅读tf官方说明:Sequence-to-Sequence Models模型应用于机器翻译的示例代码:github如果还没有看懂tf的translate示例代码,请先理解透彻tr...

tensorflow代码全解析 -3- seq2seq 自动生成文本

模型概述序列建模seq2seq,给定一个序列A,模型生产另一个序列B,然后模型再由序列B生成C,以此一直持续下去。基本工作流程如下: 序列A中的每一个单词通过word_embedding操作以后,作...

浅析谷歌tensorflow官方文档中的seq2seq代码

自然语言处理是深度学习亟待攻克的新领域,实力雄厚的IT大企业比如谷歌、IBM、脸书都不遗余力招揽人才开展前沿研究,抢占话语权。比如谷歌开源了深度学习工具包tensorflow意图打造谷歌生态圈,脸书也...

常见优化算法 (caffe和tensorflow对应参数)

常见优化算法 (caffe和tensorflow对应参数)算法可视化常见算法SGDx+= -learning_rate*dxMomentumMomentum可以使SGD不至于陷入局部鞍点震荡,同时起到...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)