unstructured_pruner.rst 5.2 KB
Newer Older
1 2 3 4 5 6 7 8 9
非结构化稀疏
================

UnstructuredPruner
----------

.. py:class:: paddleslim.UnstructuredPruner(model, mode, threshold=0.01, ratio=0.3, skip_params_func=None)


10
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/dygraph/prune/unstructured_pruner.py>`_
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

对于神经网络中的参数进行非结构化稀疏。非结构化稀疏是指,根据某些衡量指标,将不重要的参数置0。其不按照固定结构剪裁(例如一个通道等),这是和结构化剪枝的主要区别。

**参数:**

- **model(paddle.nn.Layer)** - 待剪裁的动态图模型。
- **mode(str)** - 稀疏化的模式,目前支持的模式有:'ratio''threshold'。在'ratio'模式下,会给定一个固定比例,例如0.5,然后所有参数中重要性较低的50%会被置0。类似的,在'threshold'模式下,会给定一个固定阈值,例如1e-5,然后重要性低于1e-5的参数会被置0
- **ratio(float)** - 稀疏化比例期望,只有在 mode=='ratio' 时才会生效。
- **threshold(float)** - 稀疏化阈值期望,只有在 mode=='threshold' 时才会生效。
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数不参与剪裁。

**返回:** 一个UnstructuredPruner类的实例。

**示例代码:**

.. code-block:: python

28
  import paddle
29
  from paddleslim import UnstructuredPruner
30 31 32 33 34 35
  from paddle.vision.models import LeNet as net
  import numpy as np

  place = paddle.set_device('cpu')
  model = net(num_classes=10)

36 37 38 39 40 41 42 43 44 45 46 47
  pruner = UnstructuredPruner(model, mode='ratio', ratio=0.5)

..

  .. py:method:: paddleslim.UnstructuredPruner.step()

  更新稀疏化的阈值,如果是'threshold'模式,则维持设定的阈值,如果是'ratio'模式,则根据优化后的模型参数和设定的比例,重新计算阈值。

  **示例代码:**

  .. code-block:: python

48
    import paddle
49
    from paddleslim import UnstructuredPruner
50 51 52 53 54
    from paddle.vision.models import LeNet as net
    import numpy as np

    place = paddle.set_device('cpu')
    model = net(num_classes=10)
55
    pruner = UnstructuredPruner(model, mode='ratio', ratio=0.5)
56 57

    print(pruner.threshold)
58
    pruner.step()
59
    print(pruner.threshold) # 可以看出,这里的threshold和上面打印的不同,这是因为step函数根据设定的ratio更新了threshold数值,便于剪裁操作。
60 61 62 63 64 65 66 67 68 69 70

  ..

  .. py:method:: paddleslim.UnstructuredPruner.update_params()

  每一步优化后,重制模型中本来是0的权重。这一步通常用于模型evaluationsave之前,确保模型的稀疏率。

  **示例代码:**

  .. code-block:: python

71
    import paddle
72
    from paddleslim import UnstructuredPruner
73 74 75 76 77 78 79 80 81 82 83
    from paddle.vision.models import LeNet as net
    import numpy as np

    place = paddle.set_device('cpu')
    model = net(num_classes=10)
    pruner = UnstructuredPruner(model, mode='threshold', threshold=0.5)

    density = UnstructuredPruner.total_sparse(model)
    print(density)
    model(paddle.to_tensor(
                np.random.uniform(0, 1, [16, 1, 28, 28]), dtype='float32'))
84
    pruner.update_params()
85 86
    density = UnstructuredPruner.total_sparse(model)
    print(density) # 可以看出,这里打印的模型稠密度与上述不同,这是因为update_params()函数置零了所有绝对值小于0.5的权重。
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

  ..

  ..  py:method:: paddleslim.UnstructuredPruner.total_sparse(model)

  UnstructuredPruner中的静态方法,用于计算给定的模型(model)的稠密度(1-稀疏度)并返回。该方法为静态方法,是考虑到在单单做模型评价的时候,我们就不需要初始化一个UnstructuredPruner示例了。

  **参数:**

  -  **model(paddle.nn.Layer)** - 要计算稠密度的目标网络。

  **返回:**
  
  - **density(float)** - 模型的稠密度。

  **示例代码:**

  .. code-block:: python

106
    import paddle
107
    from paddleslim import UnstructuredPruner
108 109
    from paddle.vision.models import LeNet as net
    import numpy as np
110

111 112 113 114 115
    place = paddle.set_device('cpu')
    model = net(num_classes=10)
    density = UnstructuredPruner.total_sparse(model)
    print(density)
    
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
  ..

  .. py:method:: paddleslim.UnstructuredPruner.summarize_weights(model, ratio=0.1)

  该函数用于估计预训练模型中参数的分布情况,尤其是在不清楚如何设置threshold的数值时,尤为有用。例如,当输入为ratio=0.1时,函数会返回一个数值v,而绝对值小于v的权重的个数占所有权重个数的(100*ratio%)

  **参数:**

  - **model(paddle.nn.Layer)** - 要分析权重分布的目标网络。
  - **ratio(float)** - 需要查看的比例情况,具体如上方法描述。

  **返回:**

  - **threshold(float)** - 和输入ratio对应的阈值。开发者可以根据该阈值初始化UnstructuredPruner

  **示例代码:**

  .. code-block:: python

135
    import paddle
136
    from paddleslim import UnstructuredPruner
137 138 139 140 141
    from paddle.vision.models import LeNet as net
    import numpy as np

    place = paddle.set_device('cpu')
    model = net(num_classes=10)
142
    pruner = UnstructuredPruner(model, mode='ratio', ratio=0.5)
143 144 145

    threshold = pruner.summarize_weights(model, 0.5)
    print(threshold)
146 147

  ..