<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Recurrent Group教程 &mdash; PaddlePaddle  文档</title>
  

  
  

  

  
  
    

  

  
  
    <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  

  
  
        <link rel="index" title="索引"
              href="../../genindex.html"/>
        <link rel="search" title="搜索" href="../../search.html"/>
    <link rel="top" title="PaddlePaddle  文档" href="../../index.html"/>
        <link rel="up" title="RNN模型" href="index_cn.html"/>
        <link rel="next" title="支持双层序列作为输入的Layer" href="hierarchical_layer_cn.html"/>
        <link rel="prev" title="RNN配置" href="rnn_config_cn.html"/> 

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/css/perfect-scrollbar.min.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/override.css" type="text/css" />
  <script>
  var _hmt = _hmt || [];
  (function() {
    var hm = document.createElement("script");
    hm.src = "//hm.baidu.com/hm.js?b9a314ab40d04d805655aab1deee08ba";
    var s = document.getElementsByTagName("script")[0]; 
    s.parentNode.insertBefore(hm, s);
  })();
  </script>

  

  
  <script src="../../_static/js/modernizr.min.js"></script>

</head>

<body class="wy-body-for-nav" role="document">

  
  <header class="site-header">
    <div class="site-logo">
      <a href="/"><img src="../../_static/images/PP_w.png"></a>
    </div>
    <div class="site-nav-links">
      <div class="site-menu">
        <a class="fork-on-github" href="https://github.com/PaddlePaddle/Paddle" target="_blank"><i class="fa fa-github"></i>Fork me on Github</a>
        <div class="language-switcher dropdown">
          <a type="button" data-toggle="dropdown">
            <span>English</span>
            <i class="fa fa-angle-up"></i>
            <i class="fa fa-angle-down"></i>
          </a>
          <ul class="dropdown-menu">
            <li><a href="/doc_cn">中文</a></li>
            <li><a href="/doc">English</a></li>
          </ul>
        </div>
        <ul class="site-page-links">
          <li><a href="/">Home</a></li>
        </ul>
      </div>
      <div class="doc-module">
        
        <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../getstarted/index_cn.html">新手入门</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../build_and_install/index_cn.html">安装与编译</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../index_cn.html">进阶使用</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev/index_cn.html">开发标准</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../faq/index_cn.html">FAQ</a></li>
</ul>

        
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>        
      </div>
    </div>
  </header>
  
  <div class="main-content-wrap">

    
    <nav class="doc-menu-vertical" role="navigation">
        
          
          <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../getstarted/index_cn.html">新手入门</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../getstarted/quickstart_cn.html">快速开始</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../getstarted/concepts/use_concepts_cn.html">基本使用概念</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../build_and_install/index_cn.html">安装与编译</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../build_and_install/pip_install_cn.html">使用pip安装</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../build_and_install/docker_install_cn.html">使用Docker安装运行</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../build_and_install/build_from_source_cn.html">从源码编译</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="reference internal" href="../index_cn.html">进阶使用</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../cmd_parameter/index_cn.html">命令行参数设置</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../cmd_parameter/use_case_cn.html">使用案例</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cmd_parameter/arguments_cn.html">参数概述</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cmd_parameter/detail_introduction_cn.html">细节描述</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../cluster/index_cn.html">分布式训练</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../cluster/preparations_cn.html">环境准备</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cluster/cmd_argument_cn.html">启动参数说明</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cluster/multi_cluster/index_cn.html">在不同集群中运行</a><ul>
