未验证 提交 7e5a588f 编写于 作者: X XGZhang 提交者: GitHub

add ce tests for fusing layers (#888)

上级 50d067e8
data_path="/root/datasets/ILSVRC2012"
quant_batch_num=1
quant_batch_size=16
for model in mobilenet_v2 mobilenet_v1 resnet50
do
echo "--------quantize model: ${model}-------------"
python ./src/ptq.py \
--data=${data_path} \
--arch=${model} \
--fuse=True \
--quant_batch_num=${quant_batch_num} \
--quant_batch_size=${quant_batch_size} \
--output_dir="output_ptq"
done
echo "\n"
......@@ -25,6 +25,7 @@ import numpy as np
import paddle
import paddle.vision.models as models
import paddle.nn as nn
from imagenet_dataset import ImageNetDataset
from paddleslim import PTQ
......@@ -59,12 +60,23 @@ def main():
model_list, FLAGS.arch)
fp32_model = models.__dict__[FLAGS.arch](pretrained=True)
fp32_model.eval()
for name, layer in fp32_model.named_sublayers():
print(name, layer)
count = 0
fuse_list = []
for name, layer in fp32_model.named_sublayers():
if isinstance(layer, nn.Conv2D):
fuse_list.append([name])
if isinstance(layer, nn.BatchNorm2D):
fuse_list[count].append(name)
count += 1
if FLAGS.arch == 'resnet50':
fuse_list = None
val_dataset = ImageNetDataset(FLAGS.data, mode='val')
# 2 quantizations
ptq = PTQ()
quant_model = ptq.quantize(fp32_model)
quant_model = ptq.quantize(fp32_model, fuse=FLAGS.fuse, fuse_list=fuse_list)
print("Calibrate")
calibrate(quant_model, val_dataset, FLAGS.quant_batch_num,
......@@ -90,6 +102,7 @@ if __name__ == '__main__':
"--arch", type=str, default='mobilenet_v2', help="model name")
parser.add_argument(
"--output_dir", type=str, default='output', help="save dir")
parser.add_argument("--fuse", type=bool, default=False, help="fuse layers")
# data
parser.add_argument(
......
......@@ -16,6 +16,7 @@ import copy
import logging
import paddle
import paddle.nn as nn
import paddle.fluid.contrib.slim.quantization as Q
from paddle.fluid.contrib.slim.quantization import AbsmaxQuantizer
from paddle.fluid.contrib.slim.quantization import HistQuantizer
......@@ -58,7 +59,7 @@ class PTQ(object):
self.ptq = Q.ImperativePTQ(quant_config=quant_config)
def quantize(self, model, inplace=False):
def quantize(self, model, inplace=False, fuse=False, fuse_list=None):
"""
Quantize the input model.
......@@ -66,13 +67,50 @@ class PTQ(object):
model(paddle.nn.Layer): The model to be quantized.
inplace(bool): Whether apply quantization to the input model.
Default: False.
fuse(bool): Whether to fuse layers.
Default: False.
fuse_list(list): The layers' names to be fused. For example,
"fuse_list = [["conv1", "bn1"], ["conv2", "bn2"]]".
The conv2d and bn layers will be fused automatically
if "fuse" was set as True but "fuse_list" was None.
Default: None.
Returns:
quantized_model(paddle.nn.Layer): The quantized model.
"""
assert isinstance(model, paddle.nn.Layer), \
"The model must be the instance of paddle.nn.Layer."
return self.ptq.quantize(model=model, inplace=inplace)
if fuse == True:
if fuse_list is None:
fuse_list = self.find_conv_bn_names(model)
_logger.info('The layers to be fused:')
for i in fuse_list:
_logger.info(i)
return self.ptq.quantize(
model=model, inplace=inplace, fuse=fuse, fuse_list=fuse_list)
def find_conv_bn_names(self, model):
"""
Find the connected conv2d and bn layers of model.
Args:
model(paddle.nn.Layer): The model to be fuseed.
Returns:
fuse_list(list): The conv and bn layers to be fused.
"""
last_layer = None
fuse_list = []
for name, layer in model.named_sublayers():
if isinstance(last_layer, nn.Conv2D) and isinstance(layer,
nn.BatchNorm2D):
fuse_list.append([last_name, name])
last_name = name
last_layer = layer
return fuse_list
def save_quantized_model(self, model, path, input_spec=None):
"""
......
......@@ -30,38 +30,46 @@ _logger = get_logger(
class ImperativeLenet(nn.Layer):
def __init__(self, num_classes=10, classifier_activation='softmax'):
def __init__(self, num_classes=10):
super(ImperativeLenet, self).__init__()
self.features = paddle.nn.Sequential(
paddle.nn.Conv2D(
self.features = nn.Sequential(
nn.Conv2D(
in_channels=1,
out_channels=6,
kernel_size=3,
stride=1,
padding=1),
paddle.nn.AvgPool2D(
padding=1,
bias_attr=False),
nn.BatchNorm2D(6),
nn.ReLU(),
nn.MaxPool2D(
kernel_size=2, stride=2),
paddle.nn.Conv2D(
nn.Conv2D(
in_channels=6,
out_channels=16,
kernel_size=5,
stride=1,
padding=0),
paddle.nn.AvgPool2D(
nn.BatchNorm2D(16),
nn.PReLU(),
nn.MaxPool2D(
kernel_size=2, stride=2))
self.fc = paddle.nn.Sequential(
paddle.nn.Linear(
self.fc = nn.Sequential(
nn.Linear(
in_features=400, out_features=120),
paddle.nn.Linear(
nn.LeakyReLU(),
nn.Linear(
in_features=120, out_features=84),
paddle.nn.Linear(
in_features=84, out_features=num_classes), )
nn.Sigmoid(),
nn.Linear(
in_features=84, out_features=num_classes),
nn.Softmax())
def forward(self, inputs):
x = self.features(inputs)
x = paddle.flatten(x, 1)
x = fluid.layers.flatten(x, 1)
x = self.fc(x)
return x
......@@ -166,7 +174,7 @@ class TestPTQ(unittest.TestCase):
_logger.info("quantize the fp32 model")
quanter = PTQ()
quant_lenet = quanter.quantize(fp32_lenet)
quant_lenet = quanter.quantize(fp32_lenet, fuse=True)
_logger.info("calibrate")
self.calibrate(quant_lenet, test_reader)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册