未验证 提交 7a4cc1f5 编写于 作者: C Chang Xu 提交者: GitHub

[Cherry-Pick] Upgrade ImageNet Demo (#1235)

* Upgrade ImageNet Demo

* Upgrade ImageNet Demo

* Upgrade ImageNet Demo
上级 a59d7762
......@@ -11,6 +11,7 @@ random.seed(0)
np.random.seed(0)
DATA_DIM = 224
RESIZE_DIM = 256
THREAD = 16
BUF_SIZE = 10240
......@@ -34,8 +35,8 @@ 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
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)
......@@ -98,7 +99,7 @@ def distort_color(img):
return img
def process_image(sample, mode, color_jitter, rotate):
def process_image(sample, mode, color_jitter, rotate, crop_size, resize_size):
img_path = sample[0]
try:
......@@ -108,10 +109,10 @@ def process_image(sample, mode, color_jitter, rotate):
return None
if mode == 'train':
if rotate: img = rotate_image(img)
img = random_crop(img, DATA_DIM)
img = random_crop(img, crop_size)
else:
img = resize_short(img, target_size=256)
img = crop_image(img, target_size=DATA_DIM, center=True)
img = resize_short(img, target_size=resize_size)
img = crop_image(img, target_size=crop_size, center=True)
if mode == 'train':
if color_jitter:
img = distort_color(img)
......@@ -185,9 +186,15 @@ def test(data_dir=DATA_DIR):
class ImageNetDataset(Dataset):
def __init__(self, data_dir=DATA_DIR, mode='train'):
def __init__(self,
data_dir=DATA_DIR,
mode='train',
crop_size=DATA_DIM,
resize_size=RESIZE_DIM):
super(ImageNetDataset, self).__init__()
self.data_dir = data_dir
self.crop_size = crop_size
self.resize_size = resize_size
train_file_list = os.path.join(data_dir, 'train_list.txt')
val_file_list = os.path.join(data_dir, 'val_list.txt')
test_file_list = os.path.join(data_dir, 'test_list.txt')
......@@ -211,21 +218,27 @@ class ImageNetDataset(Dataset):
[data_path, sample[1]],
mode='train',
color_jitter=False,
rotate=False)
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data, np.array([label]).astype('int64')
elif self.mode == 'val':
data, label = process_image(
[data_path, sample[1]],
mode='val',
color_jitter=False,
rotate=False)
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data, np.array([label]).astype('int64')
elif self.mode == 'test':
data = process_image(
[data_path, sample[1]],
mode='test',
color_jitter=False,
rotate=False)
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data
def __len__(self):
......
......@@ -24,25 +24,25 @@
| 模型 | 策略 | Top-1 Acc | GPU 耗时(ms) | ARM CPU 耗时(ms) |
|:------:|:------:|:------:|:------:|:------:|
| MobileNetV1 | Baseline | 70.90 | - | 33.15 |
| MobileNetV1 | 量化+蒸馏 | 70.49 | - | 13.64 |
| MobileNetV1 | 量化+蒸馏 | 70.57 | - | 13.64 |
| ResNet50_vd | Baseline | 79.12 | 3.19 | - |
| ResNet50_vd | 量化+蒸馏 | 78.55 | 0.92 | - |
| ResNet50_vd | 量化+蒸馏 | 78.74 | 0.92 | - |
| ShuffleNetV2_x1_0 | Baseline | 68.65 | - | 10.43 |
| ShuffleNetV2_x1_0 | 量化+蒸馏 | 67.78 | - | 5.51 |
| ShuffleNetV2_x1_0 | 量化+蒸馏 | 68.32 | - | 5.51 |
| SqueezeNet1_0_infer | Baseline | 59.60 | - | 35.98 |
| SqueezeNet1_0_infer | 量化+蒸馏 | 59.13 | - | 16.96 |
| SqueezeNet1_0_infer | 量化+蒸馏 | 59.45 | - | 16.96 |
| PPLCNetV2_base | Baseline | 76.86 | - | 36.50 |
| PPLCNetV2_base | 量化+蒸馏 | 76.43 | - | 15.79 |
| PPHGNet_tiny | Baseline | 79.59 | 2.82 | - |
| PPHGNet_tiny | 量化+蒸馏 | 79.19 | 0.98 | - |
| PPHGNet_tiny | 量化+蒸馏 | 79.20 | 0.98 | - |
| InceptionV3 | Baseline | 79.14 | 4.79 | - |
| InceptionV3 | 量化+蒸馏 | 78.32 | 1.47 | - |
| EfficientNetB0 | Baseline | 77.02 | 1.95 | - |
| EfficientNetB0 | 量化+蒸馏 | 73.61 | 1.44 | - |
| EfficientNetB0 | 量化+蒸馏 | 75.39 | 1.44 | - |
| GhostNet_x1_0 | Baseline | 74.02 | 2.93 | - |
| GhostNet_x1_0 | 量化+蒸馏 | 71.11 | 1.03 | - |
| InceptionV3 | Baseline | 79.14 | 4.79 | - |
| InceptionV3 | 量化+蒸馏 | 73.16 | 1.47 | - |
| GhostNet_x1_0 | 量化+蒸馏 | 72.62 | 1.03 | - |
| MobileNetV3_large_x1_0 | Baseline | 75.32 | - | 16.62 |
| MobileNetV3_large_x1_0 | 量化+蒸馏 | 68.84 | - | 9.85 |
| MobileNetV3_large_x1_0 | 量化+蒸馏 | 70.93 | - | 9.85 |
- ARM CPU 测试环境:`SDM865(4xA77+4xA55)`
- Nvidia GPU 测试环境:
......@@ -119,7 +119,7 @@ python -m paddle.distributed.launch run.py --save_dir='./save_quant_mobilev1/' -
准备好inference模型后,使用以下命令进行预测:
```shell
python infer.py -c configs/infer.yaml
python infer.py --config_path="configs/infer.yaml"
```
在配置文件```configs/infer.yaml```中有以下字段用于配置预测参数:
......@@ -134,7 +134,7 @@ python infer.py -c configs/infer.yaml
- ```PostProcess.Topk.class_id_map_file```:数据集 label 的映射文件,默认为```./images/imagenet1k_label_list.txt```,该文件为 PaddleClas 所使用的 ImageNet 数据集 label 映射文件
注意:
- 请注意模型的输入数据尺寸,部分模型需要修改参数:```PreProcess.resize_short```, ```PreProcess.resize```
- 请注意模型的输入数据尺寸,如InceptionV3输入尺寸为299,所以部分模型需要修改参数:```PreProcess.resize_short```, ```PreProcess.resize```
- 如果希望提升评测模型速度,使用 ```GPU``` 评测时,建议开启 ```TensorRT``` 加速预测,使用 ```CPU``` 评测时,建议开启 ```MKL-DNN``` 加速预测
- 若使用 TesorRT 预测引擎,需安装 ```WITH_TRT=ON``` 的Paddle,下载地址:[Python预测库](https://paddleinference.paddlepaddle.org.cn/master/user_guides/download_lib.html#python)
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......@@ -33,3 +33,4 @@ TrainConfig:
optimizer:
type: Momentum
weight_decay: 0.00002
origin_metric: 0.7402
......@@ -4,6 +4,8 @@ Global:
model_filename: inference.pdmodel
params_filename: inference.pdiparams
batch_size: 32
resize_size: 320
crop_size: 299
data_dir: /ILSVRC2012
Distillation:
......
Global:
input_name: x
model_dir: InceptionV3_infer
model_dir: save_quant_inception
model_filename: inference.pdmodel
params_filename: inference.pdiparams
batch_size: 32
data_dir: /ILSVRC2012
resize_size: 320
img_size: 299
data_dir: /workspace/dataset/ILSVRC2012
Distillation:
alpha: 10.0
alpha: 1.0
loss: l2
node:
- softmax_1.tmp_0
Quantization:
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......@@ -21,6 +23,7 @@ Quantization:
- conv2d
- depthwise_conv2d
weight_bits: 8
TrainConfig:
epochs: 1
eval_iter: 500
......
......@@ -16,7 +16,7 @@ Quantization:
activation_bits: 8
is_full_quantize: false
activation_quantize_type: moving_average_abs_max
weight_quantize_type: abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
quantize_op_types:
......
......@@ -12,10 +12,10 @@ Distillation:
node:
- softmax_0.tmp_0
Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
use_pact: true
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......@@ -25,10 +25,10 @@ Quantization:
weight_bits: 8
TrainConfig:
epochs: 1
eval_iter: 2000
eval_iter: 500
learning_rate:
type: CosineAnnealingDecay
learning_rate: 0.0001
learning_rate: 0.015
optimizer_builder:
optimizer:
type: Momentum
......
Global:
input_name: x
model_dir: PPHGNet_tiny_infer
model_filename: inference.pdmodel
params_filename: inference.pdiparams
batch_size: 32
data_dir: /ILSVRC2012
Distillation:
alpha: 1.0
loss: l2
node:
- softmax_1.tmp_0
UnstructurePrune:
prune_strategy: gmp
prune_mode: ratio
ratio: 0.75
gmp_config:
stable_iterations: 0
pruning_iterations: 4500
tunning_iterations: 4500
resume_iteration: -1
pruning_steps: 100
initial_ratio: 0.15
prune_params_type: conv1x1_only
local_sparsity: True
TrainConfig:
epochs: 1
eval_iter: 500
learning_rate:
type: CosineAnnealingDecay
learning_rate: 0.015
optimizer_builder:
optimizer:
type: Momentum
weight_decay: 0.00002
origin_metric: 0.7959
\ No newline at end of file
Global:
input_name: x
model_dir: PPHGNet_tiny_infer
model_filename: inference.pdmodel
params_filename: inference.pdiparams
batch_size: 32
data_dir: /ILSVRC2012
Distillation:
alpha: 1.0
loss: l2
node:
- softmax_1.tmp_0
Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
quantize_op_types:
- conv2d
- depthwise_conv2d
weight_bits: 8
TrainConfig:
epochs: 1
eval_iter: 500
learning_rate:
type: CosineAnnealingDecay
learning_rate: 0.015
optimizer_builder:
optimizer:
type: Momentum
weight_decay: 0.00002
origin_metric: 0.7959
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -11,13 +11,10 @@ Distillation:
loss: l2
node:
- softmax_0.tmp_0
teacher_model_dir: SqueezeNet1_0_infer
teacher_model_filename: inference.pdmodel
teacher_params_filename: inference.pdiparams
Quantization:
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
......@@ -15,7 +15,7 @@ Quantization:
use_pact: true
activation_bits: 8
is_full_quantize: false
activation_quantize_type: range_abs_max
activation_quantize_type: moving_average_abs_max
weight_quantize_type: channel_wise_abs_max
not_quant_pattern:
- skip_quant
......
Global:
infer_imgs: "./images/ILSVRC2012_val_00000010.jpeg"
inference_model_dir: "./MobileNetV1_infer"
model_filename: "inference.pdmodel"
params_filename: "inference.pdiparams"
batch_size: 1
use_gpu: True
enable_mkldnn: True
cpu_num_threads: 10
enable_benchmark: True
use_fp16: False
use_int8: False
ir_optim: True
use_tensorrt: True
gpu_mem: 8000
enable_profile: False
benchmark: True
PreProcess:
transform_ops:
- ResizeImage:
resize_short: 256
- CropImage:
size: 224
- NormalizeImage:
scale: 0.00392157
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
channel_num: 3
- ToCHWImage:
PostProcess:
main_indicator: Topk
Topk:
topk: 5
class_id_map_file: "./images/imagenet1k_label_list.txt"
SavePreLabel:
save_dir: ./pre_label/
inference_model_dir: "./MobileNetV1_infer"
model_filename: "inference.pdmodel"
params_filename: "inference.pdiparams"
batch_size: 1
image_size: 224
use_gpu: True
enable_mkldnn: True
cpu_num_threads: 10
enable_benchmark: True
use_fp16: False
use_int8: False
ir_optim: True
use_tensorrt: True
gpu_mem: 8000
enable_profile: False
benchmark: True
......@@ -16,6 +16,7 @@ import os
import sys
sys.path[0] = os.path.join(
os.path.dirname("__file__"), os.path.pardir, os.path.pardir)
print(sys.path[0])
import argparse
import functools
from functools import partial
......@@ -23,8 +24,8 @@ from functools import partial
import numpy as np
import paddle
import paddle.nn as nn
from paddle.io import Dataset, BatchSampler, DataLoader
import imagenet_reader as reader
from paddle.io import DataLoader
from imagenet_reader import ImageNetDataset
from paddleslim.auto_compression.config_helpers import load_config as load_slim_config
......@@ -36,12 +37,22 @@ def argsparser():
default=None,
help="path of compression strategy config.",
required=True)
return parser
def eval_reader(data_dir, batch_size):
val_reader = paddle.batch(
reader.val(data_dir=data_dir), batch_size=batch_size)
return val_reader
def eval_reader(data_dir, batch_size, crop_size, resize_size):
val_reader = ImageNetDataset(
mode='val',
data_dir=data_dir,
crop_size=crop_size,
resize_size=resize_size)
val_loader = DataLoader(
val_reader,
batch_size=global_config['batch_size'],
shuffle=False,
drop_last=False,
num_workers=0)
return val_loader
def eval():
......@@ -55,19 +66,16 @@ def eval():
params_filename=global_config["params_filename"])
print('Loaded model from: {}'.format(global_config["model_dir"]))
val_reader = eval_reader(data_dir, batch_size=global_config['batch_size'])
image = paddle.static.data(
name=global_config['input_name'],
shape=[None, 3, 224, 224],
dtype='float32')
label = paddle.static.data(name='label', shape=[None, 1], dtype='int64')
val_loader = eval_reader(
data_dir,
batch_size=global_config['batch_size'],
crop_size=img_size,
resize_size=resize_size)
results = []
print('Evaluating... It will take a while. Please wait...')
for batch_id, data in enumerate(val_reader()):
# top1_acc, top5_acc
image = np.array([[d[0]] for d in data])
image = image.reshape((len(data), 3, 224, 224))
label = [[d[1]] for d in data]
print('Evaluating...')
for batch_id, (image, label) in enumerate(val_loader):
image = np.array(image)
label = np.array(label).astype('int64')
pred = exe.run(val_program,
feed={feed_target_names[0]: image},
fetch_list=fetch_targets)
......@@ -92,8 +100,15 @@ def main():
all_config = load_slim_config(args.config_path)
assert "Global" in all_config, f"Key 'Global' not found in config file. \n{all_config}"
global_config = all_config["Global"]
global data_dir
data_dir = global_config['data_dir']
global img_size, resize_size
img_size = global_config['img_size'] if 'img_size' in global_config else 224
resize_size = global_config[
'resize_size'] if 'resize_size' in global_config else 256
result = eval()
print('Eval Top1:', result)
......
import os
import math
import random
import functools
import numpy as np
import paddle
from PIL import Image, ImageEnhance
from paddle.io import Dataset
random.seed(0)
np.random.seed(0)
DATA_DIM = 224
RESIZE_DIM = 256
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, crop_size, resize_size):
img_path = sample[0]
try:
img = Image.open(img_path)
except:
print(img_path, "not exists!")
return None
if mode == 'train':
if rotate: img = rotate_image(img)
img = random_crop(img, crop_size)
else:
img = resize_short(img, target_size=resize_size)
img = crop_image(img, target_size=crop_size, 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)
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)
class ImageNetDataset(Dataset):
def __init__(self,
data_dir=DATA_DIR,
mode='train',
crop_size=DATA_DIM,
resize_size=RESIZE_DIM):
super(ImageNetDataset, self).__init__()
self.data_dir = data_dir
self.crop_size = crop_size
self.resize_size = resize_size
train_file_list = os.path.join(data_dir, 'train_list.txt')
val_file_list = os.path.join(data_dir, 'val_list.txt')
test_file_list = os.path.join(data_dir, 'test_list.txt')
self.mode = mode
if mode == 'train':
with open(train_file_list) as flist:
full_lines = [line.strip() for line in flist]
np.random.shuffle(full_lines)
lines = full_lines
self.data = [line.split() for line in lines]
else:
with open(val_file_list) as flist:
lines = [line.strip() for line in flist]
self.data = [line.split() for line in lines]
def __getitem__(self, index):
sample = self.data[index]
data_path = os.path.join(self.data_dir, sample[0])
if self.mode == 'train':
data, label = process_image(
[data_path, sample[1]],
mode='train',
color_jitter=False,
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data, np.array([label]).astype('int64')
elif self.mode == 'val':
data, label = process_image(
[data_path, sample[1]],
mode='val',
color_jitter=False,
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data, np.array([label]).astype('int64')
elif self.mode == 'test':
data = process_image(
[data_path, sample[1]],
mode='test',
color_jitter=False,
rotate=False,
crop_size=self.crop_size,
resize_size=self.resize_size)
return data
def __len__(self):
return len(self.data)
......@@ -13,141 +13,76 @@
# limitations under the License.
import os
import sys
import cv2
import numpy as np
import platform
import cv2
import time
import sys
import argparse
import base64
import shutil
import yaml
from utils import preprocess, postprocess
import paddle
from postprocess import build_postprocess
from preprocess import create_operators
from paddle.inference import create_predictor
from paddleslim.auto_compression.config_helpers import load_config
def argsparser():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'-c',
'--config',
'--config_path',
type=str,
default='configs/config.yaml',
default='configs/infer.yaml',
help='config file path')
return parser
def print_arguments(args):
print('----------- Running Arguments -----------')
for arg, value in args.items():
print('%s: %s' % (arg, value))
print('------------------------------------------')
def get_image_list(img_file):
imgs_lists = []
if img_file is None or not os.path.exists(img_file):
raise Exception("not found any img file in {}".format(img_file))
img_end = ['jpg', 'png', 'jpeg', 'JPEG', 'JPG', 'bmp']
if os.path.isfile(img_file) and img_file.split('.')[-1] in img_end:
imgs_lists.append(img_file)
elif os.path.isdir(img_file):
for single_file in os.listdir(img_file):
if single_file.split('.')[-1] in img_end:
imgs_lists.append(os.path.join(img_file, single_file))
if len(imgs_lists) == 0:
raise Exception("not found any img file in {}".format(img_file))
imgs_lists = sorted(imgs_lists)
return imgs_lists
class Predictor(object):
def __init__(self, config):
predict_args = config['Global']
# HALF precission predict only work when using tensorrt
if predict_args['use_fp16'] is True:
assert predict_args.use_tensorrt is True
self.args = predict_args
if self.args.get("use_onnx", False):
self.predictor, self.config = self.create_onnx_predictor(
predict_args)
else:
self.predictor, self.config = self.create_paddle_predictor(
predict_args)
self.preprocess_ops = []
self.postprocess = None
if "PreProcess" in config:
if "transform_ops" in config["PreProcess"]:
self.preprocess_ops = create_operators(config["PreProcess"][
"transform_ops"])
if "PostProcess" in config:
self.postprocess = build_postprocess(config["PostProcess"])
# for whole_chain project to test each repo of paddle
self.benchmark = config["Global"].get("benchmark", False)
if self.benchmark:
import auto_log
import os
pid = os.getpid()
size = config["PreProcess"]["transform_ops"][1]["CropImage"]["size"]
if config["Global"].get("use_int8", False):
precision = "int8"
elif config["Global"].get("use_fp16", False):
precision = "fp16"
else:
precision = "fp32"
self.auto_logger = auto_log.AutoLogger(
model_name=config["Global"].get("model_name", "cls"),
model_precision=precision,
batch_size=config["Global"].get("batch_size", 1),
data_shape=[3, size, size],
save_path=config["Global"].get("save_log_path",
"./auto_log.log"),
inference_config=self.config,
pids=pid,
process_name=None,
gpu_ids=None,
time_keys=[
'preprocess_time', 'inference_time', 'postprocess_time'
],
warmup=2)
def create_paddle_predictor(self, args):
inference_model_dir = args['inference_model_dir']
params_file = os.path.join(inference_model_dir, args['params_filename'])
model_file = os.path.join(inference_model_dir, args['model_filename'])
# HALF precission predict only work when using tensorrt
if config['use_fp16'] is True:
assert config['use_tensorrt'] is True
self.config = config
self.paddle_predictor = self.create_paddle_predictor()
input_names = self.paddle_predictor.get_input_names()
self.input_tensor = self.paddle_predictor.get_input_handle(input_names[
0])
output_names = self.paddle_predictor.get_output_names()
self.output_tensor = self.paddle_predictor.get_output_handle(
output_names[0])
def create_paddle_predictor(self):
inference_model_dir = self.config['inference_model_dir']
model_file = os.path.join(inference_model_dir,
self.config['model_filename'])
params_file = os.path.join(inference_model_dir,
self.config['params_filename'])
config = paddle.inference.Config(model_file, params_file)
if args['use_gpu']:
config.enable_use_gpu(args['gpu_mem'], 0)
precision = paddle.inference.Config.Precision.Float32
if self.config['use_int8']:
precision = paddle.inference.Config.Precision.Int8
elif self.config['use_fp16']:
precision = paddle.inference.Config.Precision.Half
if self.config['use_gpu']:
config.enable_use_gpu(self.config['gpu_mem'], 0)
else:
config.disable_gpu()
if args['enable_mkldnn']:
# there is no set_mkldnn_cache_capatity() on macOS
if platform.system() != "Darwin":
# cache 10 different shapes for mkldnn to avoid memory leak
config.set_mkldnn_cache_capacity(10)
if self.config['enable_mkldnn']:
# cache 10 different shapes for mkldnn to avoid memory leak
config.set_mkldnn_cache_capacity(10)
config.enable_mkldnn()
config.set_cpu_math_library_num_threads(args['cpu_num_threads'])
config.set_cpu_math_library_num_threads(self.config['cpu_num_threads'])
if args['enable_profile']:
if self.config['enable_profile']:
config.enable_profile()
config.disable_glog_info()
config.switch_ir_optim(args['ir_optim']) # default true
if args['use_tensorrt']:
precision = paddle.inference.Config.Precision.Float32
if args.get("use_int8", False):
precision = paddle.inference.Config.Precision.Int8
elif args.get("use_fp16", False):
precision = paddle.inference.Config.Precision.Half
config.switch_ir_optim(self.config['ir_optim']) # default true
if self.config['use_tensorrt']:
config.enable_tensorrt_engine(
precision_mode=precision,
max_batch_size=args['batch_size'],
max_batch_size=self.config['batch_size'],
workspace_size=1 << 30,
min_subgraph_size=30,
use_calib_mode=False)
......@@ -155,112 +90,36 @@ class Predictor(object):
config.enable_memory_optim()
# use zero copy
config.switch_use_feed_fetch_ops(False)
predictor = paddle.inference.create_predictor(config)
return predictor, config
def create_onnx_predictor(self, args):
import onnxruntime as ort
inference_model_dir = args['inference_model_dir']
model_file = os.path.join(inference_model_dir, args['model_filename'])
config = ort.SessionOptions()
if args['use_gpu']:
raise ValueError(
"onnx inference now only supports cpu! please specify use_gpu false."
)
else:
config.intra_op_num_threads = args['cpu_num_threads']
if args['ir_optim']:
config.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
predictor = ort.InferenceSession(model_file, sess_options=config)
return predictor, config
def predict(self, images):
use_onnx = self.args.get("use_onnx", False)
if not use_onnx:
input_names = self.predictor.get_input_names()
input_tensor = self.predictor.get_input_handle(input_names[0])
output_names = self.predictor.get_output_names()
output_tensor = self.predictor.get_output_handle(output_names[0])
else:
input_names = self.predictor.get_inputs()[0].name
output_names = self.predictor.get_outputs()[0].name
if self.benchmark:
self.auto_logger.times.start()
if not isinstance(images, (list, )):
images = [images]
for idx in range(len(images)):
for ops in self.preprocess_ops:
images[idx] = ops(images[idx])
image = np.array(images)
if self.benchmark:
self.auto_logger.times.stamp()
if not use_onnx:
input_tensor.copy_from_cpu(image)
self.predictor.run()
batch_output = output_tensor.copy_to_cpu()
else:
batch_output = self.predictor.run(
output_names=[output_names], input_feed={input_names: image})[0]
if self.benchmark:
self.auto_logger.times.stamp()
if self.postprocess is not None:
batch_output = self.postprocess(batch_output)
if self.benchmark:
self.auto_logger.times.end(stamp=True)
return batch_output
def main(config):
predictor = Predictor(config)
image_list = get_image_list(config["Global"]["infer_imgs"])
image_list = image_list * 1000
batch_imgs = []
batch_names = []
cnt = 0
for idx, img_path in enumerate(image_list):
img = cv2.imread(img_path)
if img is None:
logger.warning(
"Image file failed to read and has been skipped. The path: {}".
format(img_path))
else:
img = img[:, :, ::-1]
batch_imgs.append(img)
img_name = os.path.basename(img_path)
batch_names.append(img_name)
cnt += 1
if cnt % config["Global"]["batch_size"] == 0 or (idx + 1
) == len(image_list):
if len(batch_imgs) == 0:
continue
batch_results = predictor.predict(batch_imgs)
for number, result_dict in enumerate(batch_results):
if "PersonAttribute" in config[
"PostProcess"] or "VehicleAttribute" in config[
"PostProcess"]:
filename = batch_names[number]
else:
filename = batch_names[number]
clas_ids = result_dict["class_ids"]
scores_str = "[{}]".format(", ".join("{:.2f}".format(
r) for r in result_dict["scores"]))
label_names = result_dict["label_names"]
batch_imgs = []
batch_names = []
if predictor.benchmark:
predictor.auto_logger.report()
return
predictor = create_predictor(config)
return predictor
def predict(self):
test_num = 1000
test_time = 0.0
for i in range(0, test_num + 10):
inputs = np.random.rand(config['batch_size'], 3,
config['image_size'],
config['image_size']).astype(np.float32)
start_time = time.time()
self.input_tensor.copy_from_cpu(inputs)
self.paddle_predictor.run()
batch_output = self.output_tensor.copy_to_cpu().flatten()
if i >= 10:
test_time += time.time() - start_time
time.sleep(0.01) # sleep for T4 GPU
fp_message = "FP16" if config['use_fp16'] else "FP32"
trt_msg = "using tensorrt" if config[
'use_tensorrt'] else "not using tensorrt"
print("{0}\t{1}\tbatch size: {2}\ttime(ms): {3}".format(
trt_msg, fp_message, config[
'batch_size'], 1000 * test_time / test_num))
if __name__ == "__main__":
parser = argsparser()
args = parser.parse_args()
config = load_config(args.config)
print_arguments(config['Global'])
main(config)
config = load_config(args.config_path)
predictor = Predictor(config)
predictor.predict()
# copyright (c) 2022 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.
import os
import copy
import shutil
from functools import partial
import importlib
import numpy as np
import paddle
import paddle.nn.functional as F
def build_postprocess(config):
if config is None:
return None
mod = importlib.import_module(__name__)
config = copy.deepcopy(config)
main_indicator = config.pop(
"main_indicator") if "main_indicator" in config else None
main_indicator = main_indicator if main_indicator else ""
func_list = []
for func in config:
func_list.append(getattr(mod, func)(**config[func]))
return PostProcesser(func_list, main_indicator)
class PostProcesser(object):
def __init__(self, func_list, main_indicator="Topk"):
self.func_list = func_list
self.main_indicator = main_indicator
def __call__(self, x, image_file=None):
rtn = None
for func in self.func_list:
tmp = func(x, image_file)
if type(func).__name__ in self.main_indicator:
rtn = tmp
return rtn
class Topk(object):
def __init__(self, topk=1, class_id_map_file=None):
assert isinstance(topk, (int, ))
self.class_id_map = self.parse_class_id_map(class_id_map_file)
self.topk = topk
def parse_class_id_map(self, class_id_map_file):
if class_id_map_file is None:
return None
if not os.path.exists(class_id_map_file):
print(
"Warning: If want to use your own label_dict, please input legal path!\nOtherwise label_names will be empty!"
)
return None
try:
class_id_map = {}
with open(class_id_map_file, "r") as fin:
lines = fin.readlines()
for line in lines:
partition = line.split("\n")[0].partition(" ")
class_id_map[int(partition[0])] = str(partition[-1])
except Exception as ex:
print(ex)
class_id_map = None
return class_id_map
def __call__(self, x, file_names=None, multilabel=False):
if file_names is not None:
assert x.shape[0] == len(file_names)
y = []
for idx, probs in enumerate(x):
index = probs.argsort(axis=0)[-self.topk:][::-1].astype(
"int32") if not multilabel else np.where(
probs >= 0.5)[0].astype("int32")
clas_id_list = []
score_list = []
label_name_list = []
for i in index:
clas_id_list.append(i.item())
score_list.append(probs[i].item())
if self.class_id_map is not None:
label_name_list.append(self.class_id_map[i.item()])
result = {
"class_ids": clas_id_list,
"scores": np.around(
score_list, decimals=5).tolist(),
}
if file_names is not None:
result["file_name"] = file_names[idx]
if label_name_list is not None:
result["label_names"] = label_name_list
y.append(result)
return y
class SavePreLabel(object):
def __init__(self, save_dir):
if save_dir is None:
raise Exception(
"Please specify save_dir if SavePreLabel specified.")
self.save_dir = partial(os.path.join, save_dir)
def __call__(self, x, file_names=None):
if file_names is None:
return
assert x.shape[0] == len(file_names)
for idx, probs in enumerate(x):
index = probs.argsort(axis=0)[-1].astype("int32")
self.save(index, file_names[idx])
def save(self, id, image_file):
output_dir = self.save_dir(str(id))
os.makedirs(output_dir, exist_ok=True)
shutil.copy(image_file, output_dir)
# Copyright (c) 2022 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
from __future__ import unicode_literals
from functools import partial
import six
import math
import random
import cv2
import numpy as np
import importlib
from PIL import Image
def create_operators(params):
"""
create operators based on the config
Args:
params(list): a dict list, used to create some operators
"""
assert isinstance(params, list), ('operator config should be a list')
mod = importlib.import_module(__name__)
ops = []
for operator in params:
assert isinstance(operator,
dict) and len(operator) == 1, "yaml format error"
op_name = list(operator)[0]
param = {} if operator[op_name] is None else operator[op_name]
op = getattr(mod, op_name)(**param)
ops.append(op)
return ops
class UnifiedResize(object):
def __init__(self, interpolation=None, backend="cv2"):
_cv2_interp_from_str = {
'nearest': cv2.INTER_NEAREST,
'bilinear': cv2.INTER_LINEAR,
'area': cv2.INTER_AREA,
'bicubic': cv2.INTER_CUBIC,
'lanczos': cv2.INTER_LANCZOS4
}
_pil_interp_from_str = {
'nearest': Image.NEAREST,
'bilinear': Image.BILINEAR,
'bicubic': Image.BICUBIC,
'box': Image.BOX,
'lanczos': Image.LANCZOS,
'hamming': Image.HAMMING
}
def _pil_resize(src, size, resample):
pil_img = Image.fromarray(src)
pil_img = pil_img.resize(size, resample)
return np.asarray(pil_img)
if backend.lower() == "cv2":
if isinstance(interpolation, str):
interpolation = _cv2_interp_from_str[interpolation.lower()]
# compatible with opencv < version 4.4.0
elif interpolation is None:
interpolation = cv2.INTER_LINEAR
self.resize_func = partial(cv2.resize, interpolation=interpolation)
elif backend.lower() == "pil":
if isinstance(interpolation, str):
interpolation = _pil_interp_from_str[interpolation.lower()]
self.resize_func = partial(_pil_resize, resample=interpolation)
else:
logger.warning(
f"The backend of Resize only support \"cv2\" or \"PIL\". \"f{backend}\" is unavailable. Use \"cv2\" instead."
)
self.resize_func = cv2.resize
def __call__(self, src, size):
return self.resize_func(src, size)
class OperatorParamError(ValueError):
""" OperatorParamError
"""
pass
class ResizeImage(object):
""" resize image """
def __init__(self,
size=None,
resize_short=None,
interpolation=None,
backend="cv2"):
if resize_short is not None and resize_short > 0:
self.resize_short = resize_short
self.w = None
self.h = None
elif size is not None:
self.resize_short = None
self.w = size if type(size) is int else size[0]
self.h = size if type(size) is int else size[1]
else:
raise OperatorParamError("invalid params for ReisizeImage for '\
'both 'size' and 'resize_short' are None")
self._resize_func = UnifiedResize(
interpolation=interpolation, backend=backend)
def __call__(self, img):
img_h, img_w = img.shape[:2]
if self.resize_short is not None:
percent = float(self.resize_short) / min(img_w, img_h)
w = int(round(img_w * percent))
h = int(round(img_h * percent))
else:
w = self.w
h = self.h
return self._resize_func(img, (w, h))
class CropImage(object):
""" crop image """
def __init__(self, size):
if type(size) is int:
self.size = (size, size)
else:
self.size = size # (h, w)
def __call__(self, img):
w, h = self.size
img_h, img_w = img.shape[:2]
if img_h < h or img_w < w:
raise Exception(
f"The size({h}, {w}) of CropImage must be greater than size({img_h}, {img_w}) of image. Please check image original size and size of ResizeImage if used."
)
w_start = (img_w - w) // 2
h_start = (img_h - h) // 2
w_end = w_start + w
h_end = h_start + h
return img[h_start:h_end, w_start:w_end, :]
class NormalizeImage(object):
""" normalize image such as substract mean, divide std
"""
def __init__(self,
scale=None,
mean=None,
std=None,
order='chw',
output_fp16=False,
channel_num=3):
if isinstance(scale, str):
scale = eval(scale)
assert channel_num in [
3, 4
], "channel number of input image should be set to 3 or 4."
self.channel_num = channel_num
self.output_dtype = 'float16' if output_fp16 else 'float32'
self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
self.order = order
mean = mean if mean is not None else [0.485, 0.456, 0.406]
std = std if std is not None else [0.229, 0.224, 0.225]
shape = (3, 1, 1) if self.order == 'chw' else (1, 1, 3)
self.mean = np.array(mean).reshape(shape).astype('float32')
self.std = np.array(std).reshape(shape).astype('float32')
def __call__(self, img):
from PIL import Image
if isinstance(img, Image.Image):
img = np.array(img)
assert isinstance(img,
np.ndarray), "invalid input 'img' in NormalizeImage"
img = (img.astype('float32') * self.scale - self.mean) / self.std
if self.channel_num == 4:
img_h = img.shape[1] if self.order == 'chw' else img.shape[0]
img_w = img.shape[2] if self.order == 'chw' else img.shape[1]
pad_zeros = np.zeros(
(1, img_h, img_w)) if self.order == 'chw' else np.zeros(
(img_h, img_w, 1))
img = (np.concatenate(
(img, pad_zeros), axis=0)
if self.order == 'chw' else np.concatenate(
(img, pad_zeros), axis=2))
return img.astype(self.output_dtype)
class ToCHWImage(object):
""" convert hwc image to chw image
"""
def __init__(self):
pass
def __call__(self, img):
from PIL import Image
if isinstance(img, Image.Image):
img = np.array(img)
return img.transpose((2, 0, 1))
......@@ -19,13 +19,13 @@ sys.path[0] = os.path.join(
import argparse
import functools
from functools import partial
import math
import numpy as np
import math
import paddle
import paddle.nn as nn
from paddle.io import Dataset, BatchSampler, DataLoader
import imagenet_reader as reader
from paddle.io import DataLoader
from imagenet_reader import ImageNetDataset
from paddleslim.auto_compression.config_helpers import load_config as load_slim_config
from paddleslim.auto_compression import AutoCompression
......@@ -54,35 +54,41 @@ def argsparser():
# yapf: enable
def reader_wrapper(reader, input_name):
def gen():
for i, data in enumerate(reader()):
imgs = np.float32([item[0] for item in data])
for i, (imgs, label) in enumerate(reader()):
yield {input_name: imgs}
return gen
def eval_reader(data_dir, batch_size):
val_reader = paddle.batch(
reader.val(data_dir=data_dir), batch_size=batch_size)
return val_reader
def eval_reader(data_dir, batch_size, crop_size, resize_size):
val_reader = ImageNetDataset(
mode='val',
data_dir=data_dir,
crop_size=crop_size,
resize_size=resize_size)
val_loader = DataLoader(
val_reader,
batch_size=global_config['batch_size'],
shuffle=False,
drop_last=False,
num_workers=0)
return val_loader
def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
val_reader = eval_reader(data_dir, batch_size=global_config['batch_size'])
image = paddle.static.data(
name=global_config['input_name'],
shape=[None, 3, 224, 224],
dtype='float32')
label = paddle.static.data(name='label', shape=[None, 1], dtype='int64')
val_loader = eval_reader(
data_dir,
batch_size=global_config['batch_size'],
crop_size=img_size,
resize_size=resize_size)
results = []
print('Evaluating... It will take a while. Please wait...')
for batch_id, data in enumerate(val_reader()):
print('Evaluating...')
for batch_id, (image, label) in enumerate(val_loader):
# top1_acc, top5_acc
if len(test_feed_names) == 1:
image = np.array([[d[0]] for d in data])
image = image.reshape((len(data), 3, 224, 224))
label = [[d[1]] for d in data]
image = np.array(image)
label = np.array(label).astype('int64')
pred = exe.run(compiled_test_program,
feed={test_feed_names[0]: image},
fetch_list=test_fetch_list)
......@@ -100,9 +106,8 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
results.append([top_1, top_5])
else:
# eval "eval model", which inputs are image and label, output is top1 and top5 accuracy
image = np.array([[d[0]] for d in data])
image = image.reshape((len(data), 3, 224, 224))
label = [[d[1]] for d in data]
image = np.array(image)
label = np.array(label).astype('int64')
result = exe.run(
compiled_test_program,
feed={test_feed_names[0]: image,
......@@ -110,6 +115,8 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
fetch_list=test_fetch_list)
result = [np.mean(r) for r in result]
results.append(result)
if batch_id % 100 == 0:
print('Eval iter: ', batch_id)
result = np.mean(np.array(results), axis=0)
return result[0]
......@@ -117,8 +124,10 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
def main():
global global_config
all_config = load_slim_config(args.config_path)
assert "Global" in all_config, f"Key 'Global' not found in config file. \n{all_config}"
global_config = all_config["Global"]
gpu_num = paddle.distributed.get_world_size()
if isinstance(all_config['TrainConfig']['learning_rate'],
dict) and all_config['TrainConfig']['learning_rate'][
......@@ -129,12 +138,28 @@ def main():
gpu_num)))
all_config['TrainConfig']['learning_rate']['T_max'] = step
print('total training steps:', step)
global data_dir
data_dir = global_config['data_dir']
train_reader = paddle.batch(
reader.train(data_dir=data_dir), batch_size=global_config['batch_size'])
train_dataloader = reader_wrapper(train_reader, global_config['input_name'])
global img_size, resize_size
img_size = global_config['img_size'] if 'img_size' in global_config else 224
resize_size = global_config[
'resize_size'] if 'resize_size' in global_config else 256
train_dataset = ImageNetDataset(
mode='train',
data_dir=data_dir,
crop_size=img_size,
resize_size=resize_size)
train_loader = DataLoader(
train_dataset,
batch_size=global_config['batch_size'],
shuffle=True,
drop_last=True,
num_workers=0)
train_dataloader = reader_wrapper(train_loader, global_config['input_name'])
ac = AutoCompression(
model_dir=global_config['model_dir'],
......@@ -145,7 +170,11 @@ def main():
train_dataloader=train_dataloader,
eval_callback=eval_function,
eval_dataloader=reader_wrapper(
eval_reader(data_dir, global_config['batch_size']),
eval_reader(
data_dir,
global_config['batch_size'],
crop_size=img_size,
resize_size=resize_size),
global_config['input_name']))
ac.compress()
......
# 单卡启动
export CUDA_VISIBLE_DEVICES=0
python3.7 eval.py --save_dir='./save_quant_mobilev1/' --config_path='./configs/MobileNetV1/qat_dis.yaml'
# 多卡启动
export CUDA_VISIBLE_DEVICES=0,1,2,3
python -m paddle.distributed.launch run.py --save_dir='./save_quant_mobilev1/' --config_path='./configs/MobileNetV1/qat_dis.yaml'
# Copyright (c) 2020 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 argparse
import base64
import shutil
import cv2
import numpy as np
def preprocess(img, args):
resize_op = ResizeImage(resize_short=args.resize_short)
img = resize_op(img)
crop_op = CropImage(size=(args.resize, args.resize))
img = crop_op(img)
if args.normalize:
img_mean = [0.485, 0.456, 0.406]
img_std = [0.229, 0.224, 0.225]
img_scale = 1.0 / 255.0
normalize_op = NormalizeImage(
scale=img_scale, mean=img_mean, std=img_std)
img = normalize_op(img)
tensor_op = ToTensor()
img = tensor_op(img)
return img
def postprocess(batch_outputs, topk=5, multilabel=False):
batch_results = []
for probs in batch_outputs:
results = []
if multilabel:
index = np.where(probs >= 0.5)[0].astype('int32')
else:
index = probs.argsort(axis=0)[-topk:][::-1].astype("int32")
clas_id_list = []
score_list = []
for i in index:
clas_id_list.append(i.item())
score_list.append(probs[i].item())
batch_results.append({"clas_ids": clas_id_list, "scores": score_list})
return batch_results
class ResizeImage(object):
def __init__(self, resize_short=None):
self.resize_short = resize_short
def __call__(self, img):
img_h, img_w = img.shape[:2]
percent = float(self.resize_short) / min(img_w, img_h)
w = int(round(img_w * percent))
h = int(round(img_h * percent))
return cv2.resize(img, (w, h))
class CropImage(object):
def __init__(self, size):
if type(size) is int:
self.size = (size, size)
else:
self.size = size
def __call__(self, img):
w, h = self.size
img_h, img_w = img.shape[:2]
w_start = (img_w - w) // 2
h_start = (img_h - h) // 2
w_end = w_start + w
h_end = h_start + h
return img[h_start:h_end, w_start:w_end, :]
class NormalizeImage(object):
def __init__(self, scale=None, mean=None, std=None):
self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
mean = mean if mean is not None else [0.485, 0.456, 0.406]
std = std if std is not None else [0.229, 0.224, 0.225]
shape = (1, 1, 3)
self.mean = np.array(mean).reshape(shape).astype('float32')
self.std = np.array(std).reshape(shape).astype('float32')
def __call__(self, img):
return (img.astype('float32') * self.scale - self.mean) / self.std
class ToTensor(object):
def __init__(self):
pass
def __call__(self, img):
img = img.transpose((2, 0, 1))
return img
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册