<li class="toctree-l4"><a class="reference internal" href="../cluster/multi_cluster/k8s_cn.html">Kubernetes单机训练</a></li>
<li class="toctree-l4"><a class="reference internal" href="../cluster/multi_cluster/k8s_distributed_cn.html">Kubernetes分布式训练</a></li>
<li class="toctree-l4"><a class="reference internal" href="../cluster/multi_cluster/openmpi_cn.html">在OpenMPI集群中启动训练</a></li>
<li class="toctree-l4"><a class="reference internal" href="../cluster/multi_cluster/fabric_cn.html">使用fabric启动集群训练</a></li>
<li class="toctree-l4"><a class="reference internal" href="../cluster/multi_cluster/k8s_aws_cn.html">Kubernetes on AWS</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../capi/index_cn.html">C-API预测库</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../capi/compile_paddle_lib_cn.html">安装与编译C-API预测库</a></li>
<li class="toctree-l3"><a class="reference internal" href="../capi/organization_of_the_inputs_cn.html">输入/输出数据组织</a></li>
<li class="toctree-l3"><a class="reference internal" href="../capi/workflow_of_capi_cn.html">C-API使用流程</a></li>
</ul>
</li>
<li class="toctree-l2 current"><a class="reference internal" href="index_cn.html">RNN模型</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="rnn_config_cn.html">RNN配置</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Recurrent Group教程</a></li>
<li class="toctree-l3"><a class="reference internal" href="hierarchical_layer_cn.html">支持双层序列作为输入的Layer</a></li>
<li class="toctree-l3"><a class="reference internal" href="hrnn_rnn_api_compare_cn.html">单双层RNN API对比介绍</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../optimization/gpu_profiling_cn.html">GPU性能调优</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../dev/index_cn.html">开发标准</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../dev/contribute_to_paddle_cn.html">如何贡献代码</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../dev/write_docs_cn.html">如何贡献文档</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../faq/index_cn.html">FAQ</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../../faq/build_and_install/index_cn.html">编译安装与单元测试</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../faq/model/index_cn.html">模型配置</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../faq/parameter/index_cn.html">参数设置</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../faq/local/index_cn.html">本地训练与预测</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../faq/cluster/index_cn.html">集群训练与预测</a></li>
</ul>
</li>
</ul>

        
    </nav>
    
    <section class="doc-content-wrap">

      

 







<div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
      
        <li><a href="../index_cn.html">进阶使用</a> > </li>
      
        <li><a href="index_cn.html">RNN模型</a> > </li>
      
    <li>Recurrent Group教程</li>
  </ul>
