Skip to content

Commit 09bc9c0

Browse files
authored
Move the ASP training API to paddle.static.sparsity. (#36525) (#36860)
Cherry-pick #36525
1 parent f2daef5 commit 09bc9c0

14 files changed

+277
-142
lines changed

python/paddle/fluid/contrib/sparsity/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
from .utils import check_sparsity
2626
from .utils import MaskAlgo
2727
from .utils import CheckMethod
28-
from .asp import decorate, prune_model
29-
from .asp import set_excluded_layers, reset_excluded_layers
28+
from .asp import decorate
29+
from .asp import prune_model
30+
from .asp import set_excluded_layers
31+
from .asp import reset_excluded_layers
3032

3133
__all__ = [
3234
'calculate_density', 'check_mask_1d', 'get_mask_1d', 'check_mask_2d',

python/paddle/fluid/contrib/sparsity/asp.py

+111-51
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
import copy
2020
import numpy as np
2121
import paddle
22-
from paddle.fluid import framework, global_scope, program_guard, layers
22+
from paddle.fluid import global_scope, program_guard, layers
2323
from paddle.fluid.initializer import ConstantInitializer
2424
from paddle.fluid.contrib import sparsity
25-
from paddle.fluid import core
2625

2726
__all__ = [
2827
'decorate', 'prune_model', 'set_excluded_layers', 'reset_excluded_layers'
@@ -36,6 +35,35 @@ def set_excluded_layers(main_program, param_names):
3635
Args:
3736
main_program (Program, optional): Program with model definition and its parameters.
3837
param_names (list): A list contains names of parameters.
38+
Examples:
39+
.. code-block:: python
40+
41+
import paddle
42+
from paddle.static import sparsity
43+
44+
paddle.enable_static()
45+
46+
main_program = paddle.static.Program()
47+
startup_program = paddle.static.Program()
48+
49+
with paddle.static.program_guard(main_program, startup_program):
50+
input_data = paddle.static.data(name='data', shape=[None, 128])
51+
label = paddle.static.data(name='label', shape=[None, 10])
52+
hidden = paddle.static.nn.fc(x=input_data, num_flatten_dims=-1, size=32, activation=None, name="need_sparse_fc")
53+
hidden = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=32, activation=None, name="need_dense_fc")
54+
prob = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=10, activation=None)
55+
loss = paddle.mean(paddle.nn.functional.square_error_cost(prob, label))
56+
57+
# Setup exluded layers out from ASP workflow.
58+
# Please note, excluded_layers must be set before calling `optimizer.minimize()`.
59+
sparsity.set_excluded_layers(main_program, ["need_dense_fc"])
60+
61+
optimizer = paddle.optimizer.SGD(learning_rate=0.1)
62+
optimizer = paddle.static.amp.decorate(optimizer )
63+
# Calling sparsity.decorate() to wrap minimize() in optimizer, which
64+
# will insert necessary masking operations for ASP workflow.
65+
optimizer = sparsity.decorate(optimizer)
66+
optimizer.minimize(loss, startup_program)
3967
"""
4068
ASPHelper.set_excluded_layers(
4169
main_program=main_program, param_names=param_names)
@@ -48,6 +76,33 @@ def reset_excluded_layers(main_program=None):
4876
4977
Args:
5078
main_program (Program, optional): Program with model definition and its parameters.
79+
Examples:
80+
.. code-block:: python
81+
82+
import paddle
83+
from paddle.static import sparsity
84+
85+
paddle.enable_static()
86+
87+
main_program = paddle.static.Program()
88+
startup_program = paddle.static.Program()
89+
90+
with paddle.static.program_guard(main_program, startup_program):
91+
input_data = paddle.static.data(name='data', shape=[None, 128])
92+
label = paddle.static.data(name='label', shape=[None, 10])
93+
hidden = paddle.static.nn.fc(x=input_data, num_flatten_dims=-1, size=32, activation=None, name="my_first_fc")
94+
hidden = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=32, activation=None, name="my_second_fc")
95+
prob = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=10, activation=None)
96+
loss = paddle.mean(paddle.nn.functional.square_error_cost(prob, label))
97+
98+
# Setup exluded layers out from ASP workflow.
99+
# Please note, excluded_layers must be set before calling `optimizer.minimize()`.
100+
sparsity.set_excluded_layers(main_program, ["my_second_fc"])
101+
# Now the weights of "my_second_fc" would not be included in Automatic SParsity's workflow.
102+
103+
# Reset excluded_layers, all FC layers would be included into Automatic SParsity's workflow.
104+
# Please note, reset_excluded_layers also must be called before calling `optimizer.minimize()`.
105+
sparsity.reset_excluded_layers(main_program)
51106
"""
52107
ASPHelper.reset_excluded_layers(main_program=main_program)
53108

@@ -65,22 +120,21 @@ def decorate(optimizer):
65120
.. code-block:: python
66121
67122
import paddle
68-
import paddle.fluid as fluid
69-
from paddle.fluid.contrib import sparsity
123+
from paddle.static import sparsity
70124
71-
main_program = fluid.Program()
72-
startup_program = fluid.Program()
125+
main_program = paddle.static.Program()
126+
startup_program = paddle.static.Program()
73127
74128
paddle.enable_static()
75129
76-
with fluid.program_guard(main_program, startup_program):
77-
input_data = fluid.layers.data(name='data', shape=[None, 128])
78-
label = fluid.layers.data(name='label', shape=[None, 10])
79-
hidden = fluid.layers.fc(input=input_data, num_flatten_dims=-1, size=32, act=None)
80-
prob = fluid.layers.fc(input=hidden, num_flatten_dims=-1, size=10, act=None)
81-
loss = fluid.layers.mean(fluid.layers.square_error_cost(prob, label))
130+
with paddle.static.program_guard(main_program, startup_program):
131+
input_data = paddle.static.data(name='data', shape=[None, 128])
132+
label = paddle.static.data(name='label', shape=[None, 10])
133+
hidden = paddle.static.nn.fc(x=input_data, num_flatten_dims=-1, size=32, activation=None)
134+
prob = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=10, activation=None)
135+
loss = paddle.mean(paddle.nn.functional.square_error_cost(prob, label))
82136
83-
optimizer = fluid.optimizer.SGD(learning_rate=0.1)
137+
optimizer = paddle.optimizer.SGD(learning_rate=0.1)
84138
optimizer = sparsity.decorate(optimizer)
85139
# if do sparse training with Fleet, please replace above decorate with:
86140
# strategy = paddle.distributed.fleet.DistributedStrategy()
@@ -92,15 +146,14 @@ def decorate(optimizer):
92146
return ASPHelper.decorate(optimizer)
93147

