Skip to content

Commit 23cc74d

Browse files
authored
[Unstructured prune]Support block sparse training (PaddlePaddle#1000)
1 parent d096d3a commit 23cc74d

File tree

14 files changed

+163
-24
lines changed

14 files changed

+163
-24
lines changed

demo/dygraph/unstructured_pruning/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ paddleslim>=2.2.0
3333
默认根据参数的绝对值大小进行稀疏化,且不稀疏归一化层参数。如果开发者想更改相应的逻辑,可按照下述操作:
3434

3535
- 开发者可以通过重写`paddleslim.dygraph.prune.unstructured_pruner.py`中的`UnstructuredPruner.mask_parameters()``UnstructuredPruner.update_threshold()`来定义自己的非结构化稀疏策略(目前为剪裁掉绝对值小的parameters)。
36-
- 开发可以在初始化`UnstructuredPruner`时,传入自定义的`skip_params_func`,来定义哪些参数不参与剪裁。`skip_params_func`示例代码如下(路径:`paddleslim.dygraph.prune.unstructured_pruner._get_skip_params())`默认为所有的归一化层的参数不参与剪裁
36+
- 开发可以在初始化`UnstructuredPruner`时,传入自定义的`skip_params_func`,来定义哪些参数不参与剪裁。`skip_params_func`示例代码如下(路径:`paddleslim.dygraph.prune.unstructured_pruner._get_skip_params())`默认为所有的归一化层的参数和 `bias` 不参与剪裁
3737

3838
```python
3939
NORMS_ALL = [ 'BatchNorm', 'GroupNorm', 'LayerNorm', 'SpectralNorm', 'BatchNorm1D',
@@ -55,6 +55,8 @@ def _get_skip_params(model):
5555
for _, sub_layer in model.named_sublayers():
5656
if type(sub_layer).__name__.split('.')[-1] in NORMS_ALL:
5757
skip_params.add(sub_layer.full_name())
58+
for param in sub_layer.parameters(include_sublayers=False):
59+
if len(param.shape) == 1: skip_params.add(param.name)
5860
return skip_params
5961
```
6062

demo/dygraph/unstructured_pruning/train.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
add_arg('threshold', float, 0.01, "The threshold to set zeros. Default: 0.01")
3636
add_arg('num_epochs', int, 120, "The number of total epochs. Default: 120")
3737
parser.add_argument('--step_epochs', nargs='+', type=int, default=[30, 60, 90], help="piecewise decay step")
38+
parser.add_argument('--sparse_block', nargs='+', type=int, default=[1, 1], help="There must be two integers inside this array. The array defines the shape of the block, the values within which are either sparsified to all zeros or kept original. [1, 1] means unstructured pruning. Default: [1, 1]")
3839
add_arg('data', str, "imagenet", "Which data to use. 'cifar10' or 'imagenet'. Default: imagenet")
3940
add_arg('log_period', int, 100, "Log period in batches. Default: 100")
4041
add_arg('test_period', int, 5, "Test period in epoches. Default: 5")
@@ -100,13 +101,15 @@ def create_unstructured_pruner(model, args, configs=None):
100101
ratio=args.ratio,
101102
threshold=args.threshold,
102103
prune_params_type=args.prune_params_type,
103-
local_sparsity=args.local_sparsity)
104+
local_sparsity=args.local_sparsity,
105+
sparse_block=args.sparse_block)
104106
else:
105107
return GMPUnstructuredPruner(
106108
model,
107109
ratio=args.ratio,
108110
prune_params_type=args.prune_params_type,
109111
local_sparsity=args.local_sparsity,
112+
sparse_block=args.sparse_block,
110113
configs=configs)
111114

112115

demo/unstructured_prune/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ tar -xf MobileNetV1_pretrained.tar
4242
默认根据参数的绝对值大小进行稀疏化,且不稀疏归一化层参数。如果开发者想更改相应的逻辑,可按照下述操作:
4343

4444
- 可以通过重写`paddleslim.prune.unstructured_pruner.py`中的`UnstructuredPruner.update_threshold()`来定义自己的非结构化稀疏策略(目前为剪裁掉绝对值小的parameters)。
45-
- 可以在初始化`UnstructuredPruner`时,传入自定义的`skip_params_func`,来定义哪些参数不参与剪裁。`skip_params_func`示例代码如下(路径:`paddleslim.prune.unstructured_pruner._get_skip_params()`)。默认为所有的归一化层的参数不参与剪裁
45+
- 可以在初始化`UnstructuredPruner`时,传入自定义的`skip_params_func`,来定义哪些参数不参与剪裁。`skip_params_func`示例代码如下(路径:`paddleslim.prune.unstructured_pruner._get_skip_params()`)。默认为所有的归一化层的参数和 `bias` 不参与剪裁
4646

4747
```python
4848
def _get_skip_params(program):
@@ -61,6 +61,9 @@ def _get_skip_params(program):
6161
if 'norm' in op.type() and 'grad' not in op.type():
6262
for input in op.all_inputs():
6363
skip_params.add(input.name())
64+
for param in program.all_parameters():
65+
if len(param.shape) == 1:
66+
skip_params.add(param.name)
6467
return skip_params
6568
```
6669

demo/unstructured_prune/train.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
add_arg('ratio', float, 0.55, "The ratio to set zeros, the smaller portion will be zeros. Default: 0.55")
4040
add_arg('num_epochs', int, 120, "The number of total epochs. Default: 120")
4141
parser.add_argument('--step_epochs', nargs='+', type=int, default=[30, 60, 90], help="piecewise decay step")
42+
parser.add_argument('--sparse_block', nargs='+', type=int, default=[1, 1], help="There must be two integers inside this array. The array defines the shape of the block, the values within which are either sparsified to all zeros or kept original. [1, 1] means unstructured pruning. Default: [1, 1]")
4243
add_arg('data', str, "imagenet", "Which data to use. 'mnist', 'cifar10' or 'imagenet'. Default: imagenet")
4344
add_arg('log_period', int, 100, "Log period in batches. Default: 100")
4445
add_arg('test_period', int, 5, "Test period in epoches. Default: 5")
@@ -102,14 +103,16 @@ def create_unstructured_pruner(train_program, args, place, configs):
102103
threshold=args.threshold,
103104
prune_params_type=args.prune_params_type,
104105
place=place,
105-
local_sparsity=args.local_sparsity)
106+
local_sparsity=args.local_sparsity,
107+
sparse_block=args.sparse_block)
106108
else:
107109
return GMPUnstructuredPruner(
108110
train_program,
109111
ratio=args.ratio,
110112
prune_params_type=args.prune_params_type,
111113
place=place,
112114
local_sparsity=args.local_sparsity,
115+
sparse_block=args.sparse_block,
113116
configs=configs)
114117

