tensorflow源码解析之seq2seq.py文件(上)

tensorflow源码解析之seq2seq.py文件(上)
2018年05月14日 09:38 ai人工智能angtk

一、前言

自从接触并学习tensorflow框架之后,总是会遇到很多莫名奇妙的报错信息。而网上又很少有相似的问题的解决方案。因此很久之前就想学一下tendorflow的源码,能够深层次的理解tensorflow这个框架。但是由于一些原因耽搁了。现在正式开始研究tensorflow源码,由于要参加之后的京东对话系统挑战赛,因此就从nlp部分的seq2seq开始。这里使用的tensorflow版本为1.2.1。

二、阅读源码的一些小技巧

在阅读源码文件的过程中,会发现基本上每个文件都存在大量交叉引用的现象,在阅读的过程中,可以提前了解import进来的一些文件,暂时先不用去读import进来的文件中的内容,看源码的过程中遇到不知道的函数名或类,再去import进来的其他文件中去找。我用的工具是windows下的pycharm。这里放一张分析图:

三、开始搞

seq2seq.py文件

1、介绍

seq2seq.py文件在tensorflow/contrib/legacy_seq2seq/python/ops路径下。为1.2.1以下版本的seq2seq接口,但是也封装进了1.2.1版本中。由于使用1.2.1版本以下的人也很多,因此先介绍一下这个文件。

文件的目的:在TensorFlow创建序列到序列模型的库。

2、*全部的序列模型包括:

-basic_rnn_seq2seq:#最简单版本,输入和输出都是embedding的形式;最后一步的state vector#作为decoder的initial state;encoder和decoder用相同的RNN cell, #但不共享权值参数;-tied_rnn_seq2seq:#同basic_rnn_seq2seq,但是encoder和decoder共享权值参数-embedding_rnn_seq2seq: #同basic_rnn_seq2seq,但输入和输出改为id的形式,函数会在内部创建分 #别用于encoder和decoder的embedding matrix-embedding_tied_rnn_seq2seq#同tied_rnn_seq2seq,但输入和输出改为id形式,函数会在内部创建分别 #用于encoder和decoder的embedding matrix-embedding_attention_seq2seq:#同embedding_rnn_seq2seq,但多了attention机制,推荐用于复杂任务。

*多任务序列到序列模型

-one2many_rnn_seq2seq:具有多个解码器的嵌入模型

