Skip to content

Commit 0a4dbe1

Browse files
authored
add user defined function support in quantization and unittest and demo (#319)
1 parent 8b0005b commit 0a4dbe1

File tree

11 files changed

+1098
-12
lines changed

11 files changed

+1098
-12
lines changed

demo/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .mobilenet_v2 import MobileNetV2_x0_25, MobileNetV2
66
from .pvanet import PVANet
77
from .slimfacenet import SlimFaceNet_A_x0_60, SlimFaceNet_B_x0_75, SlimFaceNet_C_x0_75
8+
from .mobilenet_v3 import *
89
__all__ = [
910
"model_list", "MobileNet", "ResNet34", "ResNet50", "MobileNetV2", "PVANet",
1011
"ResNet50_vd", "ResNet101_vd", "MobileNetV2_x0_25"
@@ -13,3 +14,6 @@
1314
'MobileNet', 'ResNet34', 'ResNet50', 'MobileNetV2', 'PVANet',
1415
'ResNet50_vd', "ResNet101_vd", "MobileNetV2_x0_25"
1516
]
17+
18+
__all__ += mobilenet_v3.__all__
19+
model_list += mobilenet_v3.__all__

demo/models/mobilenet_v3.py

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import paddle.fluid as fluid
2+
from paddle.fluid.initializer import MSRA
3+
from paddle.fluid.param_attr import ParamAttr
4+
import math
5+
6+
__all__ = [
7+
'MobileNetV3', 'MobileNetV3_small_x0_25', 'MobileNetV3_small_x0_5',
8+
'MobileNetV3_small_x0_75', 'MobileNetV3_small_x1_0',
9+
'MobileNetV3_small_x1_25', 'MobileNetV3_large_x0_25',
10+
'MobileNetV3_large_x0_5', 'MobileNetV3_large_x0_75',
11+
'MobileNetV3_large_x1_0', 'MobileNetV3_large_x1_25',
12+
'MobileNetV3_large_x2_0'
13+
]
14+
15+
16+
class MobileNetV3():
17+
def __init__(self, scale=1.0, model_name='small'):
18+
self.scale = scale
19+
self.inplanes = 16
20+
if model_name == "large":
21+
self.cfg = [
22+
# k, exp, c, se, nl, s,
23+
[3, 16, 16, False, 'relu', 1],
24+
[3, 64, 24, False, 'relu', 2],
25+
[3, 72, 24, False, 'relu', 1],
26+
[5, 72, 40, True, 'relu', 2],
27+
[5, 120, 40, True, 'relu', 1],
28+
[5, 120, 40, True, 'relu', 1],
29+
[3, 240, 80, False, 'hard_swish', 2],
30+
[3, 200, 80, False, 'hard_swish', 1],
31+
[3, 184, 80, False, 'hard_swish', 1],
32+
[3, 184, 80, False, 'hard_swish', 1],
33+
[3, 480, 112, True, 'hard_swish', 1],
34+
[3, 672, 112, True, 'hard_swish', 1],
35+
[5, 672, 160, True, 'hard_swish', 2],
36+
[5, 960, 160, True, 'hard_swish', 1],
37+
[5, 960, 160, True, 'hard_swish', 1],
38+
]
39+
self.cls_ch_squeeze = 960
40+
self.cls_ch_expand = 1280
41+
elif model_name == "small":
42+
self.cfg = [
43+
# k, exp, c, se, nl, s,
44+
[3, 16, 16, True, 'relu', 2],
45+
[3, 72, 24, False, 'relu', 2],
46+
[3, 88, 24, False, 'relu', 1],
47+
[5, 96, 40, True, 'hard_swish', 2],
48+
[5, 240, 40, True, 'hard_swish', 1],
49+
[5, 240, 40, True, 'hard_swish', 1],
50+
[5, 120, 48, True, 'hard_swish', 1],
51+
[5, 144, 48, True, 'hard_swish', 1],
52+
[5, 288, 96, True, 'hard_swish', 2],
53+
[5, 576, 96, True, 'hard_swish', 1],
54+
[5, 576, 96, True, 'hard_swish', 1],
55+
]
56+
self.cls_ch_squeeze = 576
57+
self.cls_ch_expand = 1280
58+
else:
59+
raise NotImplementedError
60+
61+
def net(self, input, class_dim=1000):
62+
scale = self.scale
63+
inplanes = self.inplanes
64+
cfg = self.cfg
65+
cls_ch_squeeze = self.cls_ch_squeeze
66+
cls_ch_expand = self.cls_ch_expand
67+
68+
#conv1
69+
conv = self.conv_bn_layer(
70+
input,
71+
filter_size=3,
72+
#num_filters=int(scale*inplanes),
73+
num_filters=inplanes if scale <= 1.0 else int(inplanes * scale),
74+
stride=2,
75+
padding=1,
76+
num_groups=1,
77+
if_act=True,
78+
act='hard_swish',
79+
name='conv1')
80+
print(conv.shape)
81+
i = 0
82+
for layer_cfg in cfg:
83+
conv = self.residual_unit(
84+
input=conv,
85+
num_in_filter=inplanes,
86+
num_mid_filter=int(scale * layer_cfg[1]),
87+
num_out_filter=int(scale * layer_cfg[2]),
88+
act=layer_cfg[4],
89+
stride=layer_cfg[5],
90+
filter_size=layer_cfg[0],
91+
use_se=layer_cfg[3],
92+
name='conv' + str(i + 2))
93+
94+
inplanes = int(scale * layer_cfg[2])
95+
i += 1
96+
97+
conv = self.conv_bn_layer(
98+
input=conv,
99+
filter_size=1,
100+
num_filters=int(scale * cls_ch_squeeze),
101+
stride=1,
102+
padding=0,
103+
num_groups=1,
104+
if_act=True,
105+
act='hard_swish',
106+
name='conv_last')
107+
conv = fluid.layers.pool2d(
108+
input=conv, pool_type='avg', global_pooling=True, use_cudnn=False)
109+
conv = fluid.layers.conv2d(
110+
input=conv,
111+
num_filters=cls_ch_expand,
112+
filter_size=1,
113+
stride=1,
114+
padding=0,
115+
act=None,
116+
param_attr=ParamAttr(name='last_1x1_conv_weights'),
117+
bias_attr=False)
118+
#conv = fluid.layers.hard_swish(conv)
119+
conv = self.hard_swish(conv)
120+
out = fluid.layers.fc(input=conv,
121+
size=class_dim,
122+
act='softmax',
123+
param_attr=ParamAttr(name='fc_weights'),
124+
bias_attr=ParamAttr(name='fc_offset'))
125+
return out
126+
127+
def conv_bn_layer(self,
128+
input,
129+
filter_size,
130+
num_filters,
131+
stride,
132+
padding,
133+
num_groups=1,
134+
if_act=True,
135+
act=None,
136+
name=None,
137+
use_cudnn=True):
138+
conv = fluid.layers.conv2d(
139+
input=input,
140+
num_filters=num_filters,
141+
filter_size=filter_size,
142+
stride=stride,
143+
padding=padding,
144+
groups=num_groups,
145+
act=None,
146+
use_cudnn=use_cudnn,
147+
param_attr=ParamAttr(name=name + '_weights'),
148+
bias_attr=False)
149+
bn_name = name + '_bn'
150+
bn = fluid.layers.batch_norm(
151+
input=conv,
152+
param_attr=ParamAttr(
153+
name=bn_name + "_scale",
154+
regularizer=fluid.regularizer.L2DecayRegularizer(
155+
regularization_coeff=0.0)),
156+
bias_attr=ParamAttr(
157+
name=bn_name + "_offset",
158+
regularizer=fluid.regularizer.L2DecayRegularizer(
159+
regularization_coeff=0.0)),
160+
moving_mean_name=bn_name + '_mean',
161+
moving_variance_name=bn_name + '_variance')
162+
if if_act:
163+
if act == 'relu':
164+
bn = fluid.layers.relu(bn)
165+
elif act == 'hard_swish':
166+
#bn = fluid.layers.hard_swish(bn)
167+
bn = self.hard_swish(bn)
168+
return bn
169+
170+
def hard_swish(self, x):
171+
return x * fluid.layers.relu6(x + 3) / 6.
172+
173+
def se_block(self, input, num_out_filter, ratio=4, name=None):
174+
num_mid_filter = int(num_out_filter // ratio)
175+
pool = fluid.layers.pool2d(
176+
input=input, pool_type='avg', global_pooling=True, use_cudnn=False)
177+
conv1 = fluid.layers.conv2d(
178+
input=pool,
179+
filter_size=1,
180+
num_filters=num_mid_filter,
181+
act='relu',
182+
param_attr=ParamAttr(name=name + '_1_weights'),
183+
bias_attr=ParamAttr(name=name + '_1_offset'))
184+
conv2 = fluid.layers.conv2d(
185+
input=conv1,
186+
filter_size=1,
187+
num_filters=num_out_filter,
188+
act='hard_sigmoid',
189+
param_attr=ParamAttr(name=name + '_2_weights'),
190+
bias_attr=ParamAttr(name=name + '_2_offset'))
191+
192+
scale = fluid.layers.elementwise_mul(x=input, y=conv2, axis=0)
193+
return scale
194+
195+
def residual_unit(self,
196+
input,
197+
num_in_filter,
198+
num_mid_filter,
199+
num_out_filter,
200+
stride,
201+
filter_size,
202+
act=None,
203+
use_se=False,
204+
name=None):
205+
206+
input_data = input
207+
conv0 = self.conv_bn_layer(
208+
input=input,
209+
filter_size=1,
210+
num_filters=num_mid_filter,
211+
stride=1,
212+
padding=0,
213+
if_act=True,
214+
act=act,
215+
name=name + '_expand')
216+
217+
conv1 = self.conv_bn_layer(
218+
input=conv0,
219+
filter_size=filter_size,
220+
num_filters=num_mid_filter,
221+
stride=stride,
222+
padding=int((filter_size - 1) // 2),
223+
if_act=True,
224+
act=act,
225+
num_groups=num_mid_filter,
226+
use_cudnn=False,
227+
name=name + '_depthwise')
228+
229+
if use_se:
230+
with fluid.name_scope('se_block_skip'):
231+
conv1 = self.se_block(
232+
input=conv1,
233+
num_out_filter=num_mid_filter,
234+
name=name + '_se')
235+
236+
conv2 = self.conv_bn_layer(
237+
input=conv1,
238+
filter_size=1,
239+
num_filters=num_out_filter,
240+
stride=1,
241+
padding=0,
242+
if_act=False,
243+
name=name + '_linear')
244+
if num_in_filter != num_out_filter or stride != 1:
245+
return conv2
246+
else:
247+
return fluid.layers.elementwise_add(
248+
x=input_data, y=conv2, act=None)
249+
250+
251+
def MobileNetV3_small_x0_25():
252+
model = MobileNetV3(model_name='small', scale=0.25)
253+
return model
254+
255+
256+
def MobileNetV3_small_x0_5():
257+
model = MobileNetV3(model_name='small', scale=0.5)
258+
return model
259+
260+
261+
def MobileNetV3_small_x0_75():
262+
model = MobileNetV3(model_name='small', scale=0.75)
263+
return model
264+
265+
266+
def MobileNetV3_small_x1_0():
267+
model = MobileNetV3(model_name='small', scale=1.0)
268+
return model
269+
270+
271+
def MobileNetV3_small_x1_25():
272+
model = MobileNetV3(model_name='small', scale=1.25)
273+
return model
274+
275+
276+
def MobileNetV3_large_x0_25():
277+
model = MobileNetV3(model_name='large', scale=0.25)
278+
return model
279+
280+
281+
def MobileNetV3_large_x0_5():
282+
model = MobileNetV3(model_name='large', scale=0.5)
283+
return model
284+
285+
286+
def MobileNetV3_large_x0_75():
287+
model = MobileNetV3(model_name='large', scale=0.75)
288+
return model
289+
290+
291+
def MobileNetV3_large_x1_0():
292+
model = MobileNetV3(model_name='large', scale=1.0)
293+
return model
294+
295+
296+
def MobileNetV3_large_x1_25():
297+
model = MobileNetV3(model_name='large', scale=1.25)
298+
return model
299+
300+
301+
def MobileNetV3_large_x2_0():
302+
model = MobileNetV3(model_name='large', scale=2.0)
303+
return model

0 commit comments

Comments
 (0)