115118

@@ -312,7 +315,6 @@ def train(epoch, program):
312315
fetch_list=[avg_cost.name, acc_top1.name, acc_top5.name])
313316
# GMP pruner step 2: step() to update ratios and other internal states of the pruner.
314317
pruner.step()
315-
316318
train_run_cost += time.time() - train_start
317319
total_samples += args.batch_size
318320
loss_n = np.mean(loss_n)

docs/zh_cn/api_cn/dygraph/pruners/unstructured_pruner.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
UnstructuredPruner
55
----------
66

7-
.. py:class:: paddleslim.UnstructuredPruner(model, mode, threshold=0.01, ratio=0.55, prune_params_type=None, skip_params_func=None, local_sparsity=False)
7+
.. py:class:: paddleslim.UnstructuredPruner(model, mode, threshold=0.01, ratio=0.55, prune_params_type=None, skip_params_func=None, local_sparsity=False, sparse_block=[1,1])
88
99
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/dygraph/prune/unstructured_pruner.py>`_
1010

@@ -17,7 +17,7 @@ UnstructuredPruner
1717
- **ratio(float)** - 稀疏化比例期望,只有在 mode=='ratio' 时才会生效。
1818
- **threshold(float)** - 稀疏化阈值期望,只有在 mode=='threshold' 时才会生效。
1919
- **prune_params_type(String)** - 用以指定哪些类型的参数参与稀疏。目前只支持None和"conv1x1_only"两个选项,后者表示只稀疏化1x1卷积。而前者表示稀疏化除了归一化层的参数。
20-
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数不参与剪裁。示例代码如下:
20+
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数和 bias 不参与剪裁。示例代码如下:
2121

2222
.. code-block:: python
2323
@@ -28,7 +28,7 @@ UnstructuredPruner
2828
def _get_skip_params(model):
2929
"""
3030
This function is used to check whether the given model's layers are valid to be pruned.
31-
Usually, the convolutions are to be pruned while we skip the normalization-related parameters.
31+
Usually, the convolutions are to be pruned while we skip the normalization-related parameters and bias.
3232
Deverlopers could replace this function by passing their own when initializing the UnstructuredPuner instance.
3333
3434
Args:
@@ -40,11 +40,14 @@ UnstructuredPruner
4040
for _, sub_layer in model.named_sublayers():
4141
if type(sub_layer).__name__.split('.')[-1] in NORMS_ALL:
4242
skip_params.add(sub_layer.full_name())
43+
for param in sub_layer.parameters(include_sublayers=False):
44+
if len(param.shape) == 1: skip_params.add(param.name)
4345
return skip_params
4446
4547
..
4648
4749
- **local_sparsity(bool)** - 剪裁比例(ratio)应用的范围:local_sparsity 开启时意味着每个参与剪裁的参数矩阵稀疏度均为 'ratio', 关闭时表示只保证模型整体稀疏度达到'ratio',但是每个参数矩阵的稀疏度可能存在差异。
50+
- **sparse_block(Array<Integer>)** - 一个含有两个正整数的数组,定义了稀疏化时候block的大小。即 sparse_block[0] x sparse_block[1]中的参数作为一个整体,要么被置0,要么保持不变。默认为 [1,1],代表非结构化稀疏。
4851

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

@@ -245,6 +248,7 @@ GMPUnstructuredPruner
245248
- **prune_params_type(str)** - 用以指定哪些类型的参数参与稀疏。目前只支持None和"conv1x1_only"两个选项,后者表示只稀疏化1x1卷积。而前者表示稀疏化除了归一化层的参数。
246249
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数不参与剪裁。
247250
- **local_sparsity(bool)** - 剪裁比例(ratio)应用的范围:local_sparsity 开启时意味着每个参与剪裁的参数矩阵稀疏度均为 'ratio', 关闭时表示只保证模型整体稀疏度达到'ratio',但是每个参数矩阵的稀疏度可能存在差异。
251+
- **sparse_block(Array<Integer>)** - 一个含有两个正整数的数组,定义了稀疏化时候block的大小。即 sparse_block[0] x sparse_block[1]中的参数作为一个整体,要么被置0,要么保持不变。默认为 [1,1],代表非结构化稀疏。
248252
- **configs(Dict)** - 传入额外的训练超参用以指导GMP训练过程。各参数介绍如下:
249253

250254
.. code-block:: python

docs/zh_cn/api_cn/static/prune/unstructured_prune_api.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
UnstrucuturedPruner
55
----------
66

7-
.. py:class:: paddleslim.prune.UnstructuredPruner(program, mode, ratio=0.55, threshold=1e-2, scope=None, place=None, prune_params_type, skip_params_func=None, local_sparsity=False)
7+
.. py:class:: paddleslim.prune.UnstructuredPruner(program, mode, ratio=0.55, threshold=1e-2, scope=None, place=None, prune_params_type, skip_params_func=None, local_sparsity=False, sparse_block=[1,1])
88
99
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/prune/unstructured_pruner.py>`_
1010