94148

95-
def prune_model(place,
96-
main_program=None,
149+
def prune_model(main_program=None,
97150
n=2,
98151
m=4,
99-
func_name=sparsity.MaskAlgo.MASK_1D,
152+
mask_algo='mask_1d',
100153
with_mask=True):
101154
r"""
102155
Pruning parameters of supported layers in :attr:`main_program` via
103-
specified mask generation function given by :attr:`func_name`. This
156+
specified mask generation function given by :attr:`mask_algo`. This
104157
function supports both training and inference controlled by :attr:`with_mask`.
105158
If :attr:`with_mask` is True, it would also prune parameter related ASP mask Variables,
106159
else only prunes parameters.
@@ -114,62 +167,70 @@ def prune_model(place,
114167
inference only. To obtain OptimizerWithSparsityGuarantee, please see `sparsity.decoreate()`.
115168
116169
Args:
117-
place (fluid.CPUPlace()|fluid.CUDAPlace(N)): Device place for pruned parameter and mask Variables, and N means the GPU's id. It should be the same as created instance of Executor.
118170
main_program (Program, optional): Program with model definition and its parameters. Default is `paddle.static.default_main_program()
119171
n (int): n of `n:m` sparse pattern.
120172
m (int): m of `n:m` sparse pattern.
121-
func_name (MaskAlgo, optional): The function name to generate spase mask. Default is `MaskAlgo.MASK_1D`. All options please refer to `MaskAlgo`.
173+
mask_algo (string, optional): The function name to generate spase mask. Default is `mask_1d`.
174+
The vaild inputs should be one of 'mask_1d', 'mask_2d_greedy' and 'mask_2d_best'.
122175
with_mask (bool, optional): To prune mask Variables related to parameters or not. Ture is purning also, False is not. Defalut is True.
123176
Returns:
124177
dictionary: A dictionary with key: `parameter name` (string) and value: its corresponding mask Variable.
125178
Examples:
126179
.. code-block:: python
127180
128181
import paddle
129-
import paddle.fluid as fluid
130-
import paddle.fluid.core as core
131-
from paddle.fluid.contrib import sparsity
182+
from paddle.static import sparsity
132183
133184
paddle.enable_static()
134185
135-
main_program = fluid.Program()
136-
startup_program = fluid.Program()
186+
main_program = paddle.static.Program()
187+
startup_program = paddle.static.Program()
137188
138-
place = paddle.CPUPlace()
139-
if core.is_compiled_with_cuda():
140-
place = paddle.CUDAPlace(0)
141-
142-
with fluid.program_guard(main_program, startup_program):
143-
input_data = fluid.layers.data(name='data', shape=[None, 128])
144-
label = fluid.layers.data(name='label', shape=[None, 10])
145-
hidden = fluid.layers.fc(input=input_data, num_flatten_dims=-1, size=32, act=None, name="need_sparse")
146-
hidden = fluid.layers.fc(input=hidden, num_flatten_dims=-1, size=32, act=None, name="need_dense")
147-
prob = fluid.layers.fc(input=hidden, num_flatten_dims=-1, size=10, act=None)
148-
loss = fluid.layers.mean(fluid.layers.square_error_cost(prob, label))
189+
with paddle.static.program_guard(main_program, startup_program):
190+
input_data = paddle.static.data(name='data', shape=[None, 128])
191+
label = paddle.static.data(name='label', shape=[None, 10])
192+
hidden = paddle.static.nn.fc(x=input_data, num_flatten_dims=-1, size=32, activation=None, name="need_sparse_fc")
193+
hidden = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=32, activation=None, name="need_dense_fc")
194+
prob = paddle.static.nn.fc(x=hidden, num_flatten_dims=-1, size=10, activation=None)
195+
loss = paddle.mean(paddle.nn.functional.square_error_cost(prob, label))
149196
150197
# Setup exluded layers out from ASP workflow.
151198
# Please note, excluded_layers must be set before calling `optimizer.minimize()`.
152-
sparsity.set_excluded_layers(main_program, ["need_dense"])
199+
sparsity.set_excluded_layers(main_program, ["need_dense_fc"])
153200
154-
optimizer = fluid.optimizer.SGD(learning_rate=0.1)
155-
optimizer = fluid.contrib.mixed_precision.decorator.decorate(optimizer )
201+
optimizer = paddle.optimizer.SGD(learning_rate=0.1)
202+
optimizer = paddle.static.amp.decorate(optimizer )
156203
# Calling sparsity.decorate() to wrap minimize() in optimizer, which
157204
# will insert necessary masking operations for ASP workflow.
158205
optimizer = sparsity.decorate(optimizer)
159206
optimizer.minimize(loss, startup_program)
160207
161-
exe = fluid.Executor(place)
208+
device = paddle.device.get_device()
209+
place = paddle.set_device(device)
210+
211+
exe = paddle.static.Executor(place)
162212
exe.run(startup_program)
163213
164214
# Must call `exe.run(startup_program)` first before calling `sparsity.prune_model`
165-
sparsity.prune_model(place, main_program, func_name=sparsity.MaskAlgo.MASK_2D_BEST)
215+
sparsity.prune_model(main_program, mask_algo='mask_2d_best')
166216
"""
217+
device = paddle.device.get_device()
218+
place = paddle.set_device(device)
219+
220+
MaskAlgo_mapping = {
221+
'mask_1d': sparsity.MaskAlgo.MASK_1D,
222+
'mask_2d_greedy': sparsity.MaskAlgo.MASK_2D_GREEDY,
223+
'mask_2d_best': sparsity.MaskAlgo.MASK_2D_BEST
224+
}
225+
assert (mask_algo in MaskAlgo_mapping), \
226+
'The "mask_algo" should be one of ["mask_1d", "mask_2d_greedy", "mask_2d_best"]'
227+
167228
return ASPHelper.prune_model(
168229
place=place,
169230
main_program=main_program,
170231
n=n,
171232
m=m,
172-
func_name=func_name,
233+
mask_algo=MaskAlgo_mapping[mask_algo],
173234
with_mask=with_mask)
174235

175236

@@ -256,12 +317,12 @@ def prune_model(cls,
256317
main_program=None,
257318
n=2,
258319
m=4,
259-
func_name=sparsity.MaskAlgo.MASK_1D,
320+
mask_algo=sparsity.MaskAlgo.MASK_1D,
260321
with_mask=True):
261322
r"""
262323
This is the implementation of `sparsity.prune_model`, for details please see explanation in `sparsity.prune_model`.
263324
"""
264-
checked_func_name = sparsity.CheckMethod.get_checking_method(func_name)
325+
checked_func_name = sparsity.CheckMethod.get_checking_method(mask_algo)
265326

266327
if main_program is None:
267328
main_program = paddle.static.default_main_program()
@@ -284,7 +345,7 @@ def prune_model(cls,
284345
# matrices beforce invoking create_mask. Then we transpose the result maks to make
285346
# sure its shape to be the same as the input weight.
286347
weight_sparse_mask = sparsity.create_mask(
287-
weight_nparray.T, func_name=func_name, n=n, m=m).T
348+
weight_nparray.T, func_name=mask_algo, n=n, m=m).T
288349
weight_pruned_nparray = np.multiply(weight_nparray,
289350
weight_sparse_mask)
290351
weight_tensor.set(weight_pruned_nparray, place)
@@ -347,15 +408,14 @@ def _is_supported_layer(cls, main_program, param_name):
347408
Examples:
348409
.. code-block:: python
349410
350-
import paddle.fluid as fluid
351-
from paddle.fluid.contrib.sparsity.asp import ASPHelper
411+
from paddle.static.sparsity.asp import ASPHelper
352412
353-
main_program = fluid.Program()
354-
startup_program = fluid.Program()
413+
main_program = paddle.static.Program()
414+
startup_program = paddle.static.Program()
355415
356-
with fluid.program_guard(main_program, startup_program):
357-
input_data = fluid.layers.data(name='data', shape=[None, 128])
358-
fc = fluid.layers.fc(input=input_data, num_flatten_dims=-1, size=32, act=None)
416+
with paddle.static.program_guard(main_program, startup_program):
417+
input_data = paddle.static.data(name='data', shape=[None, 128])
418+
fc = paddle.static.nn.fc(x=input_data, num_flatten_dims=-1, size=32, activation=None)
359419
360420
for param in main_program.global_block().all_parameters():
361421
ASPHelper._is_supported_layer(main_program, param.name)

python/paddle/fluid/contrib/sparsity/utils.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def get_checking_method(mask_algo):
6464
.. code-block:: python
6565
6666
import numpy as np
67-
from paddle.fluid.contrib.sparsity import MaskAlgo, CheckMethod
67+
from paddle.static.sparsity import MaskAlgo
68+
from paddle.fluid.contrib.sparsity import CheckMethod
6869
6970
CheckMethod.get_checking_method(MaskAlgo.MASK_1D)
7071
# CheckMethod.CHECK_1D
@@ -95,7 +96,7 @@ def calculate_density(x):
9596
.. code-block:: python
9697
9798
import numpy as np
98-
import paddle.fluid.contrib.sparsity as sparsity
99+
import paddle.static.sparsity as sparsity
99100
100101
x = np.array([[0, 1, 3, 0],
101102
[1, 1, 0, 1]])
@@ -446,7 +447,7 @@ def get_mask_2d_best(mat, n, m):
446447
[5, 6, 3, 9],
447448
[2, 4, 6, 9]])
448449
mask_greedy = sparsity.get_mask_2d_greedy(mat, 2, 4)
449-
mask_greedy = sparsity.get_mask_2d_best(mat, 2, 4)
450+
mask_best = sparsity.get_mask_2d_best(mat, 2, 4)
450451
print("L1 norm of `greedy` sparse matrix", np.multiply(mat, mask_greedy).sum()) # 56
451452
print("L1 norm of `best` sparse matrix", np.multiply(mat, mask_best).sum()) # 61
452453
"""

python/paddle/fluid/tests/unittests/asp/asp_pruning_base.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import paddle
2121
import paddle.fluid as fluid
2222
import paddle.fluid.core as core
23-
from paddle.fluid.contrib import sparsity
23+
from paddle.static import sparsity
2424
from paddle.fluid.contrib.sparsity.asp import ASPHelper
2525
import numpy as np
2626

@@ -76,14 +76,11 @@ def __pruning_and_checking(self, exe, place, mask_func_name,
7676
check_func_name, with_mask):
7777
exe.run(self.startup_program)
7878
sparsity.prune_model(
79-
place,
80-
self.main_program,
81-
func_name=mask_func_name,
82-
with_mask=with_mask)
79+
self.main_program, mask_algo=mask_func_name, with_mask=with_mask)
8380
for param in self.main_program.global_block().all_parameters():
8481
if ASPHelper._is_supported_layer(self.main_program, param.name):
8582
mat = np.array(fluid.global_scope().find_var(param.name)
8683
.get_tensor())
8784
self.assertTrue(
88-
sparsity.check_sparsity(
85+
paddle.fluid.contrib.sparsity.check_sparsity(
8986
mat.T, func_name=check_func_name, n=2, m=4))

python/paddle/fluid/tests/unittests/asp/test_asp_optimize.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import paddle
2121
import paddle.fluid as fluid
2222
import paddle.fluid.core as core
23-
from paddle.fluid.contrib import sparsity
23+
from paddle.static import sparsity
2424
from paddle.fluid.contrib.sparsity.asp import ASPHelper
2525
import numpy as np
2626

@@ -129,7 +129,7 @@ def test_asp_training(self):
129129
feeder = fluid.DataFeeder(feed_list=[self.img, self.label], place=place)
130130

131131
exe.run(self.startup_program)
132-
sparsity.prune_model(place, self.main_program)
132+
sparsity.prune_model(self.main_program)
133133

134134
data = (np.random.randn(64, 3, 32, 32), np.random.randint(
135135
10, size=(64, 1)))
@@ -139,7 +139,9 @@ def test_asp_training(self):
139139
if ASPHelper._is_supported_layer(self.main_program, param.name):
140140
mat = np.array(fluid.global_scope().find_var(param.name)
141141
.get_tensor())
142-
self.assertTrue(sparsity.check_sparsity(mat.T, n=2, m=4))
142+
self.assertTrue(
143+
paddle.fluid.contrib.sparsity.check_sparsity(
144+
mat.T, n=2, m=4))
143145

144146
def test_asp_training_with_amp(self):
145147
if core.is_compiled_with_cuda():
@@ -155,7 +157,7 @@ def test_asp_training_with_amp(self):
155157
feed_list=[self.img, self.label], place=place)
156158

157159
exe.run(self.startup_program)
158-
sparsity.prune_model(place, self.main_program)
160+
sparsity.prune_model(self.main_program)
159161

160162
data = (np.random.randn(64, 3, 32, 32), np.random.randint(
161163
10, size=(64, 1)))
@@ -165,7 +167,9 @@ def test_asp_training_with_amp(self):
165167
if ASPHelper._is_supported_layer(self.main_program, param.name):
166168
mat = np.array(fluid.global_scope().find_var(param.name)
167169
.get_tensor())
168-
self.assertTrue(sparsity.check_sparsity(mat.T, n=2, m=4))
170+
self.assertTrue(
171+
paddle.fluid.contrib.sparsity.check_sparsity(
172+
mat.T, n=2, m=4))
169173

170174
def __get_param_names(self, params):
171175
param_names = []

0 commit comments

Comments
 (0)