chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,352 @@
|
||||
# copyright (c) 2018 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 functools
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from test_post_training_quantization_mobilenetv1 import (
|
||||
TestPostTrainingQuantization,
|
||||
)
|
||||
|
||||
import paddle
|
||||
from paddle.static.quantization import PostTrainingQuantizationProgram
|
||||
|
||||
paddle.enable_static()
|
||||
|
||||
random.seed(0)
|
||||
np.random.seed(0)
|
||||
|
||||
THREAD = 1
|
||||
DATA_DIM = 224
|
||||
BUF_SIZE = 102400
|
||||
DATA_DIR = 'data/ILSVRC2012'
|
||||
|
||||
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 is 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 process_image(sample, mode, color_jitter, rotate):
|
||||
img_path = sample[0]
|
||||
img = Image.open(img_path)
|
||||
img = resize_short(img, target_size=256)
|
||||
img = crop_image(img, target_size=DATA_DIM, center=True)
|
||||
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
|
||||
return img, sample[1]
|
||||
|
||||
|
||||
def _reader_creator(
|
||||
file_list,
|
||||
mode,
|
||||
shuffle=False,
|
||||
color_jitter=False,
|
||||
rotate=False,
|
||||
data_dir=DATA_DIR,
|
||||
):
|
||||
def reader():
|
||||
with open(file_list) as flist:
|
||||
full_lines = [line.strip() for line in flist]
|
||||
if shuffle:
|
||||
np.random.shuffle(full_lines)
|
||||
lines = full_lines
|
||||
|
||||
for line in lines:
|
||||
img_path, label = line.split()
|
||||
img_path = os.path.join(data_dir, img_path)
|
||||
if not os.path.exists(img_path):
|
||||
continue
|
||||
yield img_path, int(label)
|
||||
|
||||
mapper = functools.partial(
|
||||
process_image, mode=mode, color_jitter=color_jitter, rotate=rotate
|
||||
)
|
||||
|
||||
return paddle.reader.xmap_readers(mapper, reader, THREAD, BUF_SIZE)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class TestPostTrainingQuantizationProgram(TestPostTrainingQuantization):
|
||||
def run_program(
|
||||
self,
|
||||
model_path,
|
||||
model_filename,
|
||||
params_filename,
|
||||
batch_size,
|
||||
infer_iterations,
|
||||
):
|
||||
image_shape = [3, 224, 224]
|
||||
place = paddle.CPUPlace()
|
||||
exe = paddle.static.Executor(place)
|
||||
[
|
||||
infer_program,
|
||||
feed_dict,
|
||||
fetch_targets,
|
||||
] = paddle.static.load_inference_model(
|
||||
model_path,
|
||||
exe,
|
||||
model_filename=model_filename,
|
||||
params_filename=params_filename,
|
||||
)
|
||||
val_reader = paddle.batch(val(), batch_size)
|
||||
iterations = infer_iterations
|
||||
test_info = []
|
||||
cnt = 0
|
||||
periods = []
|
||||
for batch_id, data in enumerate(val_reader()):
|
||||
image = np.array([x[0].reshape(image_shape) for x in data]).astype(
|
||||
"float32"
|
||||
)
|
||||
label = np.array([x[1] for x in data]).astype("int64")
|
||||
label = label.reshape([-1, 1])
|
||||
|
||||
t1 = time.time()
|
||||
_, acc1, _ = exe.run(
|
||||
infer_program,
|
||||
feed={feed_dict[0]: image, feed_dict[1]: label},
|
||||
fetch_list=fetch_targets,
|
||||
)
|
||||
t2 = time.time()
|
||||
period = t2 - t1
|
||||
periods.append(period)
|
||||
|
||||
test_info.append(np.mean(acc1) * len(data))
|
||||
cnt += len(data)
|
||||
|
||||
if (batch_id + 1) % 100 == 0:
|
||||
print(f"{batch_id + 1} images,")
|
||||
sys.stdout.flush()
|
||||
if (batch_id + 1) == iterations:
|
||||
break
|
||||
|
||||
throughput = cnt / np.sum(periods)
|
||||
latency = np.average(periods)
|
||||
acc1 = np.sum(test_info) / cnt
|
||||
[
|
||||
infer_program,
|
||||
feed_dict,
|
||||
fetch_targets,
|
||||
] = paddle.static.load_inference_model(
|
||||
model_path,
|
||||
exe,
|
||||
model_filename=model_filename,
|
||||
params_filename=params_filename,
|
||||
)
|
||||
return (
|
||||
throughput,
|
||||
latency,
|
||||
acc1,
|
||||
infer_program,
|
||||
feed_dict,
|
||||
fetch_targets,
|
||||
)
|
||||
|
||||
def generate_quantized_model(
|
||||
self,
|
||||
program,
|
||||
quantizable_op_type,
|
||||
feed_list,
|
||||
fetch_list,
|
||||
algo="KL",
|
||||
round_type="round",
|
||||
is_full_quantize=False,
|
||||
is_use_cache_file=False,
|
||||
is_optimize_model=False,
|
||||
onnx_format=False,
|
||||
):
|
||||
try:
|
||||
os.system("mkdir " + self.int8_model)
|
||||
except Exception as e:
|
||||
print(f"Failed to create {self.int8_model} due to {e}")
|
||||
sys.exit(-1)
|
||||
|
||||
place = paddle.CPUPlace()
|
||||
exe = paddle.static.Executor(place)
|
||||
val_reader = val()
|
||||
same_scale_tensor_list = [
|
||||
['batch_norm_3.tmp_2#/#1', 'batch_norm_4.tmp_2#*#1'],
|
||||
['batch_norm_27.tmp_2', 'batch_norm_26.tmp_2'],
|
||||
[
|
||||
'test_scale_name_not_in_scale_dict1',
|
||||
'test_scale_name_not_in_scale_dict2',
|
||||
],
|
||||
[
|
||||
'test_scale_name_not_in_scale_dict1#/#1',
|
||||
'test_scale_name_not_in_scale_dict2#/#1',
|
||||
],
|
||||
]
|
||||
ptq = PostTrainingQuantizationProgram(
|
||||
executor=exe,
|
||||
program=program,
|
||||
sample_generator=val_reader,
|
||||
batch_nums=10,
|
||||
algo=algo,
|
||||
quantizable_op_type=quantizable_op_type,
|
||||
round_type=round_type,
|
||||
is_full_quantize=is_full_quantize,
|
||||
optimize_model=is_optimize_model,
|
||||
onnx_format=onnx_format,
|
||||
is_use_cache_file=is_use_cache_file,
|
||||
feed_list=feed_list,
|
||||
fetch_list=fetch_list,
|
||||
same_scale_tensor_list=same_scale_tensor_list,
|
||||
)
|
||||
ptq.quantize()
|
||||
ptq.save_quantized_model(self.int8_model)
|
||||
|
||||
def run_test(
|
||||
self,
|
||||
model,
|
||||
model_filename,
|
||||
params_filename,
|
||||
algo,
|
||||
round_type,
|
||||
data_urls,
|
||||
data_md5s,
|
||||
quantizable_op_type,
|
||||
is_full_quantize,
|
||||
is_use_cache_file,
|
||||
is_optimize_model,
|
||||
diff_threshold,
|
||||
onnx_format=False,
|
||||
):
|
||||
infer_iterations = self.infer_iterations
|
||||
batch_size = self.batch_size
|
||||
|
||||
model_cache_folder = self.download_data(data_urls, data_md5s, model)
|
||||
|
||||
print(
|
||||
f"Start FP32 inference for {model} on {infer_iterations * batch_size} images ..."
|
||||
)
|
||||
(
|
||||
fp32_throughput,
|
||||
fp32_latency,
|
||||
fp32_acc1,
|
||||
infer_program,
|
||||
feed_dict,
|
||||
fetch_targets,
|
||||
) = self.run_program(
|
||||
os.path.join(model_cache_folder, "model"),
|
||||
model_filename,
|
||||
params_filename,
|
||||
batch_size,
|
||||
infer_iterations,
|
||||
)
|
||||
|
||||
self.generate_quantized_model(
|
||||
infer_program,
|
||||
quantizable_op_type,
|
||||
feed_dict,
|
||||
fetch_targets,
|
||||
algo,
|
||||
round_type,
|
||||
is_full_quantize,
|
||||
is_use_cache_file,
|
||||
is_optimize_model,
|
||||
onnx_format,
|
||||
)
|
||||
|
||||
print(
|
||||
f"Start INT8 inference for {model} on {infer_iterations * batch_size} images ..."
|
||||
)
|
||||
(int8_throughput, int8_latency, int8_acc1, _, _, _) = self.run_program(
|
||||
self.int8_model,
|
||||
model_filename,
|
||||
params_filename,
|
||||
batch_size,
|
||||
infer_iterations,
|
||||
)
|
||||
|
||||
print(f"---Post training quantization of {algo} method---")
|
||||
print(
|
||||
f"FP32 {model}: batch_size {batch_size}, throughput {fp32_throughput} images/second, latency {fp32_latency} second, accuracy {fp32_acc1}."
|
||||
)
|
||||
print(
|
||||
f"INT8 {model}: batch_size {batch_size}, throughput {int8_throughput} images/second, latency {int8_latency} second, accuracy {int8_acc1}.\n"
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
delta_value = fp32_acc1 - int8_acc1
|
||||
self.assertLess(delta_value, diff_threshold)
|
||||
|
||||
|
||||
class TestPostTrainingProgramAbsMaxForResnet50(
|
||||
TestPostTrainingQuantizationProgram
|
||||
):
|
||||
def test_post_training_abs_max_resnet50(self):
|
||||
model = "ResNet-50"
|
||||
algo = "abs_max"
|
||||
round_type = "round"
|
||||
data_urls = [
|
||||
'http://paddle-inference-dist.bj.bcebos.com/int8/resnet50_int8_model_combined.tar.gz'
|
||||
]
|
||||
data_md5s = ['db212fd4e9edc83381aef4533107e60c']
|
||||
quantizable_op_type = ["conv2d", "mul"]
|
||||
is_full_quantize = False
|
||||
is_use_cache_file = False
|
||||
is_optimize_model = False
|
||||
diff_threshold = 0.025
|
||||
self.run_test(
|
||||
model,
|
||||
'model.pdmodel',
|
||||
'model.pdiparams',
|
||||
algo,
|
||||
round_type,
|
||||
data_urls,
|
||||
data_md5s,
|
||||
quantizable_op_type,
|
||||
is_full_quantize,
|
||||
is_use_cache_file,
|
||||
is_optimize_model,
|
||||
diff_threshold,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user