*解码器(当你编写自己的编码器时,你可以用这些来解码;

- rnn_decoder: 基于纯RNN的基本解码器。- attention_decoder: 使用注意机制的解码器。

*损失。

- sequence_loss:返回 average log-perplexity的序列模型的损失。 - sequence_loss_by_example: 和上面损失函数一样,但不在所有的例子中求均值

*model_with_buckets:一种方便的带桶创建模型的功能

3、正式源码:

(1)import部分

from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport copy# We disable pylint because we need python3 compatibility.from six.moves import xrange # pylint: disable=redefined-builtinfrom six.moves import zip # pylint: disable=redefined-builtin#core_rnn_cell在tensorflow/contrib/rnn/python/ops目录下。即引入rnn模块from tensorflow.contrib.rnn.python.ops import core_rnn_cell#引入张量元素类型的库from tensorflow.python.framework import dtypes#引入用来构建graph的类和函数from tensorflow.python.framework import ops#引入关于array操作的一些函数,下面就不一一列举了,想要了解每个import进来的文件是做什么用的,去对应的文件下看一下就知道了from tensorflow.python.ops import array_opsfrom tensorflow.python.ops import control_flow_opsfrom tensorflow.python.ops import embedding_opsfrom tensorflow.python.ops import math_opsfrom tensorflow.python.ops import nn_opsfrom tensorflow.python.ops import rnnfrom tensorflow.python.ops import rnn_cell_implfrom tensorflow.python.ops import variable_scopefrom tensorflow.python.util import nest

下面将按照源码中函数出现的顺序逐一介绍各个函数。

(2) _extract_argmax_and_embed()

函数功能:得到一个提取前一个符号并嵌入它的loop_functiondef _extract_argmax_and_embed(embedding, output_projection=None, update_embedding=True):'''参数:embedding:嵌入符号的张量 output_projection=None:None或一对(W,B)。如果提供,如果提供,每个前馈输出将首先乘以W并加上B. update_embedding=True:布尔类型,如果为假,则梯度不会通过嵌入传播。''' def loop_function(prev, _): if output_projection is not None: prev = nn_ops.xw_plus_b(prev, output_projection[0], output_projection[1]) prev_symbol = math_ops.argmax(prev, 1) # Note that gradients will not propagate through the second parameter of # embedding_lookup. emb_prev = embedding_ops.embedding_lookup(embedding, prev_symbol) if not update_embedding: emb_prev = array_ops.stop_gradient(emb_prev) return emb_prev #最终返回的loop_function在之后的函数中会被用到 return loop_function

(3)rnn_decoder()

函数功能:RNN decoder for the sequence-to-sequence modeldef rnn_decoder(decoder_inputs, initial_state, cell, loop_function=None, scope=None):'''参数:decoder_inputs:是a list,其中的每一个元素表示的是t_i时刻的输入,每一时刻的输入又会有batch_size个,每一个输入(通差是表示一个word或token)又是input_size维度的。initial_state:初始状态,通常是encoder的ht。cell:如果output_projection为默认的None,此时为训练模式,这时的cell加了一层OutputProjectionWrapper,即将输出的[batch_size, output_size]转化为[batch_size,symbol]。而如果output_projection不为空,此时的cell的输出还是[batch_size, output_size]。loop_function: 如果loop_function有设置的话,decoder input中第一个”GO”会输入,但之后时刻的input就会被忽略,取代的是input_ti+1 = loop_function(output_ti)。这里定义的loop_function,有2个参数,(prev,i),输出为next''' with variable_scope.variable_scope(scope or "rnn_decoder"): state = initial_state outputs = [] prev = None for i, inp in enumerate(decoder_inputs): if loop_function is not None and prev is not None: with variable_scope.variable_scope("loop_function", reuse=True): inp = loop_function(prev, i) if i > 0: variable_scope.get_variable_scope().reuse_variables() output, state = cell(inp, state) outputs.append(output) if loop_function is not None: prev = output return outputs, state

(4)、basic_rnn_seq2seq()

函数功能:Basic RNN sequence-to-sequence model.def basic_rnn_seq2seq(encoder_inputs, decoder_inputs, cell, dtype=dtypes.float32, scope=None): """ 这一部分具体描述就看英文的吧,更通俗易懂一些 This model first runs an RNN to encode encoder_inputs into a state vector, then runs decoder, initialized with the last encoder state, on decoder_inputs. Encoder and decoder use the same RNN cell type, but don't share parameters. Args: encoder_inputs: A list of 2D Tensors [batch_size x input_size]. decoder_inputs: A list of 2D Tensors [batch_size x input_size]. cell: tf.nn.rnn_cell.RNNCell defining the cell function and size. dtype: The dtype of the initial state of the RNN cell (default: tf.float32). scope: VariableScope for the created subgraph; default: "basic_rnn_seq2seq". Returns: #一个由output和state构成的元组 A tuple of the form (outputs, state), where: outputs: A list of the same length as decoder_inputs of 2D Tensors with shape [batch_size x output_size] containing the generated outputs. state: The state of each decoder cell in the final time-step. It is a 2D Tensor of shape [batch_size x cell.state_size]. """ with variable_scope.variable_scope(scope or "basic_rnn_seq2seq"): enc_cell = copy.deepcopy(cell) _, enc_state = rnn.static_rnn(enc_cell, encoder_inputs, dtype=dtype) return rnn_decoder(decoder_inputs, enc_state, cell)

由于篇幅原因,后面的API介绍将在下篇文章中给出。由于本人水平有限,文中难免有出错的地方,还望大家指正,谢谢大家。

我们人工智能社群正在基于知识点分析联系tf源码文件。大家可以在:aiangtk 留言参加,给大家发送二维码

财经自媒体联盟更多自媒体作者

新浪首页 语音播报 相关新闻 返回顶部