diff --git a/paddleslim/tests/quant_test/imagenet_reader.py b/paddleslim/tests/quant_test/imagenet_reader.py deleted file mode 100644 index b6f27c9681315095c43752398313ab770275e3ea..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/imagenet_reader.py +++ /dev/null @@ -1,207 +0,0 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License" -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import math -import random -import functools -import numpy as np -import paddle -from PIL import Image, ImageEnhance - -random.seed(0) -np.random.seed(0) - -DATA_DIM = 224 - -THREAD = 16 -BUF_SIZE = 10240 - -DATA_DIR = '../data/ILSVRC2012' -DATA_DIR = os.path.join(os.path.split(os.path.realpath(__file__))[0], DATA_DIR) - - -img_mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1)) -img_std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1)) - - -def resize_short(img, target_size): - percent = float(target_size) / min(img.size[0], img.size[1]) - resized_width = int(round(img.size[0] * percent)) - resized_height = int(round(img.size[1] * percent)) - img = img.resize((resized_width, resized_height), Image.LANCZOS) - return img - - -def crop_image(img, target_size, center): - width, height = img.size - size = target_size - if center == True: - w_start = (width - size) / 2 - h_start = (height - size) / 2 - else: - w_start = np.random.randint(0, width - size + 1) - h_start = np.random.randint(0, height - size + 1) - w_end = w_start + size - h_end = h_start + size - img = img.crop((w_start, h_start, w_end, h_end)) - return img - - -def random_crop(img, size, scale=[0.08, 1.0], ratio=[3. / 4., 4. / 3.]): - aspect_ratio = math.sqrt(np.random.uniform(*ratio)) - w = 1. * aspect_ratio - h = 1. / aspect_ratio - - bound = min((float(img.size[0]) / img.size[1]) / (w**2), - (float(img.size[1]) / img.size[0]) / (h**2)) - scale_max = min(scale[1], bound) - scale_min = min(scale[0], bound) - - target_area = img.size[0] * img.size[1] * np.random.uniform(scale_min, - scale_max) - target_size = math.sqrt(target_area) - w = int(target_size * w) - h = int(target_size * h) - - i = np.random.randint(0, img.size[0] - w + 1) - j = np.random.randint(0, img.size[1] - h + 1) - - img = img.crop((i, j, i + w, j + h)) - img = img.resize((size, size), Image.LANCZOS) - return img - - -def rotate_image(img): - angle = np.random.randint(-10, 11) - img = img.rotate(angle) - return img - - -def distort_color(img): - def random_brightness(img, lower=0.5, upper=1.5): - e = np.random.uniform(lower, upper) - return ImageEnhance.Brightness(img).enhance(e) - - def random_contrast(img, lower=0.5, upper=1.5): - e = np.random.uniform(lower, upper) - return ImageEnhance.Contrast(img).enhance(e) - - def random_color(img, lower=0.5, upper=1.5): - e = np.random.uniform(lower, upper) - return ImageEnhance.Color(img).enhance(e) - - ops = [random_brightness, random_contrast, random_color] - np.random.shuffle(ops) - - img = ops[0](img) - img = ops[1](img) - img = ops[2](img) - - return img - - -def process_image(sample, mode, color_jitter, rotate): - img_path = sample[0] - - img = Image.open(img_path) - if mode == 'train': - if rotate: img = rotate_image(img) - img = random_crop(img, DATA_DIM) - else: - img = resize_short(img, target_size=256) - img = crop_image(img, target_size=DATA_DIM, center=True) - if mode == 'train': - if color_jitter: - img = distort_color(img) - if np.random.randint(0, 2) == 1: - img = img.transpose(Image.FLIP_LEFT_RIGHT) - - if img.mode != 'RGB': - img = img.convert('RGB') - - img = np.array(img).astype('float32').transpose((2, 0, 1)) / 255 - img -= img_mean - img /= img_std - - if mode == 'train' or mode == 'val': - return img, sample[1] - elif mode == 'test': - return [img] - - -def _reader_creator(file_list, - mode, - shuffle=False, - color_jitter=False, - rotate=False, - data_dir=DATA_DIR, - batch_size=1): - def reader(): - try: - with open(file_list) as flist: - full_lines = [line.strip() for line in flist] - if shuffle: - np.random.shuffle(full_lines) - if mode == 'train' and os.getenv('PADDLE_TRAINING_ROLE'): - # distributed mode if the env var `PADDLE_TRAINING_ROLE` exits - trainer_id = int(os.getenv("PADDLE_TRAINER_ID", "0")) - trainer_count = int(os.getenv("PADDLE_TRAINERS", "1")) - per_node_lines = len(full_lines) // trainer_count - lines = full_lines[trainer_id * per_node_lines:( - trainer_id + 1) * per_node_lines] - print( - "read images from %d, length: %d, lines length: %d, total: %d" - % (trainer_id * per_node_lines, per_node_lines, - len(lines), len(full_lines))) - else: - lines = full_lines - - for line in lines: - if mode == 'train' or mode == 'val': - img_path, label = line.split() - img_path = os.path.join(data_dir, img_path) - yield img_path, int(label) - elif mode == 'test': - img_path = os.path.join(data_dir, line) - yield [img_path] - except Exception as e: - print("Reader failed!\n{}".format(str(e))) - os._exit(1) - - mapper = functools.partial( - process_image, mode=mode, color_jitter=color_jitter, rotate=rotate) - - return paddle.reader.xmap_readers(mapper, reader, THREAD, BUF_SIZE) - - -def train(data_dir=DATA_DIR): - file_list = os.path.join(data_dir, 'train_list.txt') - return _reader_creator( - file_list, - 'train', - shuffle=True, - color_jitter=False, - rotate=False, - data_dir=data_dir) - - -def val(data_dir=DATA_DIR): - file_list = os.path.join(data_dir, 'val_list.txt') - return _reader_creator(file_list, 'val', shuffle=False, data_dir=data_dir) - - -def test(data_dir=DATA_DIR): - file_list = os.path.join(data_dir, 'test_list.txt') - return _reader_creator(file_list, 'test', shuffle=False, data_dir=data_dir) diff --git a/paddleslim/tests/quant_test/models/__init__.py b/paddleslim/tests/quant_test/models/__init__.py deleted file mode 100644 index a4dbe24e5afbd9167c3dd8b924c9b87e47e1d8ff..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/models/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License" -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .mobilenet import MobileNet -from .resnet import ResNet34, ResNet50 -from .mobilenet_v2 import MobileNetV2 - -__all__ = ['MobileNet', 'ResNet34', 'ResNet50', 'MobileNetV2'] \ No newline at end of file diff --git a/paddleslim/tests/quant_test/models/mobilenet.py b/paddleslim/tests/quant_test/models/mobilenet.py deleted file mode 100644 index 6e1e089c4d08aba02a95019e6b03d81d3ad34f04..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/models/mobilenet.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License" -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -import paddle.fluid as fluid -from paddle.fluid.initializer import MSRA -from paddle.fluid.param_attr import ParamAttr - -__all__ = ['MobileNet'] - -train_parameters = { - "input_size": [3, 224, 224], - "input_mean": [0.485, 0.456, 0.406], - "input_std": [0.229, 0.224, 0.225], - "learning_strategy": { - "name": "piecewise_decay", - "batch_size": 256, - "epochs": [10, 16, 30], - "steps": [0.1, 0.01, 0.001, 0.0001] - } -} - - -class MobileNet(): - def __init__(self): - self.params = train_parameters - - def net(self, input, class_dim=1000, scale=1.0): - # conv1: 112x112 - input = self.conv_bn_layer( - input, - filter_size=3, - channels=3, - num_filters=int(32 * scale), - stride=2, - padding=1, - name="conv1") - - # 56x56 - input = self.depthwise_separable( - input, - num_filters1=32, - num_filters2=64, - num_groups=32, - stride=1, - scale=scale, - name="conv2_1") - - input = self.depthwise_separable( - input, - num_filters1=64, - num_filters2=128, - num_groups=64, - stride=2, - scale=scale, - name="conv2_2") - - # 28x28 - input = self.depthwise_separable( - input, - num_filters1=128, - num_filters2=128, - num_groups=128, - stride=1, - scale=scale, - name="conv3_1") - - input = self.depthwise_separable( - input, - num_filters1=128, - num_filters2=256, - num_groups=128, - stride=2, - scale=scale, - name="conv3_2") - - # 14x14 - input = self.depthwise_separable( - input, - num_filters1=256, - num_filters2=256, - num_groups=256, - stride=1, - scale=scale, - name="conv4_1") - - input = self.depthwise_separable( - input, - num_filters1=256, - num_filters2=512, - num_groups=256, - stride=2, - scale=scale, - name="conv4_2") - - # 14x14 - for i in range(5): - input = self.depthwise_separable( - input, - num_filters1=512, - num_filters2=512, - num_groups=512, - stride=1, - scale=scale, - name="conv5" + "_" + str(i + 1)) - # 7x7 - input = self.depthwise_separable( - input, - num_filters1=512, - num_filters2=1024, - num_groups=512, - stride=2, - scale=scale, - name="conv5_6") - - input = self.depthwise_separable( - input, - num_filters1=1024, - num_filters2=1024, - num_groups=1024, - stride=1, - scale=scale, - name="conv6") - - input = fluid.layers.pool2d( - input=input, - pool_size=0, - pool_stride=1, - pool_type='avg', - global_pooling=True) - - output = fluid.layers.fc(input=input, - size=class_dim, - act='softmax', - param_attr=ParamAttr( - initializer=MSRA(), name="fc7_weights"), - bias_attr=ParamAttr(name="fc7_offset")) - - return output - - def conv_bn_layer(self, - input, - filter_size, - num_filters, - stride, - padding, - channels=None, - num_groups=1, - act='relu', - use_cudnn=True, - name=None): - conv = fluid.layers.conv2d( - input=input, - num_filters=num_filters, - filter_size=filter_size, - stride=stride, - padding=padding, - groups=num_groups, - act=None, - use_cudnn=use_cudnn, - param_attr=ParamAttr( - initializer=MSRA(), name=name + "_weights"), - bias_attr=False) - bn_name = name + "_bn" - return fluid.layers.batch_norm( - input=conv, - act=act, - param_attr=ParamAttr(name=bn_name + "_scale"), - bias_attr=ParamAttr(name=bn_name + "_offset"), - moving_mean_name=bn_name + '_mean', - moving_variance_name=bn_name + '_variance') - - def depthwise_separable(self, - input, - num_filters1, - num_filters2, - num_groups, - stride, - scale, - name=None): - depthwise_conv = self.conv_bn_layer( - input=input, - filter_size=3, - num_filters=int(num_filters1 * scale), - stride=stride, - padding=1, - num_groups=int(num_groups * scale), - use_cudnn=False, - name=name + "_dw") - - pointwise_conv = self.conv_bn_layer( - input=depthwise_conv, - filter_size=1, - num_filters=int(num_filters2 * scale), - stride=1, - padding=0, - name=name + "_sep") - return pointwise_conv diff --git a/paddleslim/tests/quant_test/models/mobilenet_v2.py b/paddleslim/tests/quant_test/models/mobilenet_v2.py deleted file mode 100644 index 5d3e4c0d7094db7f3c377407fefc5459cd8a9701..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/models/mobilenet_v2.py +++ /dev/null @@ -1,257 +0,0 @@ -# copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -import paddle.fluid as fluid -from paddle.fluid.initializer import MSRA -from paddle.fluid.param_attr import ParamAttr - -__all__ = ['MobileNetV2', 'MobileNetV2_x0_25, ''MobileNetV2_x0_5', 'MobileNetV2_x1_0', 'MobileNetV2_x1_5', - 'MobileNetV2_x2_0', - 'MobileNetV2_scale'] - -train_parameters = { - "input_size": [3, 224, 224], - "input_mean": [0.485, 0.456, 0.406], - "input_std": [0.229, 0.224, 0.225], - "learning_strategy": { - "name": "piecewise_decay", - "batch_size": 256, - "epochs": [30, 60, 90], - "steps": [0.1, 0.01, 0.001, 0.0001] - } -} - - -class MobileNetV2(): - def __init__(self, scale=1.0, change_depth=False): - self.params = train_parameters - self.scale = scale - self.change_depth = change_depth - - def net(self, input, class_dim=1000): - scale = self.scale - change_depth = self.change_depth - # if change_depth is True, the new depth is 1.4 times as deep as before. - bottleneck_params_list = [ - (1, 16, 1, 1), - (6, 24, 2, 2), - (6, 32, 3, 2), - (6, 64, 4, 2), - (6, 96, 3, 1), - (6, 160, 3, 2), - (6, 320, 1, 1), - ] if change_depth == False else [ - (1, 16, 1, 1), - (6, 24, 2, 2), - (6, 32, 5, 2), - (6, 64, 7, 2), - (6, 96, 5, 1), - (6, 160, 3, 2), - (6, 320, 1, 1), - ] - - # conv1 - input = self.conv_bn_layer( - input, - num_filters=int(32 * scale), - filter_size=3, - stride=2, - padding=1, - if_act=True, - name='conv1_1') - - # bottleneck sequences - i = 1 - in_c = int(32 * scale) - for layer_setting in bottleneck_params_list: - t, c, n, s = layer_setting - i += 1 - input = self.invresi_blocks( - input=input, - in_c=in_c, - t=t, - c=int(c * scale), - n=n, - s=s, - name='conv' + str(i)) - in_c = int(c * scale) - # last_conv - input = self.conv_bn_layer( - input=input, - num_filters=int(1280 * scale) if scale > 1.0 else 1280, - filter_size=1, - stride=1, - padding=0, - if_act=True, - name='conv9') - - input = fluid.layers.pool2d( - input=input, - pool_size=7, - pool_stride=1, - pool_type='avg', - global_pooling=True) - - output = fluid.layers.fc(input=input, - size=class_dim, - act='softmax', - param_attr=ParamAttr(name='fc10_weights'), - bias_attr=ParamAttr(name='fc10_offset')) - return output - - def conv_bn_layer(self, - input, - filter_size, - num_filters, - stride, - padding, - channels=None, - num_groups=1, - if_act=True, - name=None, - use_cudnn=True): - conv = fluid.layers.conv2d( - input=input, - num_filters=num_filters, - filter_size=filter_size, - stride=stride, - padding=padding, - groups=num_groups, - act=None, - use_cudnn=use_cudnn, - param_attr=ParamAttr(name=name + '_weights'), - bias_attr=False) - bn_name = name + '_bn' - bn = fluid.layers.batch_norm( - input=conv, - param_attr=ParamAttr(name=bn_name + "_scale"), - bias_attr=ParamAttr(name=bn_name + "_offset"), - moving_mean_name=bn_name + '_mean', - moving_variance_name=bn_name + '_variance') - if if_act: - return fluid.layers.relu6(bn) - else: - return bn - - def shortcut(self, input, data_residual): - return fluid.layers.elementwise_add(input, data_residual) - - def inverted_residual_unit(self, - input, - num_in_filter, - num_filters, - ifshortcut, - stride, - filter_size, - padding, - expansion_factor, - name=None): - num_expfilter = int(round(num_in_filter * expansion_factor)) - - channel_expand = self.conv_bn_layer( - input=input, - num_filters=num_expfilter, - filter_size=1, - stride=1, - padding=0, - num_groups=1, - if_act=True, - name=name + '_expand') - - bottleneck_conv = self.conv_bn_layer( - input=channel_expand, - num_filters=num_expfilter, - filter_size=filter_size, - stride=stride, - padding=padding, - num_groups=num_expfilter, - if_act=True, - name=name + '_dwise', - use_cudnn=False) - - linear_out = self.conv_bn_layer( - input=bottleneck_conv, - num_filters=num_filters, - filter_size=1, - stride=1, - padding=0, - num_groups=1, - if_act=False, - name=name + '_linear') - if ifshortcut: - out = self.shortcut(input=input, data_residual=linear_out) - return out - else: - return linear_out - - def invresi_blocks(self, input, in_c, t, c, n, s, name=None): - first_block = self.inverted_residual_unit( - input=input, - num_in_filter=in_c, - num_filters=c, - ifshortcut=False, - stride=s, - filter_size=3, - padding=1, - expansion_factor=t, - name=name + '_1') - - last_residual_block = first_block - last_c = c - - for i in range(1, n): - last_residual_block = self.inverted_residual_unit( - input=last_residual_block, - num_in_filter=last_c, - num_filters=c, - ifshortcut=True, - stride=1, - filter_size=3, - padding=1, - expansion_factor=t, - name=name + '_' + str(i + 1)) - return last_residual_block - - -def MobileNetV2_x0_25(): - model = MobileNetV2(scale=0.25) - return model - - -def MobileNetV2_x0_5(): - model = MobileNetV2(scale=0.5) - return model - - -def MobileNetV2_x1_0(): - model = MobileNetV2(scale=1.0) - return model - - -def MobileNetV2_x1_5(): - model = MobileNetV2(scale=1.5) - return model - - -def MobileNetV2_x2_0(): - model = MobileNetV2(scale=2.0) - return model - - -def MobileNetV2_scale(): - model = MobileNetV2(scale=1.2, change_depth=True) - return model diff --git a/paddleslim/tests/quant_test/models/resnet.py b/paddleslim/tests/quant_test/models/resnet.py deleted file mode 100644 index 09c8d6c7773ce47ab9d487d556d9070137554af5..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/models/resnet.py +++ /dev/null @@ -1,194 +0,0 @@ -# copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -import paddle -import paddle.fluid as fluid -import math -from paddle.fluid.param_attr import ParamAttr - -__all__ = ["ResNet", "ResNet34", "ResNet50", "ResNet101", "ResNet152"] - -train_parameters = { - "input_size": [3, 224, 224], - "input_mean": [0.485, 0.456, 0.406], - "input_std": [0.229, 0.224, 0.225], - "learning_strategy": { - "name": "piecewise_decay", - "batch_size": 256, - "epochs": [10, 16, 30], - "steps": [0.1, 0.01, 0.001, 0.0001] - } -} - - -class ResNet(): - def __init__(self, layers=50, prefix_name=''): - self.params = train_parameters - self.layers = layers - self.prefix_name = prefix_name - - def net(self, input, class_dim=1000, conv1_name='conv1', fc_name='res_fc'): - layers = self.layers - prefix_name = self.prefix_name if self.prefix_name is '' else self.prefix_name + '_' - supported_layers = [34, 50, 101, 152] - assert layers in supported_layers, \ - "supported layers are {} but input layer is {}".format(supported_layers, layers) - - if layers == 34 or layers == 50: - depth = [3, 4, 6, 3] - elif layers == 101: - depth = [3, 4, 23, 3] - elif layers == 152: - depth = [3, 8, 36, 3] - num_filters = [64, 128, 256, 512] - - # TODO(wanghaoshuang@baidu.com): - # fix name("conv1") conflict between student and teacher in distillation. - conv = self.conv_bn_layer( - input=input, - num_filters=64, - filter_size=7, - stride=2, - act='relu', - name=prefix_name + conv1_name) - conv = fluid.layers.pool2d( - input=conv, - pool_size=3, - pool_stride=2, - pool_padding=1, - pool_type='max') - - for block in range(len(depth)): - for i in range(depth[block]): - if layers in [101, 152] and block == 2: - if i == 0: - conv_name = "res" + str(block + 2) + "a" - else: - conv_name = "res" + str(block + 2) + "b" + str(i) - else: - conv_name = "res" + str(block + 2) + chr(97 + i) - conv_name = prefix_name + conv_name - conv = self.bottleneck_block( - input=conv, - num_filters=num_filters[block], - stride=2 if i == 0 and block != 0 else 1, - name=conv_name) - - pool = fluid.layers.pool2d( - input=conv, pool_size=7, pool_type='avg', global_pooling=True) - stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) - out = fluid.layers.fc(input=pool, - size=class_dim, - act='softmax', - name=prefix_name + fc_name, - param_attr=fluid.param_attr.ParamAttr( - initializer=fluid.initializer.Uniform(-stdv, - stdv))) - return out - - def conv_bn_layer(self, - input, - num_filters, - filter_size, - stride=1, - groups=1, - act=None, - name=None): - conv = fluid.layers.conv2d( - input=input, - num_filters=num_filters, - filter_size=filter_size, - stride=stride, - padding=(filter_size - 1) // 2, - groups=groups, - act=None, - param_attr=ParamAttr(name=name + "_weights"), - bias_attr=False, - name=name + '.conv2d.output.1') - if self.prefix_name == '': - if name == "conv1": - bn_name = "bn_" + name - else: - bn_name = "bn" + name[3:] - else: - if name.split("_")[1] == "conv1": - bn_name = name.split("_", 1)[0] + "_bn_" + name.split("_", 1)[1] - else: - bn_name = name.split("_", 1)[0] + "_bn" + name.split("_", - 1)[1][3:] - return fluid.layers.batch_norm( - input=conv, - act=act, - name=bn_name + '.output.1', - param_attr=ParamAttr(name=bn_name + '_scale'), - bias_attr=ParamAttr(bn_name + '_offset'), - moving_mean_name=bn_name + '_mean', - moving_variance_name=bn_name + '_variance', ) - - def shortcut(self, input, ch_out, stride, name): - ch_in = input.shape[1] - if ch_in != ch_out or stride != 1: - return self.conv_bn_layer(input, ch_out, 1, stride, name=name) - else: - return input - - def bottleneck_block(self, input, num_filters, stride, name): - conv0 = self.conv_bn_layer( - input=input, - num_filters=num_filters, - filter_size=1, - act='relu', - name=name + "_branch2a") - conv1 = self.conv_bn_layer( - input=conv0, - num_filters=num_filters, - filter_size=3, - stride=stride, - act='relu', - name=name + "_branch2b") - conv2 = self.conv_bn_layer( - input=conv1, - num_filters=num_filters * 4, - filter_size=1, - act=None, - name=name + "_branch2c") - - short = self.shortcut( - input, num_filters * 4, stride, name=name + "_branch1") - - return fluid.layers.elementwise_add( - x=short, y=conv2, act='relu', name=name + ".add.output.5") - - -def ResNet34(prefix_name=''): - model = ResNet(layers=34, prefix_name=prefix_name) - return model - - -def ResNet50(prefix_name=''): - model = ResNet(layers=50, prefix_name=prefix_name) - return model - - -def ResNet101(): - model = ResNet(layers=101) - return model - - -def ResNet152(): - model = ResNet(layers=152) - return model diff --git a/paddleslim/tests/quant_test/quanter_test.py b/paddleslim/tests/quant_test/quanter_test.py deleted file mode 100644 index 40700e57114aa7999a2b9199dd2ffbe46ed3eb41..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/quanter_test.py +++ /dev/null @@ -1,425 +0,0 @@ -# copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -import os -import numpy as np -import time -import functools -import paddle -import paddle.fluid as fluid -import argparse -import subprocess -import sys -sys.path.append('../..') -sys.path.append('.') - -import imagenet_reader as reader -import models -from utility import add_arguments, print_arguments -from utility import save_persistable_nodes, load_persistable_nodes -import quant - - -parser = argparse.ArgumentParser(description=__doc__) -add_arg = functools.partial(add_arguments, argparser=parser) -# yapf: disable -add_arg('batch_size', int, 256, "Minibatch size.") -add_arg('use_gpu', bool, True, "Whether to use GPU or not.") -add_arg('total_images', int, 1281167, "Training image number.") -add_arg('num_epochs', int, 120, "number of epochs.") -add_arg('class_dim', int, 1000, "Class number.") -add_arg('image_shape', str, "3,224,224", "input image size") -add_arg('model_save_dir', str, "output", "model save directory") -add_arg('pretrained_fp32_model', str, None, "Whether to use the pretrained float32 model to initialize the weights.") -add_arg('checkpoint', str, None, "Whether to resume the training process from the checkpoint.") -add_arg('lr', float, 0.1, "set learning rate.") -add_arg('lr_strategy', str, "piecewise_decay", "Set the learning rate decay strategy.") -add_arg('model', str, "SE_ResNeXt50_32x4d", "Set the network to use.") -add_arg('data_dir', str, "./data/ILSVRC2012", "The ImageNet dataset root dir.") -add_arg('act_quant_type', str, "abs_max", "quantization type for activation, valid value:'abs_max','range_abs_max', 'moving_average_abs_max'" ) -add_arg('wt_quant_type', str, "abs_max", "quantization type for weight, valid value:'abs_max','channel_wise_abs_max'" ) -# yapf: enabl - - -def optimizer_setting(params): - ls = params["learning_strategy"] - if ls["name"] == "piecewise_decay": - if "total_images" not in params: - total_images = 1281167 - else: - total_images = params["total_images"] - batch_size = ls["batch_size"] - step = int(total_images / batch_size + 1) - - bd = [step * e for e in ls["epochs"]] - print("decay list:{}".format(bd)) - base_lr = params["lr"] - lr = [] - lr = [base_lr * (0.1**i) for i in range(len(bd) + 1)] - optimizer = fluid.optimizer.Momentum( - learning_rate=fluid.layers.piecewise_decay( - boundaries=bd, values=lr), - momentum=0.9, - regularization=fluid.regularizer.L2Decay(1e-4)) - - elif ls["name"] == "cosine_decay": - if "total_images" not in params: - total_images = 1281167 - else: - total_images = params["total_images"] - - batch_size = ls["batch_size"] - step = int(total_images / batch_size + 1) - - lr = params["lr"] - num_epochs = params["num_epochs"] - - optimizer = fluid.optimizer.Momentum( - learning_rate=fluid.layers.cosine_decay( - learning_rate=lr, step_each_epoch=step, epochs=num_epochs), - momentum=0.9, - regularization=fluid.regularizer.L2Decay(4e-5)) - elif ls["name"] == "exponential_decay": - if "total_images" not in params: - total_images = 1281167 - else: - total_images = params["total_images"] - batch_size = ls["batch_size"] - step = int(total_images / batch_size +1) - lr = params["lr"] - num_epochs = params["num_epochs"] - learning_decay_rate_factor=ls["learning_decay_rate_factor"] - num_epochs_per_decay = ls["num_epochs_per_decay"] - NUM_GPUS = 1 - - optimizer = fluid.optimizer.Momentum( - learning_rate=fluid.layers.exponential_decay( - learning_rate = lr * NUM_GPUS, - decay_steps = step * num_epochs_per_decay / NUM_GPUS, - decay_rate = learning_decay_rate_factor), - momentum=0.9, - - regularization = fluid.regularizer.L2Decay(4e-5)) - - else: - lr = params["lr"] - optimizer = fluid.optimizer.Momentum( - learning_rate=lr, - momentum=0.9, - regularization=fluid.regularizer.L2Decay(1e-4)) - - return optimizer - -def net_config(image, label, model, args): - model_list = [m for m in dir(models) if "__" not in m] - assert args.model in model_list,"{} is not lists: {}".format( - args.model, model_list) - - class_dim = args.class_dim - model_name = args.model - - if model_name == "GoogleNet": - out0, out1, out2 = model.net(input=image, class_dim=class_dim) - cost0 = fluid.layers.cross_entropy(input=out0, label=label) - cost1 = fluid.layers.cross_entropy(input=out1, label=label) - cost2 = fluid.layers.cross_entropy(input=out2, label=label) - avg_cost0 = fluid.layers.mean(x=cost0) - avg_cost1 = fluid.layers.mean(x=cost1) - avg_cost2 = fluid.layers.mean(x=cost2) - - avg_cost = avg_cost0 + 0.3 * avg_cost1 + 0.3 * avg_cost2 - acc_top1 = fluid.layers.accuracy(input=out0, label=label, k=1) - acc_top5 = fluid.layers.accuracy(input=out0, label=label, k=5) - out = out0 - else: - out = model.net(input=image, class_dim=class_dim) - cost = fluid.layers.cross_entropy(input=out, label=label) - - avg_cost = fluid.layers.mean(x=cost) - acc_top1 = fluid.layers.accuracy(input=out, label=label, k=1) - acc_top5 = fluid.layers.accuracy(input=out, label=label, k=5) - - return out, avg_cost, acc_top1, acc_top5 - - -def build_program(is_train, main_prog, startup_prog, args): - image_shape = [int(m) for m in args.image_shape.split(",")] - model_name = args.model - model_list = [m for m in dir(models) if "__" not in m] - assert model_name in model_list, "{} is not in lists: {}".format(args.model, - model_list) - model = models.__dict__[model_name]() - with fluid.program_guard(main_prog, startup_prog): - py_reader = fluid.layers.py_reader( - capacity=16, - shapes=[[-1] + image_shape, [-1, 1]], - lod_levels=[0, 0], - dtypes=["float32", "int64"], - use_double_buffer=True) - with fluid.unique_name.guard(): - image, label = fluid.layers.read_file(py_reader) - out, avg_cost, acc_top1, acc_top5 = net_config(image, label, model, args) - avg_cost.persistable = True - acc_top1.persistable = True - acc_top5.persistable = True - if is_train: - params = model.params - params["total_images"] = args.total_images - params["lr"] = args.lr - params["num_epochs"] = args.num_epochs - params["learning_strategy"]["batch_size"] = args.batch_size - params["learning_strategy"]["name"] = args.lr_strategy - - optimizer = optimizer_setting(params) - optimizer.minimize(avg_cost) - global_lr = optimizer._global_learning_rate() - if is_train: - return image, out, py_reader, avg_cost, acc_top1, acc_top5, global_lr - else: - return image, out, py_reader, avg_cost, acc_top1, acc_top5 - -def train(args): - ############################################################################################################ - # 1. quantization configs - ############################################################################################################ - quant_config = { - # weight quantize type, default is 'abs_max' - 'weight_quantize_type': 'abs_max', - # activation quantize type, default is 'abs_max' - 'activation_quantize_type': 'abs_max', - # weight quantize bit num, default is 8 - 'weight_bits': 8, - # activation quantize bit num, default is 8 - 'activation_bits': 8, - # op of name_scope in not_quant_pattern list, will not quantized - 'not_quant_pattern': ['skip_quant_dd'], - # op of types in quantize_op_types, will quantized - 'quantize_op_types': ['conv2d', 'depthwise_conv2d', 'mul'], - # data type after quantization, default is 'int8' - 'dtype': 'int8', - # window size for 'range_abs_max' quantization. defaulf is 10000 - 'window_size': 10000, - # The decay coefficient of moving average, default is 0.9 - 'moving_rate': 0.9, - # if set quant_weight_only True, then only quantize parameters of layers which need quantization, - # and insert anti-quantization op for parameters of these layers. - 'quant_weight_only': False - } - - - # parameters from arguments - model_name = args.model - pretrained_fp32_model = args.pretrained_fp32_model - checkpoint = args.checkpoint - model_save_dir = args.model_save_dir - data_dir = args.data_dir - activation_quant_type = args.act_quant_type - weight_quant_type = args.wt_quant_type - print("Using %s as the actiavtion quantize type." % activation_quant_type) - print("Using %s as the weight quantize type." % weight_quant_type) - - startup_prog = fluid.Program() - train_prog = fluid.Program() - test_prog = fluid.Program() - - _, _, train_py_reader, train_cost, train_acc1, train_acc5, global_lr = build_program( - is_train=True, - main_prog=train_prog, - startup_prog=startup_prog, - args=args) - image, out, test_py_reader, test_cost, test_acc1, test_acc5 = build_program( - is_train=False, - main_prog=test_prog, - startup_prog=startup_prog, - args=args) - test_prog = test_prog.clone(for_test=True) - - place = fluid.CUDAPlace(0) if args.use_gpu else fluid.CPUPlace() - scope = fluid.global_scope() - exe = fluid.Executor(place) - - - # load checkpoint todo - - - exe.run(startup_prog) - - if pretrained_fp32_model: - def if_exist(var): - return os.path.exists(os.path.join(pretrained_fp32_model, var.name)) - fluid.io.load_vars( - exe, pretrained_fp32_model, main_program=train_prog, predicate=if_exist) - - if args.use_gpu: - visible_device = os.getenv('CUDA_VISIBLE_DEVICES') - if visible_device: - device_num = len(visible_device.split(',')) - else: - device_num = subprocess.check_output( - ['nvidia-smi', '-L']).decode().count('\n') - else: - device_num = 1 - - train_batch_size = args.batch_size / device_num - test_batch_size = 1 if activation_quant_type == 'abs_max' else 8 - train_reader = paddle.batch( - reader.train(data_dir=data_dir), batch_size=train_batch_size, drop_last=True) - test_reader = paddle.batch(reader.val(data_dir=data_dir), batch_size=test_batch_size) - - train_py_reader.decorate_paddle_reader(train_reader) - test_py_reader.decorate_paddle_reader(test_reader) - - train_fetch_list = [train_cost.name, train_acc1.name, train_acc5.name, global_lr.name] - test_fetch_list = [test_cost.name, test_acc1.name, test_acc5.name] - - ############################################################################################################ - # 2. quantization transform programs (training aware) - # Make some quantization transforms in the graph before training and testing. - # According to the weight and activation quantization type, the graph will be added - # some fake quantize operators and fake dequantize operators. - ############################################################################################################ - build_strategy = fluid.BuildStrategy() - build_strategy.memory_optimize = False - build_strategy.enable_inplace = False - build_strategy.fuse_all_reduce_ops = False - test_prog = quant.quanter.quant_aware(test_prog, scope, place, quant_config, for_test=True) - train_prog = quant.quanter.quant_aware(train_prog, scope, place, quant_config, for_test=False) - train_prog = train_prog.with_data_parallel(loss_name=train_cost.name, build_strategy=build_strategy) - #train_prog_binary = train_prog_binary.with_data_parallel(loss_name=train_cost.name) - - - params = models.__dict__[args.model]().params - for pass_id in range(params["num_epochs"]): - - train_py_reader.start() - - train_info = [[], [], []] - test_info = [[], [], []] - train_time = [] - batch_id = 0 - try: - while True: - t1 = time.time() - loss, acc1, acc5, lr = exe.run(train_prog, fetch_list=train_fetch_list) - t2 = time.time() - period = t2 - t1 - loss = np.mean(np.array(loss)) - acc1 = np.mean(np.array(acc1)) - acc5 = np.mean(np.array(acc5)) - train_info[0].append(loss) - train_info[1].append(acc1) - train_info[2].append(acc5) - lr = np.mean(np.array(lr)) - train_time.append(period) - if batch_id % 10 == 0: - print("Pass {0}, trainbatch {1}, loss {2}, \ - acc1 {3}, acc5 {4}, lr {5}, time {6}" - .format(pass_id, batch_id, loss, acc1, acc5, "%.6f" % - lr, "%2.2f sec" % period)) - sys.stdout.flush() - batch_id += 1 - except fluid.core.EOFException: - train_py_reader.reset() - - train_loss = np.array(train_info[0]).mean() - train_acc1 = np.array(train_info[1]).mean() - train_acc5 = np.array(train_info[2]).mean() - - test_py_reader.start() - - test_batch_id = 0 - try: - while True: - t1 = time.time() - loss, acc1, acc5 = exe.run(program=test_prog, - fetch_list=test_fetch_list) - t2 = time.time() - period = t2 - t1 - loss = np.mean(loss) - acc1 = np.mean(acc1) - acc5 = np.mean(acc5) - test_info[0].append(loss) - test_info[1].append(acc1) - test_info[2].append(acc5) - if test_batch_id % 10 == 0: - print("Pass {0},testbatch {1},loss {2}, \ - acc1 {3},acc5 {4},time {5}" - .format(pass_id, test_batch_id, loss, acc1, acc5, - "%2.2f sec" % period)) - sys.stdout.flush() - test_batch_id += 1 - except fluid.core.EOFException: - test_py_reader.reset() - - test_loss = np.array(test_info[0]).mean() - test_acc1 = np.array(test_info[1]).mean() - test_acc5 = np.array(test_info[2]).mean() - - print("End pass {0}, train_loss {1}, train_acc1 {2}, train_acc5 {3}, " - "test_loss {4}, test_acc1 {5}, test_acc5 {6}".format( - pass_id, train_loss, train_acc1, train_acc5, test_loss, - test_acc1, test_acc5)) - sys.stdout.flush() - - # save checkpoints todo - # save_checkpoint_path = os.path.join(model_save_dir, model_name, str(pass_id)) - # if not os.path.isdir(save_checkpoint_path): - # os.makedirs(save_checkpoint_path) - # save_persistable_nodes(exe, save_checkpoint_path, main_graph) - - - - - ############################################################################################################ - # 3. Freeze the graph after training by adjusting the quantize - # operators' order for the inference. - # The dtype of float_program's weights is float32, but in int8 range. - ############################################################################################################ - float_program, int8_program = quant.quanter.convert(test_prog, scope, place, quant_config, save_int8=True) - - - ############################################################################################################ - # 4. Save inference model - ############################################################################################################ - model_path = os.path.join(model_save_dir, model_name, args.act_quant_type) - float_path = os.path.join(model_path, 'float') - int8_path = os.path.join(model_path, 'int8') - if not os.path.isdir(model_path): - os.makedirs(model_path) - - fluid.io.save_inference_model( - dirname=float_path, - feeded_var_names=[image.name], - target_vars=[out], executor=exe, - main_program=float_program) - - fluid.io.save_inference_model( - dirname=int8_path, - feeded_var_names=[image.name], - target_vars=[out], executor=exe, - main_program=int8_program) - - - -def main(): - args = parser.parse_args() - print_arguments(args) - train(args) - - -if __name__ == '__main__': - main() diff --git a/paddleslim/tests/quant_test/run_quant.sh b/paddleslim/tests/quant_test/run_quant.sh deleted file mode 100644 index ee23d99a5b22c6d279d03ec1005d5fe15bdee1a4..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/run_quant.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -source /home/wsz/anaconda2/bin/activate py27_paddle1.6 -export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 -#MobileNet v1: -nohup python quanter_test.py \ - --model=MobileNet \ - --pretrained_fp32_model='../../../../pretrain/MobileNetV1_pretrained/' \ - --use_gpu=True \ - --data_dir='/home/ssd8/wsz/tianfei01/traindata/imagenet/' \ - --batch_size=2048 \ - --total_images=1281167 \ - --class_dim=1000 \ - --image_shape=3,224,224 \ - --model_save_dir=output/ \ - --lr_strategy=piecewise_decay \ - --num_epochs=20 \ - --lr=0.0001 \ - --act_quant_type=abs_max \ - --wt_quant_type=abs_max 2>&1 & - -#ResNet50: -#python quanter_test.py \ -# --model=ResNet50 \ -# --pretrained_fp32_model=${pretrain_dir}/ResNet50_pretrained \ -# --use_gpu=True \ -# --data_dir=${data_dir} \ -# --batch_size=128 \ -# --total_images=1281167 \ -# --class_dim=1000 \ -# --image_shape=3,224,224 \ -# --model_save_dir=output/ \ -# --lr_strategy=piecewise_decay \ -# --num_epochs=20 \ -# --lr=0.0001 \ -# --act_quant_type=abs_max \ -# --wt_quant_type=abs_max diff --git a/paddleslim/tests/quant_test/utility.py b/paddleslim/tests/quant_test/utility.py deleted file mode 100644 index 9e77a26dbed17e2f75856c6ff9b4d0677a9d575e..0000000000000000000000000000000000000000 --- a/paddleslim/tests/quant_test/utility.py +++ /dev/null @@ -1,156 +0,0 @@ -"""Contains common utility functions.""" -# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve. -# -#Licensed under the Apache License, Version 2.0 (the "License"); -#you may not use this file except in compliance with the License. -#You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, software -#distributed under the License is distributed on an "AS IS" BASIS, -#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#See the License for the specific language governing permissions and -#limitations under the License. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import distutils.util -import os -import numpy as np -import six -import logging -import paddle.fluid as fluid -import paddle.compat as cpt -from paddle.fluid import core -from paddle.fluid.framework import Program - -logging.basicConfig(format='%(asctime)s-%(levelname)s: %(message)s') -_logger = logging.getLogger(__name__) -_logger.setLevel(logging.INFO) - -def print_arguments(args): - """Print argparse's arguments. - - Usage: - - .. code-block:: python - - parser = argparse.ArgumentParser() - parser.add_argument("name", default="Jonh", type=str, help="User name.") - args = parser.parse_args() - print_arguments(args) - - :param args: Input argparse.Namespace for printing. - :type args: argparse.Namespace - """ - print("----------- Configuration Arguments -----------") - for arg, value in sorted(six.iteritems(vars(args))): - print("%s: %s" % (arg, value)) - print("------------------------------------------------") - - -def add_arguments(argname, type, default, help, argparser, **kwargs): - """Add argparse's argument. - - Usage: - - .. code-block:: python - - parser = argparse.ArgumentParser() - add_argument("name", str, "Jonh", "User name.", parser) - args = parser.parse_args() - """ - type = distutils.util.strtobool if type == bool else type - argparser.add_argument( - "--" + argname, - default=default, - type=type, - help=help + ' Default: %(default)s.', - **kwargs) - - -def save_persistable_nodes(executor, dirname, graph): - """ - Save persistable nodes to the given directory by the executor. - - Args: - executor(Executor): The executor to run for saving node values. - dirname(str): The directory path. - graph(IrGraph): All the required persistable nodes in the graph will be saved. - """ - persistable_node_names = set() - persistable_nodes = [] - all_persistable_nodes = graph.all_persistable_nodes() - for node in all_persistable_nodes: - name = cpt.to_text(node.name()) - if name not in persistable_node_names: - persistable_node_names.add(name) - persistable_nodes.append(node) - program = Program() - var_list = [] - for node in persistable_nodes: - var_desc = node.var() - if var_desc.type() == core.VarDesc.VarType.RAW or \ - var_desc.type() == core.VarDesc.VarType.READER: - continue - var = program.global_block().create_var( - name=var_desc.name(), - shape=var_desc.shape(), - dtype=var_desc.dtype(), - type=var_desc.type(), - lod_level=var_desc.lod_level(), - persistable=var_desc.persistable()) - var_list.append(var) - fluid.io.save_vars(executor=executor, dirname=dirname, vars=var_list) - - -def load_persistable_nodes(executor, dirname, graph): - """ - Load persistable node values from the given directory by the executor. - - Args: - executor(Executor): The executor to run for loading node values. - dirname(str): The directory path. - graph(IrGraph): All the required persistable nodes in the graph will be loaded. - """ - persistable_node_names = set() - persistable_nodes = [] - all_persistable_nodes = graph.all_persistable_nodes() - for node in all_persistable_nodes: - name = cpt.to_text(node.name()) - if name not in persistable_node_names: - persistable_node_names.add(name) - persistable_nodes.append(node) - program = Program() - var_list = [] - - def _exist(var): - return os.path.exists(os.path.join(dirname, var.name)) - - def _load_var(name, scope): - return np.array(scope.find_var(name).get_tensor()) - - def _store_var(name, array, scope, place): - tensor = scope.find_var(name).get_tensor() - tensor.set(array, place) - - for node in persistable_nodes: - var_desc = node.var() - if var_desc.type() == core.VarDesc.VarType.RAW or \ - var_desc.type() == core.VarDesc.VarType.READER: - continue - var = program.global_block().create_var( - name=var_desc.name(), - shape=var_desc.shape(), - dtype=var_desc.dtype(), - type=var_desc.type(), - lod_level=var_desc.lod_level(), - persistable=var_desc.persistable()) - if _exist(var): - var_list.append(var) - else: - _logger.info("Cannot find the var %s!!!" %(node.name())) - fluid.io.load_vars(executor=executor, dirname=dirname, vars=var_list)