未验证 提交 ac353c48 编写于 作者: W whs 提交者: GitHub

Refactor docs of static API and dygraph API (#645) (#646)

上级 31cbd12f
# 版本更新信息 # 版本更新
## 最新版本信息 ## 最新版本信息
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
- 拆分PaddleSlim为独立repo。 - 拆分PaddleSlim为独立repo。
- 重构裁剪、量化、蒸馏、搜索接口,对用户开放底层接口。 - 重构裁剪、量化、蒸馏、搜索接口,对用户开放底层接口。
- 量化: - 量化:
- 新增基于KL散度的离线量化功能,支持对Embedding层量化。 - 新增基于KL散度的离线量化功能,支持对Embedding层量化。
- 新增对FC的QAT MKL-DNN量化策略支持 - 新增对FC的QAT MKL-DNN量化策略支持
- 新增PostTrainingQuantization,完整实现训练后量化功能:支持量化30种OP,支持灵活设置需要量化的OP,生成统一格式的量化模型,具有耗时短、易用性强、精度损失较小的优点。 - 新增PostTrainingQuantization,完整实现训练后量化功能:支持量化30种OP,支持灵活设置需要量化的OP,生成统一格式的量化模型,具有耗时短、易用性强、精度损失较小的优点。
- 量化训练支持设定需要量化的OP类型。 - 量化训练支持设定需要量化的OP类型。
- 裁剪: 重构剪裁实现,方便扩展支持更多类型的网络。 - 裁剪: 重构剪裁实现,方便扩展支持更多类型的网络。
......
...@@ -3,14 +3,11 @@ ...@@ -3,14 +3,11 @@
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.
API文档 动态图
====================================== =======
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
common_index.rst pruners/index.rst
quant_index.rst ofa/index.rst
prune_index.rst
distill_index.rst
nas_index.rst
Once-For-All OFA-训练
============ ============
在进行Once-For-All训练之前,需要把普通的模型先转换为由动态OP组网的超网络。超网络转换方式可以参考 `超网络转换 <./convert_supernet_api.rst>`_ 在进行Once-For-All训练之前,需要把普通的模型先转换为由动态OP组网的超网络。超网络转换方式可以参考 `超网络转换 <./convert_supernet_api.rst>`_
......
SuperOP OFA-超网络转换
======== ==============
PaddleSlim提供了一些API的动态版本,动态API指的是这些OP的参数大小可以在实际运行过程中根据传入的参数进行改变,用法上的差别具体是forward时候需要额外传一些实际运行相关的参数。其中 `layers_old.py <../../../paddleslim/nas/ofa/layers_old.py>`_ 对应的是Paddle 2.0alpha及之前版本的API, `layers.py <../../../paddleslim/nas/ofa/layers.py>`_ 对应的是Paddle 2.0alpha之后版本的API。 PaddleSlim提供了一些API的动态版本,动态API指的是这些OP的参数大小可以在实际运行过程中根据传入的参数进行改变,用法上的差别具体是forward时候需要额外传一些实际运行相关的参数。其中 `layers_old.py <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers_old.py>`_ 对应的是Paddle 2.0alpha及之前版本的API, `layers.py <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py>`_ 对应的是Paddle 2.0alpha之后版本的API。
.. py:class:: paddleslim.nas.ofa.layers.Block(fn, fixed=False, key=None) .. py:class:: paddleslim.nas.ofa.layers.Block(fn, fixed=False, key=None)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L64>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L64>`_
对Layer进行封装,封装后的Layer和普通Layer用法相同。把每层定义的搜索空间整合到一个大的搜索空间中,训练的时候可以去选择每层的搜索空间。只有在实际运行过程中可以主动改变参数大小的API需要用本类封装,即只有 ``Conv2D`` 、 ``Linear`` 和 ``Embedding`` 这三个API构造的层可能需要被封装。 对Layer进行封装,封装后的Layer和普通Layer用法相同。把每层定义的搜索空间整合到一个大的搜索空间中,训练的时候可以去选择每层的搜索空间。只有在实际运行过程中可以主动改变参数大小的API需要用本类封装,即只有 ``Conv2D`` 、 ``Linear`` 和 ``Embedding`` 这三个API构造的层可能需要被封装。
...@@ -27,7 +27,7 @@ Block实例 ...@@ -27,7 +27,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperConv2D(in_channels, out_channels, kernel_size, candidate_config={}, transform_kernel=False, stride=1, padding=0, dilation=1, groups=1, padding_mode='zeros', weight_attr=None, bias_attr=None, data_format='NCHW') .. py:class:: paddleslim.nas.ofa.layers.SuperConv2D(in_channels, out_channels, kernel_size, candidate_config={}, transform_kernel=False, stride=1, padding=0, dilation=1, groups=1, padding_mode='zeros', weight_attr=None, bias_attr=None, data_format='NCHW')
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L85>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L85>`_
该接口用于构建 SuperConv2D 类的一个可调用对象。 该接口用于构建 SuperConv2D 类的一个可调用对象。
...@@ -69,7 +69,7 @@ Block实例 ...@@ -69,7 +69,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperConv2DTranspose(in_channels, out_channels, kernel_size, candidate_config={}, transform_kernel=False, stride=1, padding=0, output_padding=0, dilation=1, groups=1, padding_mode='zeros', weight_attr=None, bias_attr=None, data_format='NCHW') .. py:class:: paddleslim.nas.ofa.layers.SuperConv2DTranspose(in_channels, out_channels, kernel_size, candidate_config={}, transform_kernel=False, stride=1, padding=0, output_padding=0, dilation=1, groups=1, padding_mode='zeros', weight_attr=None, bias_attr=None, data_format='NCHW')
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L381>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L386>`_
该接口用于构建 SuperConv2DTranspose 类的一个可调用对象。 该接口用于构建 SuperConv2DTranspose 类的一个可调用对象。
...@@ -112,7 +112,7 @@ Block实例 ...@@ -112,7 +112,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperLinear(in_features, out_features, candidate_config={}, weight_attr=None, bias_attr=None, name=None): .. py:class:: paddleslim.nas.ofa.layers.SuperLinear(in_features, out_features, candidate_config={}, weight_attr=None, bias_attr=None, name=None):
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L828>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L833>`_
该接口用于构建 SuperLinear 类的一个可调用对象。 该接口用于构建 SuperLinear 类的一个可调用对象。
...@@ -148,7 +148,7 @@ Block实例 ...@@ -148,7 +148,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperEmbedding(num_embeddings, embedding_dim, candidate_config={}, padding_idx=None, sparse=False, weight_attr=None, name=None): .. py:class:: paddleslim.nas.ofa.layers.SuperEmbedding(num_embeddings, embedding_dim, candidate_config={}, padding_idx=None, sparse=False, weight_attr=None, name=None):
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L1126>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L1131>`_
该接口用于构建 SuperEmbedding 类的一个可调用对象。 该接口用于构建 SuperEmbedding 类的一个可调用对象。
...@@ -184,7 +184,7 @@ Block实例 ...@@ -184,7 +184,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperBatchNorm2D(num_features, momentum=0.9, epsilon=1e-05, weight_attr=None, bias_attr=None, data_format='NCHW', name=None): .. py:class:: paddleslim.nas.ofa.layers.SuperBatchNorm2D(num_features, momentum=0.9, epsilon=1e-05, weight_attr=None, bias_attr=None, data_format='NCHW', name=None):
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L932>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L937>`_
该接口用于构建 SuperBatchNorm2D 类的一个可调用对象。 该接口用于构建 SuperBatchNorm2D 类的一个可调用对象。
...@@ -213,7 +213,7 @@ Block实例 ...@@ -213,7 +213,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperInstanceNorm2D(num_features, momentum=0.9, epsilon=1e-05, weight_attr=None, bias_attr=None, data_format='NCHW', name=None): .. py:class:: paddleslim.nas.ofa.layers.SuperInstanceNorm2D(num_features, momentum=0.9, epsilon=1e-05, weight_attr=None, bias_attr=None, data_format='NCHW', name=None):
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L999>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L1004>`_
该接口用于构建 SuperInstanceNorm2D 类的一个可调用对象。 该接口用于构建 SuperInstanceNorm2D 类的一个可调用对象。
...@@ -242,7 +242,7 @@ Block实例 ...@@ -242,7 +242,7 @@ Block实例
.. py:class:: paddleslim.nas.ofa.layers.SuperLayerNorm(normalized_shape, epsilon=1e-05, weight_attr=None, bias_attr=None, name=None): .. py:class:: paddleslim.nas.ofa.layers.SuperLayerNorm(normalized_shape, epsilon=1e-05, weight_attr=None, bias_attr=None, name=None):
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/74db974b6f0187e22bbaf340381a63b7d687a7d4/paddleslim/nas/ofa/layers.py#L1057>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/nas/ofa/layers.py#L1062>`_
该接口用于构建 SuperLayerNorm 类的一个可调用对象。 该接口用于构建 SuperLayerNorm 类的一个可调用对象。
......
FPGMFilterPruner
==================
.. py:class:: paddleslim.FPGMFilterPruner(model, inputs, sen_file=None)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/dygraph/fpgm_pruner.py>`_
用于剪裁卷积层输出通道的的剪裁器。该剪裁器按论文 `Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration <https://arxiv.org/abs/1811.00250>_` 中的统计方法对单个卷积层内的 ``Filters`` 的重要性进行排序,并按指定比例剪裁掉相对不重要的 ``Filters`` 。对 ``Filters`` 的剪裁等价于剪裁卷积层的输出通道数。
**参数:**
- **model(paddle.nn.Layer)** - 待裁剪的动态图模型。
- **inputs(list<Object>)** - 待裁模型执行时需要的参数列表。该参数列表会以 ``model(*inputs)`` 的形式被调用。注意,被调用 ``model(*inputs)`` 使用到的卷积层才能被剪裁。以上调用用于将动态转为静态图,以便获得网络结构拓扑图,从而分析多个卷积层间的依赖关系。
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果用户不需要敏感度剪裁策略,可以将该选项设置为 ``None`` 。默认为None
**返回:** 一个剪裁器实例。
**示例代码:**
.. code-block:: python
from paddleslim import FPGMFilterPruner
pruner = FPGMFilterPruner()
..
.. py:method:: prune_var(var_name, pruned_dims, pruned_ratio, apply="impretive")
按指定的比例inplace地对原模型的单个卷积层及其相关卷积层进行剪裁。
**参数:**
- **var_name(str)** - 卷积层 ``weight`` 变量的名称。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **pruned_dims(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **pruned_ratio(float)** - 待剪裁掉的输出通道比例。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import FPGMFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = FPGMFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_var("conv2d_26.w_0", [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: prune_vars(ratios, axis, apply="impretive")
按指定的比例inplace地对原模型的多个卷积层及其相关卷积层进行剪裁。
**参数:**
- **ratios(dict)** - 待剪裁卷积层 ``weight`` 变量名称以及对应的剪裁率。其中字典的 ``key`` ``str`` 类型,为变量名称, ``value`` ``float`` 类型,表示对应卷积层需要剪掉的输出通道的比例。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **axis(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import FPGMFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = FPGMFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_vars({"conv2d_26.w_0": 0.5}, [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: sensitive(eval_func=None, sen_file=None, target_vars=None, skip_vars=[])
计算或获得模型的敏感度信息。当所有选项为默认值时,该方法返回当前剪裁器已计算的敏感度信息。当选项被正确设置时,该方法会计算根据当前剪裁器的剪裁策略计算分析模型的敏感度信息,并将敏感度信息追加保存到指定的文件中,同时敏感度信息会缓存到当前剪裁器中,以供后续其它操作使用。
**参数:**
- **eval_func** - 用于评估当前剪裁器中模型精度的方法,其参数列表应该为空,并返回一个 ``float`` 类型的数值来表示模型的精度。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None。默认为None
- **target_vars(list<str>)** - 变量名称列表,用于指定需要计算哪些卷积层的 ``weight`` 的敏感度。如果设置为None,则所有卷积层的敏感度都会被计算。默认为None
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
**返回:**
- **sensitivities(dict)** - 存储敏感信息的字典,示例如下:
.. code-block:: python
{"weight_0":
{0.1: 0.22,
0.2: 0.33
},
"weight_1":
{0.1: 0.21,
0.2: 0.4
}
}
其中,``weight_0`` 是卷积层权重变量的名称, ``sensitivities['weight_0']`` 是一个字典, key是用 ``float`` 类型数值表示的剪裁率,value是对应剪裁率下整个模型的精度损失比例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import FPGMFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = FPGMFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
print(f"sen: {sen}")
.. py:method:: sensitive_prune(pruned_flops, skip_vars=[], align=None)
根据敏感度信息和模型整体的FLOPs剪裁比例,对模型中的卷积层进行inplace地剪裁,不同卷积层被裁掉的比例与其敏感度成反比。
**参数:**
- **pruned_flops(float)** - 模型整体的FLOPs被裁剪的目标比例。注意:最终FLOPs被裁剪掉的比例不一定完全等于 ``pruned_flops``
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
- **align(None|int)** - 是否将剪裁后的通道数量对齐到指定数值的倍数。假设原通道数为32,剪裁比例为0.2,如果 ``align`` None,则剪裁后通道数为26;如果 ``align`` 8,则剪裁后的通道数为24。默认为None
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import FPGMFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = FPGMFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
plan = pruner.sensitive_prune(0.5, align=8)
print(f"plan: {plan}")
L1NormFilterPruner
==================
.. py:class:: paddleslim.L1NormFilterPruner(model, inputs, sen_file=None)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/dygraph/l1norm_pruner.py#L14>`_
用于剪裁卷积层输出通道的的剪裁器。该剪裁器按 ``Filters`` ``l1-norm`` 统计值对单个卷积层内的 ``Filters`` 的重要性进行排序,并按指定比例剪裁掉相对不重要的 ``Filters`` 。对 ``Filters`` 的剪裁等价于剪裁卷积层的输出通道数。
**参数:**
- **model(paddle.nn.Layer)** - 待裁剪的动态图模型。
- **inputs(list<Object>)** - 待裁模型执行时需要的参数列表。该参数列表会以 ``model(*inputs)`` 的形式被调用。注意,被调用 ``model(*inputs)`` 使用到的卷积层才能被剪裁。以上调用用于将动态转为静态图,以便获得网络结构拓扑图,从而分析多个卷积层间的依赖关系。
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果用户不需要敏感度剪裁策略,可以将该选项设置为 ``None`` 。默认为None
**返回:** 一个剪裁器实例。
**示例代码:**
.. code-block:: python
from paddleslim import L1NormFilterPruner
pruner = L1NormFilterPruner()
..
.. py:method:: prune_var(var_name, pruned_dims, pruned_ratio, apply="impretive")
按指定的比例inplace地对原模型的单个卷积层及其相关卷积层进行剪裁。
**参数:**
- **var_name(str)** - 卷积层 ``weight`` 变量的名称。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **pruned_dims(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **pruned_ratio(float)** - 待剪裁掉的输出通道比例。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L1NormFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = L1NormFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_var("conv2d_26.w_0", [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: prune_vars(ratios, axis, apply="impretive")
按指定的比例inplace地对原模型的多个卷积层及其相关卷积层进行剪裁。
**参数:**
- **ratios(dict)** - 待剪裁卷积层 ``weight`` 变量名称以及对应的剪裁率。其中字典的 ``key`` ``str`` 类型,为变量名称, ``value`` ``float`` 类型,表示对应卷积层需要剪掉的输出通道的比例。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **axis(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L1NormFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = L1NormFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_vars({"conv2d_26.w_0": 0.5}, [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: sensitive(eval_func=None, sen_file=None, target_vars=None, skip_vars=[])
计算或获得模型的敏感度信息。当所有选项为默认值时,该方法返回当前剪裁器已计算的敏感度信息。当选项被正确设置时,该方法会计算根据当前剪裁器的剪裁策略计算分析模型的敏感度信息,并将敏感度信息追加保存到指定的文件中,同时敏感度信息会缓存到当前剪裁器中,以供后续其它操作使用。
**参数:**
- **eval_func** - 用于评估当前剪裁器中模型精度的方法,其参数列表应该为空,并返回一个 ``float`` 类型的数值来表示模型的精度。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None。默认为None
- **target_vars(list<str>)** - 变量名称列表,用于指定需要计算哪些卷积层的 ``weight`` 的敏感度。如果设置为None,则所有卷积层的敏感度都会被计算。默认为None
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
**返回:**
- **sensitivities(dict)** - 存储敏感信息的字典,示例如下:
.. code-block:: python
{"weight_0":
{0.1: 0.22,
0.2: 0.33
},
"weight_1":
{0.1: 0.21,
0.2: 0.4
}
}
其中,``weight_0`` 是卷积层权重变量的名称, ``sensitivities['weight_0']`` 是一个字典, key是用 ``float`` 类型数值表示的剪裁率,value是对应剪裁率下整个模型的精度损失比例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L1NormFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = L1NormFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
print(f"sen: {sen}")
.. py:method:: sensitive_prune(pruned_flops, skip_vars=[], align=None)
根据敏感度信息和模型整体的FLOPs剪裁比例,对模型中的卷积层进行inplace地剪裁,不同卷积层被裁掉的比例与其敏感度成反比。
**参数:**
- **pruned_flops(float)** - 模型整体的FLOPs被裁剪的目标比例。注意:最终FLOPs被裁剪掉的比例不一定完全等于 ``pruned_flops``
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
- **align(None|int)** - 是否将剪裁后的通道数量对齐到指定数值的倍数。假设原通道数为32,剪裁比例为0.2,如果 ``align`` None,则剪裁后通道数为26;如果 ``align`` 8,则剪裁后的通道数为24。默认为None
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L1NormFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = L1NormFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
plan = pruner.sensitive_prune(0.5, align=8)
print(f"plan: {plan}")
L2NormFilterPruner
==================
.. py:class:: paddleslim.L2NormFilterPruner(model, inputs, sen_file=None)
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/paddleslim/dygraph/l2norm_pruner.py>`_
用于剪裁卷积层输出通道的的剪裁器。该剪裁器按 ``Filters`` ``l2-norm`` 统计值对单个卷积层内的 ``Filters`` 的重要性进行排序,并按指定比例剪裁掉相对不重要的 ``Filters`` 。对 ``Filters`` 的剪裁等价于剪裁卷积层的输出通道数。
**参数:**
- **model(paddle.nn.Layer)** - 待裁剪的动态图模型。
- **inputs(list<Object>)** - 待裁模型执行时需要的参数列表。该参数列表会以 ``model(*inputs)`` 的形式被调用。注意,被调用 ``model(*inputs)`` 使用到的卷积层才能被剪裁。以上调用用于将动态转为静态图,以便获得网络结构拓扑图,从而分析多个卷积层间的依赖关系。
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果用户不需要敏感度剪裁策略,可以将该选项设置为 ``None`` 。默认为None
**返回:** 一个剪裁器实例。
**示例代码:**
.. code-block:: python
from paddleslim import L2NormFilterPruner
pruner = L2NormFilterPruner()
..
.. py:method:: prune_var(var_name, pruned_dims, pruned_ratio, apply="impretive")
按指定的比例inplace地对原模型的单个卷积层及其相关卷积层进行剪裁。
**参数:**
- **var_name(str)** - 卷积层 ``weight`` 变量的名称。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **pruned_dims(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **pruned_ratio(float)** - 待剪裁掉的输出通道比例。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L2NormFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = L2NormFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_var("conv2d_26.w_0", [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: prune_vars(ratios, axis, apply="impretive")
按指定的比例inplace地对原模型的多个卷积层及其相关卷积层进行剪裁。
**参数:**
- **ratios(dict)** - 待剪裁卷积层 ``weight`` 变量名称以及对应的剪裁率。其中字典的 ``key`` ``str`` 类型,为变量名称, ``value`` ``float`` 类型,表示对应卷积层需要剪掉的输出通道的比例。可以通过 `parameters API <https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/fluid/dygraph/layers/Layer_cn.html#parameters>`_ 获得所有卷积层 ``weight`` 变量的名称。
- **axis(list<int>)** - 待废弃选项。卷积层 ``weight`` 变量中 ``Filter`` 数量所在轴,一般情况下设置为 ``[0]`` 即可。
- **apply(str)** - 实施剪裁操作的类型,候选值为:"impretive""lazy" ``None`` 。如果设置为"impretive",则会从输出特征图中真正的删掉待剪裁的通道。如果设置为"lazy",则仅会将待剪裁的通道置为 ``0`` 。如果设置为None,则仅会生成并返回剪裁计划,并不会将剪裁真正实施到原模型上,剪裁计划相关信息存储在类型为 `paddleslim.PruningPlan <>`_ 的实例中。该选项默认为"impretive"
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L2NormFilterPruner
net = mobilenet_v1(pretrained=False)
pruner = L2NormFilterPruner(net, [1, 3, 224, 224])
plan = pruner.prun_vars({"conv2d_26.w_0": 0.5}, [0])
print(f"plan: {plan}")
paddle.summary(net, (1, 3, 224, 224))
..
.. py:method:: sensitive(eval_func=None, sen_file=None, target_vars=None, skip_vars=[])
计算或获得模型的敏感度信息。当所有选项为默认值时,该方法返回当前剪裁器已计算的敏感度信息。当选项被正确设置时,该方法会计算根据当前剪裁器的剪裁策略计算分析模型的敏感度信息,并将敏感度信息追加保存到指定的文件中,同时敏感度信息会缓存到当前剪裁器中,以供后续其它操作使用。
**参数:**
- **eval_func** - 用于评估当前剪裁器中模型精度的方法,其参数列表应该为空,并返回一个 ``float`` 类型的数值来表示模型的精度。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None
- **sen_file(str)** - 存储敏感度信息的文件,需要指定为绝对路径。在调用当前剪裁器的 ``sensitive`` 方法时,敏感度信息会以增量的形式追加到文件 ``sen_file`` 中。如果设置为None,则不进行敏感度计算,返回当前剪裁器缓存的已计算好的敏感度信息。默认为None。默认为None
- **target_vars(list<str>)** - 变量名称列表,用于指定需要计算哪些卷积层的 ``weight`` 的敏感度。如果设置为None,则所有卷积层的敏感度都会被计算。默认为None
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
**返回:**
- **sensitivities(dict)** - 存储敏感信息的字典,示例如下:
.. code-block:: python
{"weight_0":
{0.1: 0.22,
0.2: 0.33
},
"weight_1":
{0.1: 0.21,
0.2: 0.4
}
}
其中,``weight_0`` 是卷积层权重变量的名称, ``sensitivities['weight_0']`` 是一个字典, key是用 ``float`` 类型数值表示的剪裁率,value是对应剪裁率下整个模型的精度损失比例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L2NormFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = L2NormFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
print(f"sen: {sen}")
.. py:method:: sensitive_prune(pruned_flops, skip_vars=[], align=None)
根据敏感度信息和模型整体的FLOPs剪裁比例,对模型中的卷积层进行inplace地剪裁,不同卷积层被裁掉的比例与其敏感度成反比。
**参数:**
- **pruned_flops(float)** - 模型整体的FLOPs被裁剪的目标比例。注意:最终FLOPs被裁剪掉的比例不一定完全等于 ``pruned_flops``
- **skip_vars(list<str>)** - 变量名称列表,用于指定哪些卷积层的 ``weight`` 不需要计算敏感度。如果设置为 ``[]`` ,则仅会默认跳过 ``depthwise_conv2d`` ``conv2d_transpose``。默认为 ``[]``
- **align(None|int)** - 是否将剪裁后的通道数量对齐到指定数值的倍数。假设原通道数为32,剪裁比例为0.2,如果 ``align`` None,则剪裁后通道数为26;如果 ``align`` 8,则剪裁后的通道数为24。默认为None
**返回:**
- **plan(paddleslim.PruningPlan)** - 存储剪裁计划的实例。
**示例:**
点击 `AIStudio <>`_ 执行以下示例代码。
.. code-block:: python
from paddle.vision.models import mobilenet_v1
from paddleslim import L2NormFilterPruner
import paddle.vision.transforms as T
from paddle.static import InputSpec as Input
# 构建模型
net = mobilenet_v1(pretrained=False)
# 准备高层API
inputs = [Input([None, 3, 224, 224], 'float32', name='image')]
labels = [Input([None, 1], 'int64', name='label')]
model = paddle.Model(net, inputs, labels)
model.prepare(
None,
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 5)))
# 准备评估数据
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5], [127.5])
])
train_dataset = paddle.vision.datasets.Cifar10(mode="train", backend="cv2",transform=transform)
val_dataset = paddle.vision.datasets.Cifar10(mode="test", backend="cv2",transform=transform)
# 准备评估方法
def eval_fn():
result = model.evaluate(
val_dataset,
batch_size=128)
return result['acc_top1']
# 敏感度分析
pruner = L2NormFilterPruner(net, [1, 3, 224, 224])
sen = pruner.sensitive(eval_func=eval_fn, sen_file="./sen.pickle")
plan = pruner.sensitive_prune(0.5, align=8)
print(f"plan: {plan}")
.. PaddleSlim documentation master file, created by
sphinx-quickstart on Wed Feb 5 14:04:52 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
静态图
======
.. toctree::
:maxdepth: 1
common/common_index.rst
quant/quant_index.rst
prune/prune_index.rst
dist/distill_index.rst
nas/nas_index.rst
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册