GradientClipByNorm_cn.rst 4.3 KB
Newer Older
R
root 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
.. _cn_api_fluid_clip_GradientClipByNorm:

GradientClipByNorm
-------------------------------

.. py:class:: paddle.fluid.clip.GradientClipByNorm(clip_norm, need_clip=None)

:alias_main: paddle.nn.GradientClipByNorm
:alias: paddle.nn.GradientClipByNorm,paddle.nn.clip.GradientClipByNorm
:old_api: paddle.fluid.clip.GradientClipByNorm



将输入的多维Tensor :math:`X` 的L2范数限制在 ``clip_norm`` 范围之内。

- 如果L2范数大于 ``clip_norm`` ,则该 Tensor 会乘以一个系数进行压缩

- 如果L2范数小于或等于 ``clip_norm`` ,则不会进行任何操作。

输入的 Tensor 不是从该类里传入, 而是默认会选择 ``Program`` 中全部的梯度,如果 ``need_clip`` 不为None,则可以只选择部分参数进行梯度裁剪。

该类需要在初始化 ``optimizer`` 时进行设置后才能生效,可参看 ``optimizer`` 文档(例如: :ref:`cn_api_fluid_optimizer_SGDOptimizer` )。

裁剪公式如下:

.. math::

  Out=
  \left\{
  \begin{aligned}
  &  X & & if (norm(X) \leq clip\_norm)\\
  &  \frac{clip\_norm∗X}{norm(X)} & & if (norm(X) > clip\_norm) \\
  \end{aligned}
  \right.


其中 :math:`norm(X)` 代表 :math:`X` 的L2范数

.. math::
  \\norm(X) = (\sum_{i=1}^{n}|x_i|^2)^{\frac{1}{2}}\\

参数:
 - **clip_norm** (float) - 所允许的二范数最大值。
 - **need_clip** (function, optional) - 类型: 函数。用于指定需要梯度裁剪的参数,该函数接收一个 ``Parameter`` ,返回一个 ``bool`` (True表示需要裁剪,False不需要裁剪)。默认为None,此时会裁剪网络中全部参数。

**代码示例1:静态图**
 
.. code-block:: python
            
    import paddle
    import paddle.fluid as fluid
    import numpy as np
                
    main_prog = fluid.Program()
    startup_prog = fluid.Program()
    with fluid.program_guard(
            main_program=main_prog, startup_program=startup_prog):
        image = fluid.data(
            name='x', shape=[-1, 2], dtype='float32')
        predict = fluid.layers.fc(input=image, size=3, act='relu') #可训练参数: fc_0.w.0, fc_0.b.0
        loss = fluid.layers.mean(predict)
        
        # 裁剪网络中全部参数:
        clip = fluid.clip.GradientClipByNorm(clip_norm=1.0)
        
        # 仅裁剪参数fc_0.w_0时:
        # 为need_clip参数传入一个函数fileter_func,fileter_func接收参数的类型为Parameter,返回类型为bool
        # def fileter_func(Parameter):
        # # 可以较为方便的通过Parameter.name判断(name可以在fluid.ParamAttr中设置,默认为fc_0.w_0、fc_0.b_0)
        #   return Parameter.name=="fc_0.w_0"
        # clip = fluid.clip.GradientClipByNorm(clip_norm=1.0, need_clip=fileter_func)

        sgd_optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.1, grad_clip=clip)
        sgd_optimizer.minimize(loss)

    place = fluid.CPUPlace()
    exe = fluid.Executor(place)
    x = np.random.uniform(-100, 100, (10, 2)).astype('float32')
    exe.run(startup_prog)
    out = exe.run(main_prog, feed={'x': x}, fetch_list=loss)


**代码示例2:动态图**

.. code-block:: python

    import paddle
    import paddle.fluid as fluid
    
    with fluid.dygraph.guard():
        linear = fluid.dygraph.Linear(10, 10)  #可训练参数: linear_0.w.0, linear_0.b.0
        inputs = fluid.layers.uniform_random([32, 10]).astype('float32')
        out = linear(fluid.dygraph.to_variable(inputs))
        loss = fluid.layers.reduce_mean(out)
        loss.backward()

        # 裁剪网络中全部参数:
        clip = fluid.clip.GradientClipByNorm(clip_norm=1.0)

        # 仅裁剪参数linear_0.w_0时:
        # 为need_clip参数传入一个函数fileter_func,fileter_func接收参数的类型为ParamBase,返回类型为bool
        # def fileter_func(ParamBase):
        # # 可以通过ParamBase.name判断(name可以在fluid.ParamAttr中设置,默认为linear_0.w_0、linear_0.b_0)
        #   return ParamBase.name == "linear_0.w_0"
        # # 注:linear.weight、linear.bias能分别返回dygraph.Linear层的权重与偏差,也可以此来判断
        #   return ParamBase.name == linear.weight.name
        # clip = fluid.clip.GradientClipByNorm(clip_norm=1.0, need_clip=fileter_func)

        sgd_optimizer = fluid.optimizer.SGD(
          learning_rate=0.1, parameter_list=linear.parameters(), grad_clip=clip)
        sgd_optimizer.minimize(loss)