Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
s920243400
PaddleDetection
提交
709b706d
P
PaddleDetection
项目概览
s920243400
/
PaddleDetection
与 Fork 源项目一致
Fork自
PaddlePaddle / PaddleDetection
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleDetection
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
709b706d
编写于
10月 12, 2019
作者:
L
Liufang Sang
提交者:
whs
10月 12, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[PaddleSlim] add infer.py and add run cmd for yolov3 quantization demo (#3522)
上级
fdb027df
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
322 addition
and
11 deletion
+322
-11
slim/eval.py
slim/eval.py
+0
-0
slim/infer.py
slim/infer.py
+276
-0
slim/quantization/README.md
slim/quantization/README.md
+41
-6
slim/quantization/compress.py
slim/quantization/compress.py
+1
-1
slim/quantization/yolov3_mobilenet_v1_slim.yaml
slim/quantization/yolov3_mobilenet_v1_slim.yaml
+2
-2
slim/quantization/yolov3_mobilenet_v1_voc.yml
slim/quantization/yolov3_mobilenet_v1_voc.yml
+2
-2
未找到文件。
slim/
quantization/
eval.py
→
slim/eval.py
浏览文件 @
709b706d
文件已移动
slim/infer.py
0 → 100644
浏览文件 @
709b706d
# 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
os
import
sys
import
glob
import
numpy
as
np
from
PIL
import
Image
sys
.
path
.
append
(
"../../"
)
def
set_paddle_flags
(
**
kwargs
):
for
key
,
value
in
kwargs
.
items
():
if
os
.
environ
.
get
(
key
,
None
)
is
None
:
os
.
environ
[
key
]
=
str
(
value
)
# NOTE(paddle-dev): All of these flags should be set before
# `import paddle`. Otherwise, it would not take any effect.
set_paddle_flags
(
FLAGS_eager_delete_tensor_gb
=
0
,
# enable GC to save memory
)
from
paddle
import
fluid
from
ppdet.utils.cli
import
print_total_cfg
from
ppdet.core.workspace
import
load_config
,
merge_config
,
create
from
ppdet.modeling.model_input
import
create_feed
from
ppdet.data.data_feed
import
create_reader
from
ppdet.utils.eval_utils
import
parse_fetches
from
ppdet.utils.cli
import
ArgsParser
from
ppdet.utils.check
import
check_gpu
from
ppdet.utils.visualizer
import
visualize_results
import
ppdet.utils.checkpoint
as
checkpoint
import
logging
FORMAT
=
'%(asctime)s-%(levelname)s: %(message)s'
logging
.
basicConfig
(
level
=
logging
.
INFO
,
format
=
FORMAT
)
logger
=
logging
.
getLogger
(
__name__
)
def
get_save_image_name
(
output_dir
,
image_path
):
"""
Get save image name from source image path.
"""
if
not
os
.
path
.
exists
(
output_dir
):
os
.
makedirs
(
output_dir
)
image_name
=
os
.
path
.
split
(
image_path
)[
-
1
]
name
,
ext
=
os
.
path
.
splitext
(
image_name
)
return
os
.
path
.
join
(
output_dir
,
"{}"
.
format
(
name
))
+
ext
def
get_test_images
(
infer_dir
,
infer_img
):
"""
Get image path list in TEST mode
"""
assert
infer_img
is
not
None
or
infer_dir
is
not
None
,
\
"--infer_img or --infer_dir should be set"
assert
infer_img
is
None
or
os
.
path
.
isfile
(
infer_img
),
\
"{} is not a file"
.
format
(
infer_img
)
assert
infer_dir
is
None
or
os
.
path
.
isdir
(
infer_dir
),
\
"{} is not a directory"
.
format
(
infer_dir
)
images
=
[]
# infer_img has a higher priority
if
infer_img
and
os
.
path
.
isfile
(
infer_img
):
images
.
append
(
infer_img
)
return
images
infer_dir
=
os
.
path
.
abspath
(
infer_dir
)
assert
os
.
path
.
isdir
(
infer_dir
),
\
"infer_dir {} is not a directory"
.
format
(
infer_dir
)
exts
=
[
'jpg'
,
'jpeg'
,
'png'
,
'bmp'
]
exts
+=
[
ext
.
upper
()
for
ext
in
exts
]
for
ext
in
exts
:
images
.
extend
(
glob
.
glob
(
'{}/*.{}'
.
format
(
infer_dir
,
ext
)))
assert
len
(
images
)
>
0
,
"no image found in {}"
.
format
(
infer_dir
)
logger
.
info
(
"Found {} inference images in total."
.
format
(
len
(
images
)))
return
images
def
main
():
cfg
=
load_config
(
FLAGS
.
config
)
if
'architecture'
in
cfg
:
main_arch
=
cfg
.
architecture
else
:
raise
ValueError
(
"'architecture' not specified in config file."
)
merge_config
(
FLAGS
.
opt
)
# check if set use_gpu=True in paddlepaddle cpu version
check_gpu
(
cfg
.
use_gpu
)
# print_total_cfg(cfg)
if
'test_feed'
not
in
cfg
:
test_feed
=
create
(
main_arch
+
'TestFeed'
)
else
:
test_feed
=
create
(
cfg
.
test_feed
)
test_images
=
get_test_images
(
FLAGS
.
infer_dir
,
FLAGS
.
infer_img
)
test_feed
.
dataset
.
add_images
(
test_images
)
place
=
fluid
.
CUDAPlace
(
0
)
if
cfg
.
use_gpu
else
fluid
.
CPUPlace
()
exe
=
fluid
.
Executor
(
place
)
infer_prog
,
feed_var_names
,
fetch_list
=
fluid
.
io
.
load_inference_model
(
dirname
=
FLAGS
.
model_path
,
model_filename
=
FLAGS
.
model_name
,
params_filename
=
FLAGS
.
params_name
,
executor
=
exe
)
reader
=
create_reader
(
test_feed
)
feeder
=
fluid
.
DataFeeder
(
place
=
place
,
feed_list
=
feed_var_names
,
program
=
infer_prog
)
# parse infer fetches
assert
cfg
.
metric
in
[
'COCO'
,
'VOC'
],
\
"unknown metric type {}"
.
format
(
cfg
.
metric
)
extra_keys
=
[]
if
cfg
[
'metric'
]
==
'COCO'
:
extra_keys
=
[
'im_info'
,
'im_id'
,
'im_shape'
]
if
cfg
[
'metric'
]
==
'VOC'
:
extra_keys
=
[
'im_id'
,
'im_shape'
]
keys
,
values
,
_
=
parse_fetches
({
'bbox'
:
fetch_list
},
infer_prog
,
extra_keys
)
# parse dataset category
if
cfg
.
metric
==
'COCO'
:
from
ppdet.utils.coco_eval
import
bbox2out
,
mask2out
,
get_category_info
if
cfg
.
metric
==
"VOC"
:
from
ppdet.utils.voc_eval
import
bbox2out
,
get_category_info
anno_file
=
getattr
(
test_feed
.
dataset
,
'annotation'
,
None
)
with_background
=
getattr
(
test_feed
,
'with_background'
,
True
)
use_default_label
=
getattr
(
test_feed
,
'use_default_label'
,
False
)
clsid2catid
,
catid2name
=
get_category_info
(
anno_file
,
with_background
,
use_default_label
)
# whether output bbox is normalized in model output layer
is_bbox_normalized
=
False
# use tb-paddle to log image
if
FLAGS
.
use_tb
:
from
tb_paddle
import
SummaryWriter
tb_writer
=
SummaryWriter
(
FLAGS
.
tb_log_dir
)
tb_image_step
=
0
tb_image_frame
=
0
# each frame can display ten pictures at most.
imid2path
=
reader
.
imid2path
keys
=
[
'bbox'
]
for
iter_id
,
data
in
enumerate
(
reader
()):
feed_data
=
[[
d
[
0
],
d
[
1
]]
for
d
in
data
]
outs
=
exe
.
run
(
infer_prog
,
feed
=
feeder
.
feed
(
feed_data
),
fetch_list
=
fetch_list
,
return_numpy
=
False
)
res
=
{
k
:
(
np
.
array
(
v
),
v
.
recursive_sequence_lengths
())
for
k
,
v
in
zip
(
keys
,
outs
)
}
res
[
'im_id'
]
=
[[
d
[
2
]
for
d
in
data
]]
logger
.
info
(
'Infer iter {}'
.
format
(
iter_id
))
bbox_results
=
None
mask_results
=
None
if
'bbox'
in
res
:
bbox_results
=
bbox2out
([
res
],
clsid2catid
,
is_bbox_normalized
)
if
'mask'
in
res
:
mask_results
=
mask2out
([
res
],
clsid2catid
,
model
.
mask_head
.
resolution
)
# visualize result
im_ids
=
res
[
'im_id'
][
0
]
for
im_id
in
im_ids
:
image_path
=
imid2path
[
int
(
im_id
)]
image
=
Image
.
open
(
image_path
).
convert
(
'RGB'
)
# use tb-paddle to log original image
if
FLAGS
.
use_tb
:
original_image_np
=
np
.
array
(
image
)
tb_writer
.
add_image
(
"original/frame_{}"
.
format
(
tb_image_frame
),
original_image_np
,
tb_image_step
,
dataformats
=
'HWC'
)
image
=
visualize_results
(
image
,
int
(
im_id
),
catid2name
,
FLAGS
.
draw_threshold
,
bbox_results
,
mask_results
)
# use tb-paddle to log image with bbox
if
FLAGS
.
use_tb
:
infer_image_np
=
np
.
array
(
image
)
tb_writer
.
add_image
(
"bbox/frame_{}"
.
format
(
tb_image_frame
),
infer_image_np
,
tb_image_step
,
dataformats
=
'HWC'
)
tb_image_step
+=
1
if
tb_image_step
%
10
==
0
:
tb_image_step
=
0
tb_image_frame
+=
1
save_name
=
get_save_image_name
(
FLAGS
.
output_dir
,
image_path
)
logger
.
info
(
"Detection bbox results save in {}"
.
format
(
save_name
))
image
.
save
(
save_name
,
quality
=
95
)
if
__name__
==
'__main__'
:
parser
=
ArgsParser
()
parser
.
add_argument
(
"--infer_dir"
,
type
=
str
,
default
=
None
,
help
=
"Directory for images to perform inference on."
)
parser
.
add_argument
(
"--infer_img"
,
type
=
str
,
default
=
None
,
help
=
"Image path, has higher priority over --infer_dir"
)
parser
.
add_argument
(
"--output_dir"
,
type
=
str
,
default
=
"output"
,
help
=
"Directory for storing the output visualization files."
)
parser
.
add_argument
(
"--draw_threshold"
,
type
=
float
,
default
=
0.5
,
help
=
"Threshold to reserve the result for visualization."
)
parser
.
add_argument
(
"--use_tb"
,
type
=
bool
,
default
=
False
,
help
=
"whether to record the data to Tensorboard."
)
parser
.
add_argument
(
'--tb_log_dir'
,
type
=
str
,
default
=
"tb_log_dir/image"
,
help
=
'Tensorboard logging directory for image.'
)
parser
.
add_argument
(
'--model_path'
,
type
=
str
,
default
=
None
,
help
=
"inference model path"
)
parser
.
add_argument
(
'--model_name'
,
type
=
str
,
default
=
'__model__.infer'
,
help
=
"model filename for inference model"
)
parser
.
add_argument
(
'--params_name'
,
type
=
str
,
default
=
'__params__'
,
help
=
"params filename for inference model"
)
FLAGS
=
parser
.
parse_args
()
main
()
slim/quantization/README.md
浏览文件 @
709b706d
...
...
@@ -44,9 +44,9 @@ step1: 开启显存优化策略
export FLAGS_fast_eager_deletion_mode=1
export FLAGS_eager_delete_tensor_gb=0.0
```
step2: 设置gpu卡
step2: 设置gpu卡
,目前的超参设置适合2卡训练
```
export CUDA_VISIBLE_DEVICES=0
export CUDA_VISIBLE_DEVICES=0
,1
```
step3: 开始训练
```
...
...
@@ -104,6 +104,12 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺
<img
src=
"./images/TransformForMobilePass.png"
height=
400
width=
400
hspace=
'10'
/>
<br
/>
<strong>
图4:应用TransformForMobilePass后的结果
</strong>
</p>
> 综上,可得在量化过程中有以下几种模型结构:
1.
原始模型
2.
经QuantizationTransformPass之后得到的适用于训练的量化模型结构,在${checkpoint_path}下保存的
`eval_model`
是这种结构,在训练过程中每个epoch结束时也使用这个网络结构进行评估,虽然这个模型结构不是最终想要的模型结构,但是每个epoch的评估结果可用来挑选模型。
3.
经QuantizationFreezePass之后得到的FP32模型结构,具体结构已在上面进行介绍。本文档中列出的数据集的评估结果是对FP32模型结构进行评估得到的结果。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的
`end_epoch`
结束时进行保存,如果想将其他epoch的训练结果转化成FP32模型,可使用脚本
<a
href=
'./freeze.py'
>
PaddleSlim/classification/quantization/freeze.py
</a>
进行转化,具体使用方法在
[
评估
](
#评估
)
中介绍。
4.
经ConvertToInt8Pass之后得到的8-bit模型结构,具体结构已在上面进行介绍。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的
`end_epoch`
结束时进行保存,如果想将其他epoch的训练结果转化成8-bit模型,可使用脚本
<a
href=
'./freeze.py'
>
slim/quantization/freeze.py
</a>
进行转化,具体使用方法在
[
评估
](
#评估
)
中介绍。
5.
经TransformForMobilePass之后得到的mobile模型结构,具体结构已在上面进行介绍。这种模型结构在训练过程中只会保存一次,也就是在量化配置文件中设置的
`end_epoch`
结束时进行保存,如果想将其他epoch的训练结果转化成mobile模型,可使用脚本
<a
href=
'./freeze.py'
>
slim/quantization/freeze.py
</a>
进行转化,具体使用方法在
[
评估
](
#评估
)
中介绍。
## 评估
...
...
@@ -115,10 +121,14 @@ QuantizationFreezePass主要用于改变IrGraph中量化op和反量化op的顺
如果不需要保存评估模型,可以在定义Compressor对象时,将
`save_eval_model`
选项设置为False(默认为True)。
脚本
<a
href=
".
/eval.py"
>
slim/quantization
/eval.py
</a>
中为使用该模型在评估数据集上做评估的示例。
脚本
<a
href=
".
./eval.py"
>
slim
/eval.py
</a>
中为使用该模型在评估数据集上做评估的示例。
运行命令为:
```
python eval.py --model_path ${checkpoint_path}/${epoch_id}/eval_model/ --model_name __model__ --params_name __params__ -c yolov3_mobilenet_v1_voc.yml
python ../eval.py \
--model_path ${checkpoint_path}/${epoch_id}/eval_model/ \
--model_name __model__ \
--params_name __params__ \
-c yolov3_mobilenet_v1_voc.yml
```
在评估之后,选取效果最好的epoch的模型,可使用脚本
<a
href=
'./freeze.py'
>
slim/quantization/freeze.py
</a>
将该模型转化为以上介绍的三种模型:FP32模型,int8模型,mobile模型,需要配置的参数为:
...
...
@@ -127,16 +137,41 @@ python eval.py --model_path ${checkpoint_path}/${epoch_id}/eval_model/ --model_n
-
weight_quant_type 模型参数的量化方式,和配置文件中的类型保持一致
-
save_path
`FP32`
,
`8-bit`
,
`mobile`
模型的保存路径,分别为
`${save_path}/float/`
,
`${save_path}/int8/`
,
`${save_path}/mobile/`
运行命令示例:
```
python freeze.py \
--model_path ${checkpoint_path}/${epoch_id}/eval_model/ \
--weight_quant_type ${weight_quant_type} \
--save_path ${any path you want}
```
### 最终评估模型
最终使用的评估模型是FP32模型,使用脚本
<a
href=
".
/eval.py"
>
slim/quantization
/eval.py
</a>
中为使用该模型在评估数据集上做评估的示例。
最终使用的评估模型是FP32模型,使用脚本
<a
href=
".
./eval.py"
>
slim
/eval.py
</a>
中为使用该模型在评估数据集上做评估的示例。
运行命令为:
```
python eval.py --model_path ${float_model_path} --model_name model --params_name weights -c yolov3_mobilenet_v1_voc.yml
python ../eval.py \
--model_path ${float_model_path}
--model_name model \
--params_name weights \
-c yolov3_mobilenet_v1_voc.yml
```
## 预测
### python预测
FP32模型可直接使用原生PaddlePaddle Fluid预测方法进行预测。
在脚本
<a
href=
"../infer.py"
>
slim/infer.py
</a>
中展示了如何使用fluid python API加载使用预测模型进行预测。
运行命令示例:
```
python ../infer.py \
--model_path ${save_path}/float \
--model_name model \
--params_name weights \
-c yolov3_mobilenet_v1_voc.yml \
--infer_dir ../../demo
```
### PaddleLite预测
...
...
slim/quantization/compress.py
浏览文件 @
709b706d
...
...
@@ -201,6 +201,7 @@ def main():
checkpoint
.
load_params
(
exe
,
train_prog
,
cfg
.
pretrain_weights
)
best_box_ap_list
=
[]
def
eval_func
(
program
,
scope
):
...
...
@@ -208,7 +209,6 @@ def main():
#exe = fluid.Executor(place)
results
=
eval_run
(
exe
,
program
,
eval_reader
,
eval_keys
,
eval_values
,
eval_cls
,
test_data_feed
)
best_box_ap_list
=
[]
resolution
=
None
if
'mask'
in
results
[
0
]:
...
...
slim/quantization/yolov3_mobilenet_v1_slim.yaml
浏览文件 @
709b706d
...
...
@@ -3,7 +3,7 @@ strategies:
quantization_strategy
:
class
:
'
QuantizationStrategy'
start_epoch
:
0
end_epoch
:
0
end_epoch
:
4
float_model_save_path
:
'
./output/yolov3/float'
mobile_model_save_path
:
'
./output/yolov3/mobile'
int8_model_save_path
:
'
./output/yolov3/int8'
...
...
@@ -14,7 +14,7 @@ strategies:
save_in_nodes
:
[
'
image'
,
'
im_size'
]
save_out_nodes
:
[
'
multiclass_nms_0.tmp_0'
]
compressor
:
epoch
:
1
epoch
:
5
checkpoint_path
:
'
./checkpoints/yolov3/'
strategies
:
-
quantization_strategy
slim/quantization/yolov3_mobilenet_v1_voc.yml
浏览文件 @
709b706d
...
...
@@ -3,7 +3,7 @@ train_feed: YoloTrainFeed
eval_feed
:
YoloEvalFeed
test_feed
:
YoloTestFeed
use_gpu
:
true
max_iters
:
70
000
max_iters
:
1
000
log_smooth_window
:
20
save_dir
:
output
snapshot_iter
:
2000
...
...
@@ -45,8 +45,8 @@ LearningRate:
-
!PiecewiseDecay
gamma
:
0.1
milestones
:
-
1000
-
2000
-
8000
#- !LinearWarmup
#start_factor: 0.
#steps: 1000
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录