提交 6a094aac 编写于 作者: T Travis CI

Deploy to GitHub Pages: 29603cf3

上级 aa798ba1
......@@ -211,3 +211,49 @@ decoder_inputs = paddle.layer.fc(
* list 中元素的个数等于网络中输出层的个数;
* list 中每个元素是一个layer的输出结果矩阵,类型是numpy的ndarray;
* 每一个layer输出矩阵的高度,在非序列输入时:等于样本数;序列输入时等于:输入序列中元素的总数;宽度等于配置中layer的size;
6. 如何在训练过程中获得某一个layer的output
-----------------------------------------------
可以在event_handler中,通过 :code:`event.gm.getLayerOutputs("layer_name")` 获得在模型配置中某一层的name :code:`layer_name` 在当前
mini-batch forward的output的值。获得的值类型均为 :code:`numpy.ndarray` ,可以通过这个输出来完成自定义的评估指标计算等功能。例如下面代码:
.. code-block:: python
def score_diff(right_score, left_score):
return np.average(np.abs(right_score - left_score))
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if event.batch_id % 25 == 0:
diff = score_diff(
event.gm.getLayerOutputs("right_score")["right_score"][
"value"],
event.gm.getLayerOutputs("left_score")["left_score"][
"value"])
logger.info(("Pass %d Batch %d : Cost %.6f, "
"average absolute diff scores: %.6f") %
(event.pass_id, event.batch_id, event.cost, diff))
注意:此方法不能获取 :code:`paddle.layer.recurrent_group` 里step的内容,但可以获取 :code:`paddle.layer.recurrent_group` 的输出。
7. 如何在训练过程中获得参数的权重和梯度
-----------------------------------------------
在某些情况下,获得当前mini-batch的权重(或称作weights, parameters)有助于在训练时观察具体数值,方便排查以及快速定位问题。
可以通过在 :code:`event_handler` 中打印其值(注意,需要使用 :code:`paddle.event.EndForwardBackward` 保证使用GPU训练时也可以获得),
示例代码如下:
.. code-block:: python
...
parameters = paddle.parameters.create(cost)
...
def event_handler(event):
if isinstance(event, paddle.event.EndForwardBackward):
if event.batch_id % 25 == 0:
for p in parameters.keys():
logger.info("Param %s, Grad %s",
parameters.get(p), parameters.get_grad(p))
注意:“在训练过程中获得某一个layer的output”和“在训练过程中获得参数的权重和梯度”都会造成训练中的数据从C++拷贝到numpy,会对训练性能造成影响。不要在注重性能的训练场景下使用。
\ No newline at end of file
......@@ -234,32 +234,34 @@
<div itemprop="articleBody">
<div class="section" id="id1">
<h1><a class="toc-backref" href="#id9">本地训练与预测</a><a class="headerlink" href="#id1" title="永久链接至标题"></a></h1>
<h1><a class="toc-backref" href="#id10">本地训练与预测</a><a class="headerlink" href="#id1" title="永久链接至标题"></a></h1>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#id1" id="id9">本地训练与预测</a><ul>
<li><a class="reference internal" href="#id2" id="id10">1. 如何减少内存占用</a><ul>
<li><a class="reference internal" href="#dataprovider" id="id11">减少DataProvider缓冲池内存</a></li>
<li><a class="reference internal" href="#id3" id="id12">神经元激活内存</a></li>
<li><a class="reference internal" href="#id4" id="id13">参数内存</a></li>
<li><a class="reference internal" href="#id1" id="id10">本地训练与预测</a><ul>
<li><a class="reference internal" href="#id2" id="id11">1. 如何减少内存占用</a><ul>
<li><a class="reference internal" href="#dataprovider" id="id12">减少DataProvider缓冲池内存</a></li>
<li><a class="reference internal" href="#id3" id="id13">神经元激活内存</a></li>
<li><a class="reference internal" href="#id4" id="id14">参数内存</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id5" id="id14">2. 如何加速训练速度</a><ul>
<li><a class="reference internal" href="#id6" id="id15">减少数据载入的耗时</a></li>
<li><a class="reference internal" href="#id7" id="id16">加速训练速度</a></li>
<li><a class="reference internal" href="#id8" id="id17">利用更多的计算资源</a></li>
<li><a class="reference internal" href="#id5" id="id15">2. 如何加速训练速度</a><ul>
<li><a class="reference internal" href="#id6" id="id16">减少数据载入的耗时</a></li>
<li><a class="reference internal" href="#id7" id="id17">加速训练速度</a></li>
<li><a class="reference internal" href="#id8" id="id18">利用更多的计算资源</a></li>
</ul>
</li>
<li><a class="reference internal" href="#gpu" id="id18">3. 如何指定GPU设备</a></li>
<li><a class="reference internal" href="#floating-point-exception" id="id19">4. 训练过程中出现 <code class="code docutils literal"><span class="pre">Floating</span> <span class="pre">point</span> <span class="pre">exception</span></code>, 训练因此退出怎么办?</a></li>
<li><a class="reference internal" href="#infer-layer" id="id20">5. 如何调用 infer 接口输出多个layer的预测结果</a></li>
<li><a class="reference internal" href="#gpu" id="id19">3. 如何指定GPU设备</a></li>
<li><a class="reference internal" href="#floating-point-exception" id="id20">4. 训练过程中出现 <code class="code docutils literal"><span class="pre">Floating</span> <span class="pre">point</span> <span class="pre">exception</span></code>, 训练因此退出怎么办?</a></li>
<li><a class="reference internal" href="#infer-layer" id="id21">5. 如何调用 infer 接口输出多个layer的预测结果</a></li>
<li><a class="reference internal" href="#layeroutput" id="id22">6. 如何在训练过程中获得某一个layer的output</a></li>
<li><a class="reference internal" href="#id9" id="id23">7. 如何在训练过程中获得参数的权重和梯度</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id10">1. 如何减少内存占用</a><a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<h2><a class="toc-backref" href="#id11">1. 如何减少内存占用</a><a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<p>神经网络的训练本身是一个非常消耗内存和显存的工作,经常会消耗数10GB的内存和数GB的显存。
PaddlePaddle的内存占用主要分为如下几个方面:</p>
<ul class="simple">
......@@ -270,7 +272,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</ul>
<p>其中,其他内存杂项是指PaddlePaddle本身所用的一些内存,包括字符串分配,临时变量等等,暂不考虑在内。</p>
<div class="section" id="dataprovider">
<h3><a class="toc-backref" href="#id11">减少DataProvider缓冲池内存</a><a class="headerlink" href="#dataprovider" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id12">减少DataProvider缓冲池内存</a><a class="headerlink" href="#dataprovider" title="永久链接至标题"></a></h3>
<p>PyDataProvider使用的是异步加载,同时在内存里直接随即选取数据来做Shuffle。即</p>
<img src="../../_images/graphviz-9be6aad37f57c60f4b971dde0ef44ce27179cf9a.png" alt="digraph {
rankdir=LR;
......@@ -305,7 +307,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
<p>这样做可以极大的减少内存占用,并且可能会加速训练过程,详细文档参考 <a class="reference internal" href="../../api/v1/data_provider/pydataprovider2_cn.html#api-pydataprovider2"><span class="std std-ref">PyDataProvider2的使用</span></a></p>
</div>
<div class="section" id="id3">
<h3><a class="toc-backref" href="#id12">神经元激活内存</a><a class="headerlink" href="#id3" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id13">神经元激活内存</a><a class="headerlink" href="#id3" title="永久链接至标题"></a></h3>
<p>神经网络在训练的时候,会对每一个激活暂存一些数据,如神经元激活值等。
在反向传递的时候,这些数据会被用来更新参数。这些数据使用的内存主要和两个参数有关系,
一是batch size,另一个是每条序列(Sequence)长度。所以,其实也是和每个mini-batch中包含
......@@ -318,7 +320,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</ul>
</div>
<div class="section" id="id4">
<h3><a class="toc-backref" href="#id13">参数内存</a><a class="headerlink" href="#id4" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id14">参数内存</a><a class="headerlink" href="#id4" title="永久链接至标题"></a></h3>
<p>PaddlePaddle支持非常多的优化算法(Optimizer),不同的优化算法需要使用不同大小的内存。
例如使用 <code class="code docutils literal"><span class="pre">adadelta</span></code> 算法,则需要使用等于权重参数规模大约5倍的内存。举例,如果参数保存下来的模型目录
文件为 <code class="code docutils literal"><span class="pre">100M</span></code>, 那么该优化算法至少需要 <code class="code docutils literal"><span class="pre">500M</span></code> 的内存。</p>
......@@ -326,7 +328,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</div>
</div>
<div class="section" id="id5">
<h2><a class="toc-backref" href="#id14">2. 如何加速训练速度</a><a class="headerlink" href="#id5" title="永久链接至标题"></a></h2>
<h2><a class="toc-backref" href="#id15">2. 如何加速训练速度</a><a class="headerlink" href="#id5" title="永久链接至标题"></a></h2>
<p>加速PaddlePaddle训练可以考虑从以下几个方面:</p>
<ul class="simple">
<li>减少数据载入的耗时</li>
......@@ -334,7 +336,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
<li>利用分布式训练驾驭更多的计算资源</li>
</ul>
<div class="section" id="id6">
<h3><a class="toc-backref" href="#id15">减少数据载入的耗时</a><a class="headerlink" href="#id6" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id16">减少数据载入的耗时</a><a class="headerlink" href="#id6" title="永久链接至标题"></a></h3>
<p>使用<code class="code docutils literal"><span class="pre">pydataprovider</span></code>时,可以减少缓存池的大小,同时设置内存缓存功能,即可以极大的加速数据载入流程。
<code class="code docutils literal"><span class="pre">DataProvider</span></code> 缓存池的减小,和之前减小通过减小缓存池来减小内存占用的原理一致。</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.</span>
......@@ -363,7 +365,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
<p>同时 <code class="code docutils literal"><span class="pre">&#64;provider</span></code> 接口有一个 <code class="code docutils literal"><span class="pre">cache</span></code> 参数来控制缓存方法,将其设置成 <code class="code docutils literal"><span class="pre">CacheType.CACHE_PASS_IN_MEM</span></code> 的话,会将第一个 <code class="code docutils literal"><span class="pre">pass</span></code> (过完所有训练数据即为一个pass)生成的数据缓存在内存里,在之后的 <code class="code docutils literal"><span class="pre">pass</span></code> 中,不会再从 <code class="code docutils literal"><span class="pre">python</span></code> 端读取数据,而是直接从内存的缓存里读取数据。这也会极大减少数据读入的耗时。</p>
</div>
<div class="section" id="id7">
<h3><a class="toc-backref" href="#id16">加速训练速度</a><a class="headerlink" href="#id7" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id17">加速训练速度</a><a class="headerlink" href="#id7" title="永久链接至标题"></a></h3>
<p>PaddlePaddle支持Sparse的训练,sparse训练需要训练特征是 <code class="code docutils literal"><span class="pre">sparse_binary_vector</span></code><code class="code docutils literal"><span class="pre">sparse_vector</span></code> 、或者 <code class="code docutils literal"><span class="pre">integer_value</span></code> 的任一一种。同时,与这个训练数据交互的Layer,需要将其Parameter设置成 sparse 更新模式,即设置 <code class="code docutils literal"><span class="pre">sparse_update=True</span></code></p>
<p>这里使用简单的 <code class="code docutils literal"><span class="pre">word2vec</span></code> 训练语言模型距离,具体使用方法为:</p>
<p>使用一个词前两个词和后两个词,来预测这个中间的词。这个任务的DataProvider为:</p>
......@@ -424,7 +426,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</div>
</div>
<div class="section" id="id8">
<h3><a class="toc-backref" href="#id17">利用更多的计算资源</a><a class="headerlink" href="#id8" title="永久链接至标题"></a></h3>
<h3><a class="toc-backref" href="#id18">利用更多的计算资源</a><a class="headerlink" href="#id8" title="永久链接至标题"></a></h3>
<p>利用更多的计算资源可以分为以下几个方式来进行:</p>
<ul class="simple">
<li>单机CPU训练<ul>
......@@ -444,7 +446,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</div>
</div>
<div class="section" id="gpu">
<h2><a class="toc-backref" href="#id18">3. 如何指定GPU设备</a><a class="headerlink" href="#gpu" title="永久链接至标题"></a></h2>
<h2><a class="toc-backref" href="#id19">3. 如何指定GPU设备</a><a class="headerlink" href="#gpu" title="永久链接至标题"></a></h2>
<p>例如机器上有4块GPU,编号从0开始,指定使用2、3号GPU:</p>
<ul class="simple">
<li>方式1:通过 <a class="reference external" href="http://www.acceleware.com/blog/cudavisibledevices-masking-gpus">CUDA_VISIBLE_DEVICES</a> 环境变量来指定特定的GPU。</li>
......@@ -460,7 +462,7 @@ PaddlePaddle的内存占用主要分为如下几个方面:</p>
</div>
</div>
<div class="section" id="floating-point-exception">
<h2><a class="toc-backref" href="#id19">4. 训练过程中出现 <code class="code docutils literal"><span class="pre">Floating</span> <span class="pre">point</span> <span class="pre">exception</span></code>, 训练因此退出怎么办?</a><a class="headerlink" href="#floating-point-exception" title="永久链接至标题"></a></h2>
<h2><a class="toc-backref" href="#id20">4. 训练过程中出现 <code class="code docutils literal"><span class="pre">Floating</span> <span class="pre">point</span> <span class="pre">exception</span></code>, 训练因此退出怎么办?</a><a class="headerlink" href="#floating-point-exception" title="永久链接至标题"></a></h2>
<p>Paddle二进制在运行时捕获了浮点数异常,只要出现浮点数异常(即训练过程中出现NaN或者Inf),立刻退出。浮点异常通常的原因是浮点数溢出、除零等问题。
主要原因包括两个方面:</p>
<ul class="simple">
......@@ -508,7 +510,7 @@ layer_attr=paddle.attr.ExtraLayerAttribute(</p>
<p>除此之外,还可以通过减小学习率或者对数据进行归一化处理来解决这类问题。</p>
</div>
<div class="section" id="infer-layer">
<h2><a class="toc-backref" href="#id20">5. 如何调用 infer 接口输出多个layer的预测结果</a><a class="headerlink" href="#infer-layer" title="永久链接至标题"></a></h2>
<h2><a class="toc-backref" href="#id21">5. 如何调用 infer 接口输出多个layer的预测结果</a><a class="headerlink" href="#infer-layer" title="永久链接至标题"></a></h2>
<ul class="simple">
<li>将需要输出的层作为 <code class="code docutils literal"><span class="pre">paddle.inference.Inference()</span></code> 接口的 <code class="code docutils literal"><span class="pre">output_layer</span></code> 参数输入,代码如下:</li>
</ul>
......@@ -542,6 +544,46 @@ layer_attr=paddle.attr.ExtraLayerAttribute(</p>
<li>每一个layer输出矩阵的高度,在非序列输入时:等于样本数;序列输入时等于:输入序列中元素的总数;宽度等于配置中layer的size;</li>
</ul>
</div>
<div class="section" id="layeroutput">
<h2><a class="toc-backref" href="#id22">6. 如何在训练过程中获得某一个layer的output</a><a class="headerlink" href="#layeroutput" title="永久链接至标题"></a></h2>
<p>可以在event_handler中,通过 <code class="code docutils literal"><span class="pre">event.gm.getLayerOutputs(&quot;layer_name&quot;)</span></code> 获得在模型配置中某一层的name <code class="code docutils literal"><span class="pre">layer_name</span></code> 在当前
mini-batch forward的output的值。获得的值类型均为 <code class="code docutils literal"><span class="pre">numpy.ndarray</span></code> ,可以通过这个输出来完成自定义的评估指标计算等功能。例如下面代码:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">score_diff</span><span class="p">(</span><span class="n">right_score</span><span class="p">,</span> <span class="n">left_score</span><span class="p">):</span>
<span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">average</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">right_score</span> <span class="o">-</span> <span class="n">left_score</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">event_handler</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">paddle</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">EndIteration</span><span class="p">):</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">batch_id</span> <span class="o">%</span> <span class="mi">25</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">diff</span> <span class="o">=</span> <span class="n">score_diff</span><span class="p">(</span>
<span class="n">event</span><span class="o">.</span><span class="n">gm</span><span class="o">.</span><span class="n">getLayerOutputs</span><span class="p">(</span><span class="s2">&quot;right_score&quot;</span><span class="p">)[</span><span class="s2">&quot;right_score&quot;</span><span class="p">][</span>
<span class="s2">&quot;value&quot;</span><span class="p">],</span>
<span class="n">event</span><span class="o">.</span><span class="n">gm</span><span class="o">.</span><span class="n">getLayerOutputs</span><span class="p">(</span><span class="s2">&quot;left_score&quot;</span><span class="p">)[</span><span class="s2">&quot;left_score&quot;</span><span class="p">][</span>
<span class="s2">&quot;value&quot;</span><span class="p">])</span>
<span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">((</span><span class="s2">&quot;Pass </span><span class="si">%d</span><span class="s2"> Batch </span><span class="si">%d</span><span class="s2"> : Cost </span><span class="si">%.6f</span><span class="s2">, &quot;</span>
<span class="s2">&quot;average absolute diff scores: </span><span class="si">%.6f</span><span class="s2">&quot;</span><span class="p">)</span> <span class="o">%</span>
<span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">pass_id</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">batch_id</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">cost</span><span class="p">,</span> <span class="n">diff</span><span class="p">))</span>
</pre></div>
</div>
<p>注意:此方法不能获取 <code class="code docutils literal"><span class="pre">paddle.layer.recurrent_group</span></code> 里step的内容,但可以获取 <code class="code docutils literal"><span class="pre">paddle.layer.recurrent_group</span></code> 的输出。</p>
</div>
<div class="section" id="id9">
<h2><a class="toc-backref" href="#id23">7. 如何在训练过程中获得参数的权重和梯度</a><a class="headerlink" href="#id9" title="永久链接至标题"></a></h2>
<p>在某些情况下,获得当前mini-batch的权重(或称作weights, parameters)有助于在训练时观察具体数值,方便排查以及快速定位问题。
可以通过在 <code class="code docutils literal"><span class="pre">event_handler</span></code> 中打印其值(注意,需要使用 <code class="code docutils literal"><span class="pre">paddle.event.EndForwardBackward</span></code> 保证使用GPU训练时也可以获得),
示例代码如下:</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="o">...</span>
<span class="n">parameters</span> <span class="o">=</span> <span class="n">paddle</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">cost</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">event_handler</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">paddle</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">EndForwardBackward</span><span class="p">):</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">batch_id</span> <span class="o">%</span> <span class="mi">25</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">parameters</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
<span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Param </span><span class="si">%s</span><span class="s2">, Grad </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span>
<span class="n">parameters</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="n">parameters</span><span class="o">.</span><span class="n">get_grad</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
</pre></div>
</div>
<p>注意:“在训练过程中获得某一个layer的output”和“在训练过程中获得参数的权重和梯度”都会造成训练中的数据从C++拷贝到numpy,会对训练性能造成影响。不要在注重性能的训练场景下使用。</p>
</div>
</div>
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册