@@ -19,14 +19,14 @@ UnstrucuturedPruner
1919
- **scope(paddle.static.Scope)** - 一个paddle.static.Scope对象,存储了所有变量的数值,默认(None)时表示paddle.static.global_scope。
2020
- **place(CPUPlace|CUDAPlace)** - 模型执行的设备,类型为CPUPlace或者CUDAPlace,默认(None)时代表CPUPlace。
2121
- **prune_params_type(String)** - 用以指定哪些类型的参数参与稀疏。目前只支持None和"conv1x1_only"两个选项,后者表示只稀疏化1x1卷积。而前者表示稀疏化除了归一化的参数。
22-
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数不参与剪裁
22+
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数和 bias 不参与剪裁
2323

2424
.. code-block:: python
2525
2626
def _get_skip_params(program):
2727
"""
2828
The function is used to get a set of all the skipped parameters when performing pruning.
29-
By default, the normalization-related ones will not be pruned.
29+
By default, the normalization-related ones and bias will not be pruned.
3030
Developers could replace it by passing their own function when initializing the UnstructuredPruner instance.
3131
Args:
3232
- program(paddle.static.Program): the current model.
@@ -39,11 +39,15 @@ UnstrucuturedPruner
3939
if 'norm' in op.type() and 'grad' not in op.type():
4040
for input in op.all_inputs():
4141
skip_params.add(input.name())
42+
for param in program.all_parameters():
43+
if len(param.shape) == 1:
44+
skip_params.add(param.name)
4245
return skip_params
4346
4447
..
4548
4649
- **local_sparsity(bool)** - 剪裁比例(ratio)应用的范围:local_sparsity 开启时意味着每个参与剪裁的参数矩阵稀疏度均为 'ratio', 关闭时表示只保证模型整体稀疏度达到'ratio',但是每个参数矩阵的稀疏度可能存在差异。
50+
- **sparse_block(Array<Integer>)** - 一个含有两个正整数的数组,定义了稀疏化时候block的大小。即 sparse_block[0] x sparse_block[1]中的参数作为一个整体,要么被置0,要么保持不变。默认为 [1,1],代表非结构化稀疏。
4751

4852
**返回:** 一个UnstructuredPruner类的实例
4953

@@ -339,6 +343,8 @@ GMPUnstrucuturedPruner
339343
- **prune_params_type(String)** - 用以指定哪些类型的参数参与稀疏。目前只支持None和"conv1x1_only"两个选项,后者表示只稀疏化1x1卷积。而前者表示稀疏化除了归一化的参数。
340344
- **skip_params_func(function)** - 一个指向function的指针,该function定义了哪些参数不应该被剪裁,默认(None)时代表所有归一化层参数不参与剪裁。
341345
- **local_sparsity(bool)** - 剪裁比例(ratio)应用的范围:local_sparsity 开启时意味着每个参与剪裁的参数矩阵稀疏度均为 'ratio', 关闭时表示只保证模型整体稀疏度达到'ratio',但是每个参数矩阵的稀疏度可能存在差异。
346+
- **sparse_block(Array<Integer>)** - 一个含有两个正整数的数组,定义了稀疏化时候block的大小。即 sparse_block[0] x sparse_block[1]中的参数作为一个整体,要么被置0,要么保持不变。默认为 [1,1],代表非结构化稀疏。
347+
342348
- **configs(Dict)** - 传入额外的训练超参用以指导GMP训练过程。具体描述如下:
343349

344350
.. code-block:: python

0 commit comments

Comments
 (0)