From e6aa2ba9018ed4d00d5ce38747426c9b31973a70 Mon Sep 17 00:00:00 2001 From: Youwei Song Date: Tue, 8 Oct 2019 22:39:26 +0800 Subject: [PATCH] Refine cn layers: dynamic_lstm, dynamic_lstmp, lstm (#1452) * refine lstm * refine LSTMs, test=develop * fix notice color, test=develop --- .../api_cn/layers_cn/dynamic_lstm_cn.rst | 115 ++++++------ .../api_cn/layers_cn/dynamic_lstmp_cn.rst | 166 ++++++++++-------- doc/fluid/api_cn/layers_cn/lstm_cn.rst | 95 ++++++---- 3 files changed, 204 insertions(+), 172 deletions(-) diff --git a/doc/fluid/api_cn/layers_cn/dynamic_lstm_cn.rst b/doc/fluid/api_cn/layers_cn/dynamic_lstm_cn.rst index a39e9ea82..d2348658f 100644 --- a/doc/fluid/api_cn/layers_cn/dynamic_lstm_cn.rst +++ b/doc/fluid/api_cn/layers_cn/dynamic_lstm_cn.rst @@ -5,88 +5,87 @@ dynamic_lstm .. py:function:: paddle.fluid.layers.dynamic_lstm(input, size, h_0=None, c_0=None, param_attr=None, bias_attr=None, use_peepholes=True, is_reverse=False, gate_activation='sigmoid', cell_activation='tanh', candidate_activation='tanh', dtype='float32', name=None) -LSTM,即Long-Short Term Memory(长短期记忆)运算。 +该OP实现了 LSTM,即 Long-Short Term Memory(长短期记忆)运算 - `Hochreiter, S., & Schmidhuber, J. (1997) `_。 -默认实现方式为diagonal/peephole连接(https://arxiv.org/pdf/1402.1128.pdf),公式如下: +.. raw:: html + + +.. role:: red + +:red:`注意:` + - :red:`该OP仅支持 LoDTensor 作为输入,如果您需要处理的是Tensor,请使用` :ref:`cn_api_fluid_layers_lstm` 。 + - :red:`在实现的时候为了提升效率,用户必须将LSTM的输入先进行线性映射,将维度为 [T, hidden_size] 的输入映射为 [T, 4 × hidden_size] 输入,然后再传给该OP。` + +该OP的默认实现方式为 diagonal/peephole 连接,参见 `Gers, F. A., & Schmidhuber, J. (2000) `_。 +如果需要禁用 peephole 连接方法,将 use_peepholes 设为 False 即可。 + +该OP对于序列中每一个时间步的计算公式如下: .. math:: i_t=\sigma (W_{ix}x_{t}+W_{ih}h_{t-1}+W_{ic}c_{t-1}+b_i) .. math:: f_t=\sigma (W_{fx}x_{t}+W_{fh}h_{t-1}+W_{fc}c_{t-1}+b_f) .. math:: - \widetilde{c_t}=act_g(W_{ct}x_{t}+W_{ch}h_{t-1}+b_{c}) + o_t=\sigma (W_{ox}x_{t}+W_{oh}h_{t-1}+W_{oc}c_{t-1}+b_o) .. math:: - o_t=\sigma (W_{ox}x_{t}+W_{oh}h_{t-1}+W_{oc}c_{t}+b_o) + \widetilde{c_t}=act_g(W_{ct}x_{t}+W_{ch}h_{t-1}+b_{c}) .. math:: c_t=f_t\odot c_{t-1}+i_t\odot \widetilde{c_t} .. math:: h_t=o_t\odot act_h(c_t) -W 代表了权重矩阵(weight matrix),例如 :math:`W_{xi}` 是从输入门(input gate)到输入的权重矩阵, :math:`W_{ic}` ,:math:`W_{fc}` , :math:`W_{oc}` 是对角权重矩阵(diagonal weight matrix),用于peephole连接。在此实现方式中,我们使用向量来代表这些对角权重矩阵。 - -其中: - - :math:`b` 表示bias向量( :math:`b_i` 是输入门的bias向量) - - :math:`σ` 是非线性激励函数(non-linear activations),比如逻辑sigmoid函数 - - :math:`i` ,:math:`f` ,:math:`o` 和 :math:`c` 分别为输入门(input gate),遗忘门(forget gate),输出门(output gate),以及神经元激励向量(cell activation vector)这些向量和神经元输出激励向量(cell output activation vector) :math:`h` 有相同的大小。 - - :math:`⊙` 意为按元素将两向量相乘 - - :math:`act_g` , :math:`act_h` 分别为神经元(cell)输入、输出的激励函数(activation)。常常使用tanh函数。 - - :math:`\widetilde{c_t}` 也被称为候选隐藏状态(candidate hidden state)。可根据当前输入和之前的隐藏状态计算而得 - -将 ``use_peepholes`` 设为False来禁用 peephole 连接方法。 公式等详细信息请参考 http://www.bioinf.jku.at/publications/older/2604.pdf 。 - -注意, :math:`W_{xi}x_t, W_{xf}x_t, W_{xc}x_t,W_{xo}x_t` 这些在输入 :math:`x_t` 上的操作不包括在此运算中。用户可以在LSTM operator之前选择使用全连接运算。 +公式中的概念信息如下: + - :math:`x_{t}` 表示时间步 :math:`t` 的输入 + - :math:`h_{t}` 表示时间步 :math:`t` 的 hidden 状态 + - :math:`h_{t-1}, c_{t-1}` 分别表示前一个时间步的 hidden 和 cell 状态 + - :math:`\widetilde{c_t}` 表示候选的 cell 状态 + - :math:`i_t` ,:math:`f_t` 和 :math:`o_t` 分别为 input gate,forget gate,output gate + - :math:`W` 表示 weight (例如, :math:`W_{ix}` 是在计算 input gate :math:`i_t` 时,对输入 :math:`x_{t}` 做线性变换的 weight) + - :math:`b` 表示 bias (例如, :math:`b_{i}` 是 input gate 的 bias) + - :math:`\sigma` 表示 gate 的非线性激活函数,默认为 sigmoid + - :math:`act_g, act_h` 分别表示 cell 输入和 cell 输出的非线性激活函数,默认为 tanh + - :math:`\odot` 表示矩阵的 Hadamard product,即对两个维度相同的矩阵,将相同位置的元素相乘,得到另一个维度相同的矩阵 +参数: + - **input** ( :ref:`api_guide_Variable` ) 维度为 :math:`[T, 4*hidden\_size]` 的多维 LoDTensor(必须在传入该OP前对维度为 :math:`[T, hidden\_size]` 的输入经过线性变换得到),其中 T 为 batch 中所有样本的长度之和,hidden_size 为隐层大小,数据类型为 float32 或者 float64。 + - **size** (int) – 必须为 4*hidden_size。 + - **h_0** ( :ref:`api_guide_Variable` ,可选) 维度为 :math:`[batch\_size, hidden\_size]` 的多维 Tensor,其中 hidden_size 为隐层大小,数据类型为 float32 或者 float64。如果为 None,该OP会自动设置为全0的向量。默认值为None。 + - **c_0** ( :ref:`api_guide_Variable` ,可选) 维度为 :math:`[batch\_size, hidden\_size]` 的多维 Tensor,其中 hidden_size 为隐层大小,数据类型为 float32 或者 float64。如果为 None,该OP会自动设置为全0的向量;:math:`h_0, c_0` 如果要设置为None,必须同时为None。默认值为None。 + - **param_attr** (ParamAttr,可选) – 指定权重参数属性的对象。如果为None,表示使用默认的权重参数属性。具体用法请参见 :ref:`cn_api_fluid_ParamAttr` 。如果用户需要设置此属性,维度必须等于 :math:`[hidden\_size, 4*hidden\_size]`。默认值为None。 + - **bias_attr** (ParamAttr,可选) – 指定偏置参数属性的对象。如果为None,表示使用默认的偏置参数属性。具体用法请参见 :ref:`cn_api_fluid_ParamAttr` 。如果用户需要设置此属性,如果 use_peepholes=true,维度需为 :math:`[1, 4*hidden\_size]`, use_peepholes=true,维度需为 :math:`[1, 7*hidden\_size]`。默认值为None。 + - **use_peepholes** (bool,可选) – 是否使用 peephole 连接。默认值为True。 + - **is_reverse** (bool,可选) – 是否将输入的数据根据根据样本长度进行逆序,同时会将输出进行逆序,用户拿到结果之后,不需要再逆序。默认值为False。 + - **gate_activation** (str,可选) – 应用于input gate,forget gate, output gate 的激活函数。默认值为sigmoid。 + - **cell_activation** (str,可选) – 用于cell输入的激活函数。默认值为tanh。 + - **candidate_activation** (str,可选) – 用于cell输出的激活函数。默认值为tanh。 + - **dtype** (str,可选) – 数据类型为 float32 或者 float64。默认值为 float32。 + - **name** (str,可选) – 具体用法请参见 :ref:`api_guide_Name` ,默认值为None。 +返回:经过lstm运算输出的 hidden 和 cell 的状态的tuple,包括 +- hidden:LSTM hidden的输出结果,维度为 :math:`[T, hidden\_size]` 的LoDTensor,且LoD保持与输入一致,数据类型与input一致。 +- cell:LSTM cell的输出结果,维度为 :math:`[T, hidden\_size]` 的LoDTensor,且LoD保持与输入一致,数据类型与input一致。 -参数: - - **input** (Variable) (LoDTensor) - LodTensor类型,支持variable time length input sequence(时长可变的输入序列)。 该LoDTensor中底层的tensor是一个形为(T X 4D)的矩阵,其中T为此mini-batch上的总共时间步数。D为隐藏层的大小、规模(hidden size) - - **size** (int) – 4 * 隐藏层大小 - - **h_0** (Variable) – 最初的隐藏状态(hidden state),可选项。默认值为0。它是一个(N x D)张量,其中N是batch大小,D是隐藏层大小。 - - **c_0** (Variable) – 最初的神经元状态(cell state), 可选项。 默认值0。它是一个(N x D)张量, 其中N是batch大小。h_0和c_0仅可以同时为None,不能只其中一个为None。 - - **param_attr** (ParamAttr|None) – 可学习的隐藏层权重的参数属性。 - 注意: - - Weights = :math:`\{W_{ch}, W_{ih}, W_{fh}, W_{oh} \}` - - 形为(D x 4D), 其中D是hidden size(隐藏层规模) - - 如果它被设为None或者 ``ParamAttr`` 属性之一, dynamic_lstm会创建 ``ParamAttr`` 对象作为param_attr。如果没有对param_attr初始化(即构造函数没有被设置), Xavier会负责初始化参数。默认为None。 - - **bias_attr** (ParamAttr|None) – 可学习的bias权重的属性, 包含两部分,input-hidden bias weights(输入隐藏层的bias权重)和 peephole connections weights(peephole连接权重)。如果 ``use_peepholes`` 值为 ``True`` , 则意为使用peephole连接的权重。 - 另外: - - use_peepholes = False - Biases = :math:`\{ b_c,b_i,b_f,b_o \}` - 形为(1 x 4D)。 - - use_peepholes = True - Biases = :math:`\{ b_c,b_i,b_f,b_o,W_{ic},W_{fc},W_{oc} \}` - 形为 (1 x 7D)。 - - 如果它被设为None或 ``ParamAttr`` 的属性之一, ``dynamic_lstm`` 会创建一个 ``ParamAttr`` 对象作为bias_attr。 如果没有对bias_attr初始化(即构造函数没有被设置),bias会被初始化为0。默认值为None。 - - **use_peepholes** (bool) – (默认: True) 是否使用diagonal/peephole连接方式 - - **is_reverse** (bool) – (默认: False) 是否计算反LSTM(reversed LSTM) - - **gate_activation** (str) – (默认: "sigmoid")应用于input gate(输入门),forget gate(遗忘门)和 output gate(输出门)的激励函数(activation),默认为sigmoid - - **cell_activation** (str) – (默认: tanh)用于神经元输出的激励函数(activation), 默认为tanh - - **candidate_activation** (str) – (默认: tanh)candidate hidden state(候选隐藏状态)的激励函数(activation), 默认为tanh - - **dtype** (str) – 即 Data type(数据类型)。 可以选择 [“float32”, “float64”],默认为“float32” - - **name** (str|None) – 该层的命名,可选项。如果值为None, 将会自动对该层命名 - -返回:隐藏状态(hidden state),LSTM的神经元状态。两者都是(T x D)形,且LoD保持与输入一致 - -返回类型: 元组(tuple) +返回类型: tuple( :ref:`api_guide_Variable` , :ref:`api_guide_Variable` ) **代码示例** .. code-block:: python - import paddle.fluid as fluid - emb_dim = 256 - vocab_size = 10000 - hidden_dim = 512 - - data = fluid.layers.data(name='x', shape=[1], - dtype='int32', lod_level=1) - emb = fluid.layers.embedding(input=data, size=[vocab_size, emb_dim], is_sparse=True) - - forward_proj = fluid.layers.fc(input=emb, size=hidden_dim * 4, - bias_attr=False) - forward, _ = fluid.layers.dynamic_lstm( - input=forward_proj, size=hidden_dim * 4, use_peepholes=False) + import paddle.fluid as fluid + emb_dim = 256 + vocab_size = 10000 + hidden_dim = 512 + + data = fluid.layers.data(name='x', shape=[1], dtype='int32', lod_level=1) + emb = fluid.layers.embedding(input=data, size=[vocab_size, emb_dim], is_sparse=True) + + forward_proj = fluid.layers.fc(input=emb, size=hidden_dim * 4, bias_attr=False) + forward, cell = fluid.layers.dynamic_lstm(input=forward_proj, size=hidden_dim * 4, use_peepholes=False) + forward.shape # (-1, 512) + cell.shape # (-1, 512) diff --git a/doc/fluid/api_cn/layers_cn/dynamic_lstmp_cn.rst b/doc/fluid/api_cn/layers_cn/dynamic_lstmp_cn.rst index ffb0608b2..573bf9058 100644 --- a/doc/fluid/api_cn/layers_cn/dynamic_lstmp_cn.rst +++ b/doc/fluid/api_cn/layers_cn/dynamic_lstmp_cn.rst @@ -4,101 +4,117 @@ dynamic_lstmp ------------------------------- .. py:function:: paddle.fluid.layers.dynamic_lstmp(input, size, proj_size, param_attr=None, bias_attr=None, use_peepholes=True, is_reverse=False, gate_activation='sigmoid', cell_activation='tanh', candidate_activation='tanh', proj_activation='tanh', dtype='float32', name=None, h_0=None, c_0=None, cell_clip=None, proj_clip=None) -动态LSTMP层(Dynamic LSTMP Layer) +.. raw:: html -LSTMP层(具有循环映射的LSTM)在LSTM层后有一个分离的映射层,从原始隐藏状态映射到较低维的状态,用来减少参数总数,减少LSTM计算复杂度,特别是输出单元相对较大的情况下。 `Long Short-Term Memory Recurrent Neural Network Architectures for Large Scale Acoustic Modeling `_ + -公式如下: +.. role:: red -.. math:: +:red:`注意:在实现的时候为了提升效率,用户必须将输入先进行线性映射,将维度为 [T, hidden_size] 的输入映射为 [T, 4×hidden_size] 输入,然后再传给该OP。` - i_t & = \sigma(W_{ix}x_{t} + W_{ir}r_{t-1} + W_{ic}c_{t-1} + b_i)\\ - f_t & = \sigma(W_{fx}x_{t} + W_{fr}r_{t-1} + W_{fc}c_{t-1} + b_f)\\ - \tilde{c_t} & = act_g(W_{cx}x_t + W_{cr}r_{t-1} + b_c)\\ - o_t & = \sigma(W_{ox}x_{t} + W_{or}r_{t-1} + W_{oc}c_t + b_o)\\ - c_t & = f_t \odot c_{t-1} + i_t \odot \tilde{c_t}\\ - h_t & = o_t \odot act_h(c_t)\\ - r_t & = \overline{act_h}(W_{rh}h_t)\\ +该OP实现了LSTMP(LSTM Projected)层。LSTMP层在LSTM层之后有一个单独的的线性映射层。 -- `Sak, H., Senior, A., & Beaufays, F. (2014) `_。 +与标准的LSTM层相比,LSTMP多出来的线性映射层,用于从原始隐藏状态 :math:`h_t` 映射到较低维的状态 :math:`r_t`, +从而减少参数总数和计算复杂度,特别是输出单元相对较大的情况下。 -在以上公式中: - - :math:`W` : 代表权重矩阵(例如 :math:`W_{xi}` 是输入门道输入的权重矩阵) - - :math:`W_{ic}` , :math:`W_{fc}` , :math:`W_{oc}` : peephole connections的对角权重矩阵。在我们的实现中,外面用向量代表这些对角权重矩阵 - - :math:`b` : 代表偏差向量(例如 :math:`b_{i}` 是输入偏差向量) - - :math:`\delta` : 激活函数,比如逻辑回归函数 - - :math:`i,f,o` 和 :math:`c` :分别代表输入门,遗忘门,输出门和cell激活函数向量,四者的大小和cell输出激活函数向量 :math:`h` 的四者大小相等 - - :math:`h` : 隐藏状态 - - :math:`r` : 隐藏状态的循环映射 - - :math:`\tilde{c_t}` : 候选隐藏状态 - - :math:`\odot` : 向量的元素状态生成 - - :math:`act_g` 和 :math:`act_h` : cell输入和cell输出激活函数,通常使用 :math:`tanh` - - :math:`\overline{act_h}` : 映射输出的激活函数,通常用 :math:`identity` 或等同的 :math:`act_h` +该OP的默认实现方式为 diagonal/peephole 连接,参见 `Gers, F. A., & Schmidhuber, J. (2000) `_。 +如果需要禁用 peephole 连接方法,将 use_peepholes 设为 False 即可。 -将 ``use_peepholes`` 设置为False,断开窥视孔连接(peephole connection)。在此省略公式,详情请参照论文 `LONG SHORT-TERM MEMORY `_ 。 +该OP对于序列中每一个时间步的计算公式如下: -注意输入 :math:`x_{t}` 中的 :math:`W_{xi}x_{t},W_{xf}x_{t},W_{xc}x_{t},W_{xo}x_{t}` 不在此操作符中。用户选择在LSTMP层之前使用全链接层。 +.. math:: + i_t = \sigma(W_{ix}x_{t} + W_{ir}r_{t-1} + W_{ic}c_{t-1} + b_i) +.. math:: + f_t = \sigma(W_{fx}x_{t} + W_{fr}r_{t-1} + W_{fc}c_{t-1} + b_f) +.. math:: + o_t = \sigma(W_{ox}x_{t} + W_{or}r_{t-1} + W_{oc}c_{t-1} + b_o) +.. math:: + \widetilde{c_t} = act_g(W_{cx}x_t + W_{cr}r_{t-1} + b_c) +.. math:: + c_t = f_t \odot c_{t-1} + i_t \odot \widetilde{c_t} +.. math:: + h_t = o_t \odot act_h(c_t) +.. math:: + r_t = \overline{act_h}(W_{rh}h_t) + + +公式中的概念信息如下: + - :math:`x_{t}` 表示时间步 :math:`t` 的输入 + - :math:`h_{t}` 表示时间步 :math:`t` 的 hidden 状态 + - :math:`r_{t}` : 隐藏状态循环的映射输出的状态 + - :math:`h_{t-1}, c_{t-1}, r_{t-1}` 分别表示前一个时间步的 hidden 状态,cell 状态和循环映射输出状态 + - :math:`\widetilde{c_t}` 表示候选的 cell 状态 + - :math:`i_t` ,:math:`f_t` 和 :math:`o_t` 分别为 input gate,forget gate,output gate + - :math:`W` 表示 weight (例如, :math:`W_{ix}` 是在计算 input gate :math:`i_t` 时,对输入 :math:`x_{t}` 做线性变换的 weight) + - :math:`b` 表示 bias (例如, :math:`b_{i}` 是 input gate 的 bias) + - :math:`\sigma` 表示 gate 的非线性激活函数,默认为 sigmoid + - :math:`act_g, act_h, \overline{act_h}` 分别表示 cell 输入 cell 输出和映射输出的非线性激活函数,默认为 tanh + - :math:`\odot` 表示矩阵的 Hadamard product,即对两个维度相同的矩阵,将相同位置的元素相乘,得到另一个维度相同的矩阵 参数: - - **input** (Variable) - dynamic_lstmp层的输入,支持输入序列长度为变量的倍数。该变量的张量为一个矩阵,维度为(T X 4D),T为mini-batch的总时间步长,D是隐藏大小。 - - **size** (int) - 4*隐藏状态大小(hidden size) - - **proj_size** (int) - 投影输出的大小 - - **param_attr** (ParamAttr|None) - 可学习hidden-hidden权重和投影权重的参数属性。 - 说明: - - Hidden-hidden (隐藏状态到隐藏状态)权重 = :math:`\{ W_{ch},W_{ih},W_{fh},W_{oh} \}` - - hidden-hidden权重的权重矩阵为(P*4D),P是投影大小,D是隐藏大小。 - - 投影(Projection)权重 = :math:`\{ W_{rh} \}` - - 投影权重的shape为(D\*P) - - 如果设为None或者ParamAttr的一个属性,dynamic_lstm将创建ParamAttr为param_attr。如果param_attr的初始函数未设置,参数则初始化为Xavier。默认:None。 - - **bias_attr** (ParamAttr|None) - 可学习bias权重的bias属性,包含输入隐藏的bias权重和窥视孔连接权重(peephole connection),前提是use_peepholes设为True。 - - 说明: - 1.use_peepholes = False - - Biases = { :math:`b_{c},b_{i},b_{f},b_{o}`}. - - 维度为(1*4D) - - 2.use_peepholes = True - - Biases = { :math:`b_{c},b_{i},b_{f},b_{o},W_{ic},W_{fc},W_{oc}`} - - 维度为(1*7D) - - 如果设置为None或者ParamAttr的一个属性,dynamic_lstm将创建ParamAttr为bias_attr。bias_attr的初始函数未设置,bias则初始化为0.默认:None。 - - - **use_peepholes** (bool) - 是否开启诊断/窥视孔链接,默认为True。 - - **is_reverse** (bool) - 是否计算反向LSTM,默认为False。 - - **gate_activation** (bool) - 输入门(input gate)、遗忘门(forget gate)和输出门(output gate)的激活函数。Choices = [“sigmoid”,“tanh”,“relu”,“identity”],默认“sigmoid”。 - - **cell_activation** (str) - cell输出的激活函数。Choices = [“sigmoid”,“tanh”,“relu”,“identity”],默认“tanh”。 - - **candidate_activation** (str) - 候选隐藏状态(candidate hidden state)的激活状态。Choices = [“sigmoid”,“tanh”,“relu”,“identity”],默认“tanh”。 - - **proj_activation** (str) - 投影输出的激活函数。Choices = [“sigmoid”,“tanh”,“relu”,“identity”],默认“tanh”。 - - **dtype** (str) - 数据类型。Choices = [“float32”,“float64”],默认“float32”。 - - **name** (str|None) - 该层名称(可选)。若设为None,则自动为该层命名。 - - **h_0** (Variable) - 初始隐藏状态是可选输入,默认为0。这是一个具有形状的张量(N x D),其中N是批大小,D是投影大小。 - - **c_0** (Variable) - 初始cell状态是可选输入,默认为0。这是一个具有形状(N x D)的张量,其中N是批大小。h_0和c_0可以为空,但只能同时为空。 - - **cell_clip** (float) - 如果提供该参数,则在单元输出激活之前,单元状态将被此值剪裁。 - - **proj_clip** (float) - 如果 num_proj > 0 并且 proj_clip 被提供,那么将投影值沿元素方向剪切到[-proj_clip,proj_clip]内 - -返回:含有两个输出变量的元组,隐藏状态(hidden state)的投影和LSTMP的cell状态。投影的shape为(T*P),cell state的shape为(T*D),两者的LoD和输入相同。 - -返回类型:元组(tuple) + - **input** ( :ref:`api_guide_Variable` ) 维度为 :math:`[T, 4*hidden\_size]` 的多维 LoDTensor(必须在传入该OP前对维度为 :math:`[T, hidden\_size]` 的输入经过线性变换得到),其中 T 为 batch 中所有样本的长度之和,hidden_size 为隐层大小,数据类型为 float32 或者 float64。 + - **size** (int) – 必须为 4 * hidden_size。 + - **proj_size** (int) - 投影映射输出的大小。 + - **param_attr** (ParamAttr,可选) - 指定权重参数属性的对象。默认值为None,表示使用默认的权重参数属性。具体用法请参见 :ref:`cn_api_fluid_ParamAttr` 。 + + 说明: + 1. 隐藏状态到隐藏状态(Hidden-hidden)权重 = :math:`\{ W_{cr},W_{ir},W_{fr},W_{or} \}`,维度为 [P, 4*hidden_size] ,P是投影大小 + + 2. 投影(Projection)权重 = :math:`\{ W_{rh} \}`,维度为 [D, P] + + - **bias_attr** (ParamAttr,可选) - 指定偏置参数属性的对象。默认值为None,表示使用默认的偏置参数属性。具体用法请参见 :ref:`cn_api_fluid_ParamAttr` 。 + + 说明: + 1. use_peepholes = False + - Biases = { :math:`b_{c},b_{i},b_{f},b_{o}`} + - 维度为 [1, 4*hidden_size] + + 2. use_peepholes = True + - Biases = { :math:`b_{c},b_{i},b_{f},b_{o},W_{ic},W_{fc},W_{oc}`} + - 维度为 [1, 7*hidden_size] + + - **use_peepholes** (bool,可选) - 是否使用 peephole 连接。默认值为True。 + - **is_reverse** (bool,可选) - 是否计算反向LSTM,默认值为False。 + - **gate_activation** (str,可选) - 应用于input gate,forget gate, output gate 的激活函数。可选值包括 sigmoid,tanh,relu,identity。默认值为 sigmoid。 + - **cell_activation** (str,可选) - cell输出的激活函数。可选值包括 sigmoid,tanh,relu,identity。默认值为 tanh。 + - **candidate_activation** (str,可选) - 候选隐藏状态(candidate hidden state)的激活状态。可选值包括 sigmoid,tanh,relu,identity。默认值为 tanh。 + - **proj_activation** (str,可选) - 投影输出的激活函数。可选值包括 sigmoid,tanh,relu,identity。默认值为 tanh。 + - **dtype** (str,可选) - 数据类型。可选值包括 float32,float64。默认值为 float32。 + - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name` ,一般无需设置,默认值为None。 + - **h_0** ( :ref:`api_guide_Variable` ,可选) 维度为 :math:`[batch\_size, hidden\_size]` 的多维 Tensor。如果为 None,该OP会自动设置为全0的向量。默认值为None。 + - **c_0** ( :ref:`api_guide_Variable` ,可选) 维度为 :math:`[batch\_size, hidden\_size]` 的多维 Tensor。如果为 None,该OP会自动设置为全0的向量;:math:`h_0, c_0` 如果要设置为None,必须同时为None。默认值为None。 + - **cell_clip** (float,可选) - 如果该参数不为None,则在单元输出激活之前,单元状态将被此值剪裁。默认值为None。 + - **proj_clip** (float,可选) - 如果 num_proj > 0 并且 proj_clip 不为None,那么将投影值沿元素方向剪切到[-proj_clip,proj_clip]内。默认值为None。 + +返回:经过lstmp运算输出的 hidden 的映射和 cell 状态的tuple,包括 + +- hidden:LSTM hidden的输出结果,维度为 :math:`[T, P]` 的LoDTensor,且LoD保持与输入一致,数据类型与input一致。 +- cell:LSTM cell的输出结果,维度为 :math:`[T, hidden\_size]` 的LoDTensor,且LoD保持与输入一致,数据类型与input一致。 + +返回类型: tuple( :ref:`api_guide_Variable` , :ref:`api_guide_Variable` ) **代码示例**: -.. code-block:: python +.. code-block:: python import paddle.fluid as fluid dict_dim, emb_dim = 128, 64 data = fluid.layers.data(name='sequence', shape=[1], - dtype='int32', lod_level=1) + dtype='int32', lod_level=1) emb = fluid.layers.embedding(input=data, size=[dict_dim, emb_dim]) hidden_dim, proj_dim = 512, 256 fc_out = fluid.layers.fc(input=emb, size=hidden_dim * 4, - act=None, bias_attr=None) - proj_out, _ = fluid.layers.dynamic_lstmp(input=fc_out, - size=hidden_dim * 4, - proj_size=proj_dim, - use_peepholes=False, - is_reverse=True, - cell_activation="tanh", - proj_activation="tanh") + act=None, bias_attr=None) + proj_out, cell = fluid.layers.dynamic_lstmp(input=fc_out, + size=hidden_dim * 4, + proj_size=proj_dim, + use_peepholes=False, + is_reverse=True, + cell_activation="tanh", + proj_activation="tanh") + proj_out.shape # (-1, 256) + cell.shape # (-1, 512) + diff --git a/doc/fluid/api_cn/layers_cn/lstm_cn.rst b/doc/fluid/api_cn/layers_cn/lstm_cn.rst index 8b60cdfc8..8eff06d25 100644 --- a/doc/fluid/api_cn/layers_cn/lstm_cn.rst +++ b/doc/fluid/api_cn/layers_cn/lstm_cn.rst @@ -5,52 +5,66 @@ lstm .. py:function:: paddle.fluid.layers.lstm(input, init_h, init_c, max_len, hidden_size, num_layers, dropout_prob=0.0, is_bidirec=False, is_test=False, name=None, default_initializer=None, seed=-1) -如果您的设备是GPU,本op将使用cudnn LSTM实现 +.. raw:: html -一个没有 peephole 连接的四门长短期记忆网络。在前向传播中,给定迭代的输出ht和单元输出ct可由递归输入ht-1、单元输入ct-1和上一层输入xt计算,给定矩阵W、R和bias bW, bR由下式计算: + -.. math:: +.. role:: red + +:red:`注意:该OP仅支持 GPU 设备运行` - i_t &= \sigma(W_{ix}x_{t} + W_{ih}h_{t-1} + bx_i + bh_i)\\ - f_t &= \sigma(W_{fx}x_{t} + W_{fh}h_{t-1} + bx_f + bh_f)\\ - o_t &= \sigma(W_{ox}x_{t} + W_{oh}h_{t-1} + bx_o + bh_o)\\ - \tilde{c_t} &= tanh(W_{cx}x_t + W_{ch}h_{t-1} + bx_c + bh_c)\\ - c_t &= f_t \odot c_{t-1} + i_t \odot \tilde{c_t}\\ - h_t &= o_t \odot tanh(c_t) +该OP实现了 LSTM,即 Long-Short Term Memory(长短期记忆)运算 - `Hochreiter, S., & Schmidhuber, J. (1997) `_。 -公式中: - - W 项表示权重矩阵(e.g. :math:`W_{ix}` 是从输入门到输入的权重矩阵) - - b 项表示偏差向量( :math:`b_{xi}` 和 :math:`b_{hi}` 是输入门的偏差向量) - - sigmoid 是 logistic sigmoid 函数 - - i、f、o、c 分别为输入门、遗忘门、输出门和激活向量,它们的大小与 cell 输出激活向量h相同。 - - :math:`\odot` 是向量的元素乘积 - - tanh是激活函数 - - :math:`\tilde{c_t}` 也称为候选隐藏状态,它是根据当前输入和之前的隐藏状态来计算的 +该OP的实现不包括 diagonal/peephole 连接,参见 `Gers, F. A., & Schmidhuber, J. (2000) `_。 +如果需要使用 peephole 连接方法,请使用 :ref:`cn_api_fluid_layers_dynamic_lstm` 。 -sigmoid的计算公式为: :math:`sigmoid(x) = 1 / (1 + e^{-x})` 。 +该OP对于序列中每一个时间步的计算公式如下: +.. math:: + i_t = \sigma(W_{ix}x_{t} + W_{ih}h_{t-1} + b_{x_i} + b_{h_i}) +.. math:: + f_t = \sigma(W_{fx}x_{t} + W_{fh}h_{t-1} + b_{x_f} + b_{h_f}) +.. math:: + o_t = \sigma(W_{ox}x_{t} + W_{oh}h_{t-1} + b_{x_o} + b_{h_o}) +.. math:: + \widetilde{c_t} = tanh(W_{cx}x_t + W_{ch}h_{t-1} + b{x_c} + b_{h_c}) +.. math:: + c_t = f_t \odot c_{t-1} + i_t \odot \widetilde{c_t} +.. math:: + h_t = o_t \odot tanh(c_t) + +公式中的概念信息如下: + - :math:`x_{t}` 表示时间步 :math:`t` 的输入 + - :math:`h_{t}` 表示时间步 :math:`t` 的 hidden 状态 + - :math:`h_{t-1}, c_{t-1}` 分别表示前一个时间步的 hidden 和 cell 状态 + - :math:`\widetilde{c_t}` 表示候选的 cell 状态 + - :math:`i_t` ,:math:`f_t` 和 :math:`o_t` 分别为 input gate,forget gate,output gate + - :math:`W` 表示 weight (例如, :math:`W_{ix}` 是在计算 input gate :math:`i_t` 时,对输入 :math:`x_{t}` 做线性变换的 weight) + - :math:`b` 表示 bias (例如, :math:`b_{i}` 是 input gate 的 bias) + - :math:`\sigma` 表示 gate 的非线性激活函数,默认为 sigmoid + - :math:`\odot` 表示矩阵的 Hadamard product,即对两个维度相同的矩阵,将相同位置的元素相乘,得到另一个维度相同的矩阵 参数: - - **input** (Variable) - LSTM 输入张量,形状必须为(seq_len x,batch_size,x,input_size) - - **init_h** (Variable) – LSTM的初始隐藏状态,是一个有形状的张量(num_layers,x,batch_size,x,hidden_size)如果is_bidirec = True,形状应该是(num_layers*2,x, batch_size, x, hidden_size) - - **init_c** (Variable) - LSTM的初始状态。这是一个有形状的张量(num_layers, x, batch_size, x, hidden_size)如果is_bidirec = True,形状应该是(num_layers*2, x, batch_size, x, hidden_size) - - **max_len** (int) – LSTM的最大长度。输入张量的第一个 dim 不能大于max_len - - **hidden_size** (int) - LSTM的隐藏大小 - - **num_layers** (int) – LSTM的总层数 - - **dropout_prob** (float|0.0) – dropout prob,dropout 只在 rnn 层之间工作,而不是在时间步骤之间。dropout 不作用于最后的 rnn 层的 rnn 输出中 - - **is_bidirec** (bool) – 是否是双向的 - - **is_test** (bool) – 是否在测试阶段 - - **name** (str|None) - 此层的名称(可选)。如果没有设置,该层将被自动命名。 - - **default_initializer** (Initialize|None) – 在哪里使用初始化器初始化权重,如果没有设置,将进行默认初始化。 - - **seed** (int) – LSTM中dropout的Seed,如果是-1,dropout将使用随机Seed - -返回: 三个张量, rnn_out, last_h, last_c: - -- rnn_out为LSTM hidden的输出结果。形为(seq_len x batch_size x hidden_size)如果 ``is_bidirec`` 设置为True,则形为(seq_len x batch_sze hidden_size * 2) -- last_h(Tensor): LSTM最后一步的隐藏状态,形状为(num_layers x batch_size x hidden_size);如果 ``is_bidirec`` 设置为True,形状为(num_layers*2 x batch_size x hidden_size) -- last_c(Tensor): LSTM最后一步的cell状态,形状为(num_layers x batch_size x hidden_size);如果 ``is_bidirec`` 设置为True,形状为(num_layers*2 x batch_size x hidden_size) - -返回类型: rnn_out(Tensor),last_h(Tensor),last_c(Tensor) + - **input** ( :ref:`api_guide_Variable` ) - LSTM的输入张量,维度为 :math:`[batch\_size, seq\_len, input\_dim]` 的 3-D Tensor,其中 seq_len 为序列的长度, input_dim 为序列词嵌入的维度。数据类型为 float32 或者 float64。 + - **init_h** ( :ref:`api_guide_Variable` ) – LSTM的初始 hidden 状态,维度为 :math:`[num\_layers, batch\_size, hidden\_size]` 的 3-D Tensor,其中 num_layers 是LSTM的总层数,hidden_size 是隐层维度。 如果is_bidirec = True, 维度应该为 :math:`[num\_layers*2, batch\_size, hidden\_size]` 。数据类型为 float32 或者 float64。 + - **init_c** ( :ref:`api_guide_Variable` ) - LSTM的初始 cell 状态。维度为 :math:`[num\_layers, batch\_size, hidden\_size]` 的 3-D Tensor,其中 num_layers 是LSTM的总层数,hidden_size 是隐层维度。 如果is_bidirec = True, 维度应该为 :math:`[num\_layers*2, batch\_size, hidden\_size]` 。数据类型为 float32 或者 float64。 + - **max_len** (int) – LSTM的最大长度。输入张量的第一个 input_dim 不能大于 max_len。 + - **hidden_size** (int) - LSTM hidden 状态的维度。 + - **num_layers** (int) – LSTM的总层数。例如,该参数设置为2,则会堆叠两个LSTM,其第一个LSTM的输出会作为第二个LSTM的输入。 + - **dropout_prob** (float,可选) – dropout比例,dropout 只在 rnn 层之间工作,而不是在时间步骤之间。dropout 不作用于最后的 rnn 层的 rnn 输出中。默认值为 0.0。 + - **is_bidirec** (bool,可选) – 是否是双向的LSTM。默认值为 False。 + - **is_test** (bool,可选) – 是否在测试阶段。默认值为 False。 + - **name** (str,可选) - 具体用法请参见 :ref:`api_guide_Name` ,一般无需设置,默认值为None。 + - **default_initializer** (Initializer,可选) – 用于初始化权重的初始化器,如果为None,将进行默认初始化。默认值为 None。 + - **seed** (int,可选) – LSTM中dropout的seed,如果是-1,dropout将使用随机seed。默认值为 1。 + +返回: 经过lstm运算输出的三个Tensor的tuple,包括 + +- rnn_out:LSTM hidden的输出结果的Tensor,数据类型与input一致,维度为 :math:`[seq\_len, batch\_size, hidden\_size]` 。如果 ``is_bidirec`` 设置为True,则维度为 :math:`[seq\_len, batch\_size, hidden\_size*2]` +- last_h:LSTM最后一步的hidden状态的Tensor,数据类型与input一致,维度为 :math:`[num\_layers, batch\_size, hidden\_size]` 。如果 ``is_bidirec`` 设置为True,则维度为 :math:`[num\_layers*2, batch\_size, hidden\_size]` +- last_c:LSTM最后一步的cell状态的Tensor,数据类型与input一致,维度为 :math:`[num\_layers, batch\_size, hidden\_size]` 。如果 ``is_bidirec`` 设置为True,则维度为 :math:`[num\_layers*2, batch\_size, hidden\_size]` + +返回类型: tuple( :ref:`api_guide_Variable` , :ref:`api_guide_Variable` , :ref:`api_guide_Variable` ) **代码示例:** @@ -67,13 +81,16 @@ sigmoid的计算公式为: :math:`sigmoid(x) = 1 / (1 + e^{-x})` 。 batch_size = 20 max_len = 100 dropout_prob = 0.2 - input_size = 100 + seq_len = 100 hidden_size = 150 num_layers = 1 init_h = layers.fill_constant( [num_layers, batch_size, hidden_size], 'float32', 0.0 ) init_c = layers.fill_constant( [num_layers, batch_size, hidden_size], 'float32', 0.0 ) rnn_out, last_h, last_c = layers.lstm(emb, init_h, init_c, max_len, hidden_size, num_layers, dropout_prob=dropout_prob) + rnn_out.shape # (-1, 100, 150) + last_h.shape # (1, 20, 150) + layt_c.shape # (1, 20, 150) -- GitLab