</div>
      
      <div class="wy-nav-content" id="doc-content">
        <div class="rst-content">
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="section" id="recurrent-group">
<span id="recurrent-group"></span><h1>Recurrent Group教程<a class="headerlink" href="#recurrent-group" title="永久链接至标题">¶</a></h1>
<div class="section" id="">
<span id="id1"></span><h2>概述<a class="headerlink" href="#" title="永久链接至标题">¶</a></h2>
<p>序列数据是自然语言处理任务面对的一种主要输入数据类型。</p>
<p>一句话是由词语构成的序列,多句话进一步构成了段落。因此,段落可以看作是一个嵌套的双层的序列,这个序列的每个元素又是一个序列。</p>
<p>双层序列是PaddlePaddle支持的一种非常灵活的数据组织方式,帮助我们更好地描述段落、多轮对话等更为复杂的语言数据。基于双层序列输入,我们可以设计搭建一个灵活的、层次化的RNN,分别从词语和句子级别编码输入数据,同时也能够引入更加复杂的记忆机制,更好地完成一些复杂的语言理解任务。</p>
<p>在PaddlePaddle中,<code class="docutils literal"><span class="pre">recurrent_group</span></code>是一种任意复杂的RNN单元,用户只需定义RNN在一个时间步内完成的计算,PaddlePaddle负责完成信息和误差在时间序列上的传播。</p>
<p>更进一步,<code class="docutils literal"><span class="pre">recurrent_group</span></code>同样可以扩展到双层序列的处理上。通过两个嵌套的<code class="docutils literal"><span class="pre">recurrent_group</span></code>分别定义子句级别和词语级别上需要完成的运算,最终实现一个层次化的复杂RNN。</p>
<p>目前,在PaddlePaddle中,能够对双向序列进行处理的有<code class="docutils literal"><span class="pre">recurrent_group</span></code>和部分Layer,具体可参考文档:<a href = "hierarchical_layer_cn.html">支持双层序列作为输入的Layer</a>。</p>
</div>
<div class="section" id="">
<span id="id2"></span><h2>相关概念<a class="headerlink" href="#" title="永久链接至标题">¶</a></h2>
<div class="section" id="">
<span id="id3"></span><h3>基本原理<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal"><span class="pre">recurrent_group</span></code> 是PaddlePaddle支持的一种任意复杂的RNN单元。使用者只需要关注于设计RNN在一个时间步之内完成的计算,PaddlePaddle负责完成信息和梯度在时间序列上的传播。</p>
<p>PaddlePaddle中,<code class="docutils literal"><span class="pre">recurrent_group</span></code>的一个简单调用如下:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">recurrent_group</span><span class="p">(</span><span class="n">step</span><span class="p">,</span> <span class="nb">input</span><span class="p">,</span> <span class="n">reverse</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>step:一个可调用的函数,定义一个时间步之内RNN单元完成的计算</li>
<li>input:输入,必须是一个单层序列,或者一个双层序列</li>
<li>reverse:是否以逆序处理输入序列</li>
</ul>
<p>使用<code class="docutils literal"><span class="pre">recurrent_group</span></code>的核心是设计step函数的计算逻辑。step函数内部可以自由组合PaddlePaddle支持的各种layer,完成任意的运算逻辑。<code class="docutils literal"><span class="pre">recurrent_group</span></code> 的输入(即input)会成为step函数的输入,由于step 函数只关注于RNN一个时间步之内的计算,在这里<code class="docutils literal"><span class="pre">recurrent_group</span></code>替我们完成了原始输入数据的拆分。</p>
</div>
<div class="section" id="">
<span id="id4"></span><h3>输入<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal"><span class="pre">recurrent_group</span></code>处理的输入序列主要分为以下三种类型:</p>
<ul class="simple">
<li><strong>数据输入</strong>:一个双层序列进入<code class="docutils literal"><span class="pre">recurrent_group</span></code>会被拆解为一个单层序列,一个单层序列进入<code class="docutils literal"><span class="pre">recurrent_group</span></code>会被拆解为非序列,然后交给step函数,这一过程对用户是完全透明的。可以有以下两种:1)通过data_layer拿到的用户输入;2)其它layer的输出。</li>
<li><strong>只读Memory输入</strong>:<code class="docutils literal"><span class="pre">StaticInput</span></code> 定义了一个只读的Memory,由<code class="docutils literal"><span class="pre">StaticInput</span></code>指定的输入不会被<code class="docutils literal"><span class="pre">recurrent_group</span></code>拆解,<code class="docutils literal"><span class="pre">recurrent_group</span></code> 循环展开的每个时间步总是能够引用所有输入,可以是一个非序列,或者一个单层序列。</li>
<li><strong>序列生成任务的输入</strong>:<code class="docutils literal"><span class="pre">GeneratedInput</span></code>只用于在序列生成任务中指定输入数据。</li>
</ul>
</div>
<div class="section" id="">
<span id="id5"></span><h3>输入示例<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p>序列生成任务大多遵循encoder-decoer架构,encoder和decoder可以是能够处理序列的任意神经网络单元,而RNN是最流行的选择。</p>
<p>给定encoder输出和当前词,decoder每次预测产生下一个最可能的词语。在这种结构中,decoder接受两个输入:</p>
<ul class="simple">
<li>要生成的目标序列:是decoder的数据输入,也是decoder循环展开的依据,<code class="docutils literal"><span class="pre">recurrent_group</span></code>会对这类输入进行拆解。</li>
<li>encoder输出,可以是一个非序列,或者一个单层序列:是一个unbounded memory,decoder循环展开的每一个时间步会引用全部结果,不应该被拆解,这种类型的输入必须通过<code class="docutils literal"><span class="pre">StaticInput</span></code>指定。关于Unbounded Memory的更多讨论请参考论文 <a class="reference external" href="https://arxiv.org/abs/1410.5401">Neural Turning Machine</a>。</li>
</ul>
<p>在序列生成任务中,decoder RNN总是引用上一时刻预测出的词的词向量,作为当前时刻输入。<code class="docutils literal"><span class="pre">GeneratedInput</span></code>自动完成这一过程。</p>
</div>
<div class="section" id="">
<span id="id6"></span><h3>输出<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal"><span class="pre">step</span></code>函数必须返回一个或多个Layer的输出,这个Layer的输出会作为整个<code class="docutils literal"><span class="pre">recurrent_group</span></code> 最终的输出结果。在输出的过程中,<code class="docutils literal"><span class="pre">recurrent_group</span></code> 会将每个时间步的输出拼接,这个过程对用户也是透明的。</p>
</div>
<div class="section" id="memory">
<span id="memory"></span><h3>memory<a class="headerlink" href="#memory" title="永久链接至标题">¶</a></h3>
<p>memory只能在<code class="docutils literal"><span class="pre">recurrent_group</span></code>中定义和使用。memory不能独立存在,必须指向一个PaddlePaddle定义的Layer。引用memory得到这layer上一时刻输出,因此,可以将memory理解为一个时延操作。</p>
<p>可以显示地指定一个layer的输出用于初始化memory。不指定时,memory默认初始化为0。</p>
</div>
</div>
<div class="section" id="rnn">
<span id="rnn"></span><h2>双层RNN介绍<a class="headerlink" href="#rnn" title="永久链接至标题">¶</a></h2>
<p><code class="docutils literal"><span class="pre">recurrent_group</span></code>帮助我们完成对输入序列的拆分,对输出的合并,以及计算逻辑在序列上的循环展开。</p>
<p>利用这种特性,两个嵌套的<code class="docutils literal"><span class="pre">recurrent_group</span></code>能够处理双层序列,实现词语和句子两个级别的双层RNN结构。</p>
<ul class="simple">
<li>单层(word-level)RNN:每个状态(state)对应一个词(word)。</li>
<li>双层(sequence-level)RNN:一个双层RNN由多个单层RNN组成,每个单层RNN(即双层RNN的每个状态)对应一个子句(subseq)。</li>
</ul>
<p>为了描述方便,下文以NLP任务为例,将含有子句(subseq)的段落定义为一个双层序列,将含有词语的句子定义为一个单层序列,那么0层序列即为一个词语。</p>
</div>
<div class="section" id="rnn">
<span id="id7"></span><h2>双层RNN的使用<a class="headerlink" href="#rnn" title="永久链接至标题">¶</a></h2>
<div class="section" id="">
<span id="id8"></span><h3>训练流程的使用方法<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p>使用 <code class="docutils literal"><span class="pre">recurrent_group</span></code>需要遵循以下约定:</p>
<ul class="simple">
<li><strong>单进单出</strong>:输入和输出都是单层序列。<ul>
<li>如果有多个输入,不同输入序列含有的词语数必须严格相等。</li>
<li>输出一个单层序列,输出序列的词语数和输入序列一致。</li>
<li>memory:在step函数中定义 memory指向一个layer,通过引用memory得到这个layer上一个时刻输出,形成recurrent 连接。memory的is_seq参数必须为false。如果没有定义memory,每个时间步之内的运算是独立的。</li>
<li>boot_layer:memory的初始状态,默认初始状为0,memory的is_seq参数必须为false。</li>
</ul>
</li>
<li><strong>双进双出</strong>:输入和输出都是双层序列。<ul>
<li>如果有多个输入序列,不同输入含有的子句(subseq)数必须严格相等,但子句含有的词语数可以不相等。</li>
<li>输出一个双层序列,子句(subseq)数、子句的单词数和指定的一个输入序列一致,默认为第一个输入。</li>
<li>memory:在step函数中定义memory,指向一个layer,通过引用memory得到这个layer上一个时刻的输出,形成recurrent连接。定义在外层<code class="docutils literal"><span class="pre">recurrent_group</span></code> step函数中的memory,能够记录上一个subseq 的状态,可以是一个单层序列(只作为read-only memory),也可以是一个词语。如果没有定义memory,那么 subseq 之间的运算是独立的。</li>
<li>boot_layer:memory 初始状态,可以是一个单层序列(只作为read-only memory)或一个向量。默认不设置,即初始状态为0。</li>
</ul>
</li>
<li><strong>双进单出</strong>:目前还未支持,会报错&#8221;In hierachical RNN, all out links should be from sequences now&#8221;。</li>
</ul>
</div>
<div class="section" id="">
<span id="id9"></span><h3>生成流程的使用方法<a class="headerlink" href="#" title="永久链接至标题">¶</a></h3>
<p>使用<code class="docutils literal"><span class="pre">beam_search</span></code>需要遵循以下约定:</p>
<ul class="simple">
<li>单层RNN:从一个word生成下一个word。</li>
<li>双层RNN:即把单层RNN生成后的subseq给拼接成一个新的双层seq。从语义上看,也不存在一个subseq直接生成下一个subseq的情况。</li>
</ul>
</div>
</div>
</div>


           </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="hierarchical_layer_cn.html" class="btn btn-neutral float-right" title="支持双层序列作为输入的Layer" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="rnn_config_cn.html" class="btn btn-neutral" title="RNN配置" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <p>
        &copy; Copyright 2016, PaddlePaddle developers.

    </p>
  </div>
  Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 

</footer>

        </div>
      </div>

    </section>

  </div>
  


  

    <script type="text/javascript">
        var DOCUMENTATION_OPTIONS = {
            URL_ROOT:'../../',
            VERSION:'',
            COLLAPSE_INDEX:false,
            FILE_SUFFIX:'.html',
            HAS_SOURCE:  true,
            SOURCELINK_SUFFIX: ".txt",
        };
    </script>
      <script type="text/javascript" src="../../_static/jquery.js"></script>
      <script type="text/javascript" src="../../_static/underscore.js"></script>
      <script type="text/javascript" src="../../_static/doctools.js"></script>
      <script type="text/javascript" src="../../_static/translations.js"></script>
      <script type="text/javascript" src="https://cdn.bootcss.com/mathjax/2.7.0/MathJax.js"></script>
       
  

  
  
    <script type="text/javascript" src="../../_static/js/theme.js"></script>
  
  
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/js/perfect-scrollbar.jquery.min.js"></script>
  <script src="../../_static/js/paddle_doc_init.js"></script> 

</body>
</html>