DependencyAware.rst 5.5 KB
Newer Older
kvartet's avatar
kvartet committed
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
滤波器剪枝的依赖感知模式
========================================

目前,我们有几种针对卷积层的滤波剪枝算法,分别为:FPGM Pruner, L1Filter Pruner, L2Filter Pruner, Activation APoZ Rank Filter Pruner, Activation Mean Rank Filter Pruner, Taylor FO On Weight Pruner。 在这些滤波器剪枝算法中,剪枝器将分别对每个卷积层进行剪枝。 在裁剪卷积层时,算法会根据一些特定的规则(如l1-norm)量化每个滤波器的重要性,并裁剪不太重要的滤波器。

就像 `dependency analysis utils <./CompressionUtils.md>`__ 显示,如果将两个卷积层(conv1,conv2)的输出通道相加,这两个卷积层之间将具有通道依赖关系(更多详细信息参见 `Compression Utils <./CompressionUtils.rst>`__\ )。 以下图为例。


.. image:: ../../img/mask_conflict.jpg
   :target: ../../img/mask_conflict.jpg
   :alt: 


如果我们为 conv1 修剪前50%的输出通道(滤波器),并为 conv2 修剪后50%的输出通道, 虽然这两个层都删减了50%的滤波器,但加速模块仍然需要添加零来对齐输出通道。 在这种情况下,我们无法从模型剪枝中获得速度效益。

 为了更好地发挥模型剪枝的速度优势,我们为滤波器剪枝添加了一个依赖感知模式。 在依赖感知模式下,剪枝器不仅根据每个滤波器的l1范数对模型进行剪枝,而且还会基于整个网络结构的拓扑结构对模型进行剪枝。

在依赖关系感知模式下(``dependency_aware`` 设置为``True``),剪枝器将尝试为彼此具有通道依赖关系的层修剪相同的输出通道,如下图所示。


.. image:: ../../img/dependency-aware.jpg
   :target: ../../img/dependency-aware.jpg
   :alt: 


以 L1Filter Pruner 的依赖感知模式为例。 具体来说,剪枝器将为每个通道计算依赖集中所有层的L1范数和。 显然,最终可以从这个依赖集中删除的通道数量是由这个依赖集中,层的最小稀疏性决定的(记作 ``min_sparsity``)。 根据每个通道的 L1 范数和,剪枝器将对所有层修剪相同的 ``min_sparsity`` 通道。 接下来,剪枝器将根据每个卷积层自己的 L1 范数为它们额外修剪 ``sparsity`` - ``min_sparsity`` 通道。 例如,假设 ``conv1``、``conv2`` 的输出通道相加,分别配置稀疏度为0.3和0.2。 在这种情况下,``依赖感知的剪枝器`` 将会 

.. code-block:: bash

   - 首先,根据 `conv1` 和 `conv2` 的 L1 范数和,修剪 `conv1` 和 `conv2` 相同的20%通道。 
   - 其次,剪枝器将根据 `conv1` 每个通道的 L1 范数为 `conv1` 额外修剪10%的通道。


此外,对于具有多个滤波器组的卷积层,``依赖感知剪枝器`` 也将尝试为每个滤波器组修剪相同数量的通道。 总体而言,该剪枝器将根据每个滤波器的 L1 范数对模型进行剪枝,并尝试满足拓扑约束(通道依赖等),以提高加速过程后的最终速度增益。 

在依赖关系感知模式下,剪枝器将为模型修剪提供更好的速度增益。

用法
-----

在本节中,我们将说明如何使用滤波剪枝器的依赖感知模式。 目前,我们有几种 One-Shot 的 Pruner,比如 FPGM Pruner, L1Filter Pruner, L2Filter Pruner, Activation APoZ Rank Filter Pruner, Activation Mean Rank Filter Pruner, Taylor FO On Weight Pruner 支持依赖感知模式。

以为 ``L1FilterPruner`` 启动依赖感知模式为例:

.. code-block:: python

   from nni.algorithms.compression.pytorch.pruning import L1FilterPruner
   config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'] }]
   # dummy_input 对于依赖感知模式是必需的
   dummy_input = torch.ones(1, 3, 224, 224).cuda()
   pruner = L1FilterPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
   # 对于 L2FilterPruner
   # pruner = L2FilterPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
   # 对于 FPGMPruner
   # pruner = FPGMPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
   # 对于 ActivationAPoZRankFilterPruner
   # pruner = ActivationAPoZRankFilterPruner(model, config_list, statistics_batch_num=1, , dependency_aware=True, dummy_input=dummy_input)
   # 对于 ActivationMeanRankFilterPruner
   # pruner = ActivationMeanRankFilterPruner(model, config_list, statistics_batch_num=1, dependency_aware=True, dummy_input=dummy_input)
   # 对于 TaylorFOWeightFilterPruner
   # pruner = TaylorFOWeightFilterPruner(model, config_list, statistics_batch_num=1, dependency_aware=True, dummy_input=dummy_input)

   pruner.compress()


评估
----------

为了比较有无依赖感知模式的剪枝器的性能,我们使用 L1FilterPruner 分别在依赖感知模式打开和关闭下修剪 Mobilenet_v2。 为了简化实验,我们将统一剪枝,这意味着我们为模型中的所有卷积层分配相同的稀疏度。
我们在cifar10数据集上训练了Mobilenet_v2模型,并根据此预先训练的检查点对模型进行裁剪。 下图显示了不同剪枝器剪枝后模型的准确率和 FLOPs。


.. image:: ../../img/mobilev2_l1_cifar.jpg
   :target: ../../img/mobilev2_l1_cifar.jpg
   :alt: 


在图中,``依赖感知`` 表示 L1FilterPruner 启用了依赖感知模式。 ``L1 Filter`` 是没有依赖感知模式的普通 ``L1FilterPruner``,而 ``No-Dependency`` 意味着剪枝器只修剪了与其他层没有通道依赖的层。 如图所示,当启用依赖感知模式时,剪枝器可以在相同的浮点运算率下带来更高的精度。