未验证 提交 dab4becc 编写于 作者: F FDInSky 提交者: GitHub

add train&eval (#1042)

add train&eval 
add reader padding 
add new config 
上级 df151054
architecture: CascadeRCNN
use_gpu: true
max_iters: 180000
log_smooth_window: 50
save_dir: output
snapshot_iter: 10000
pretrain_weights: https://paddlemodels.bj.bcebos.com/object_detection/dygraph/resnet50.pdparams
metric: COCO
weights: output/cascade_rcnn_r50_1x/model_final
num_classes: 81
num_stages: 3
open_debug: False
# Model Achitecture
CascadeRCNN:
# model anchor info flow
anchor: AnchorRPN
proposal: Proposal
mask: Mask
# model feat info flow
backbone: ResNet
rpn_head: RPNHead
bbox_head: BBoxHead
mask_head: MaskHead
ResNet:
norm_type: 'affine'
depth: 50
freeze_at: 'res2'
RPNHead:
rpn_feat:
name: RPNFeat
feat_in: 1024
feat_out: 1024
anchor_per_position: 15
BBoxHead:
bbox_feat:
name: BBoxFeat
feat_in: 1024
feat_out: 512
roi_extractor:
resolution: 14
sampling_ratio: 0
spatial_scale: 0.0625
extractor_type: 'RoIAlign'
MaskHead:
mask_feat:
name: MaskFeat
feat_in: 2048
feat_out: 256
feat_in: 256
resolution: 14
AnchorRPN:
anchor_generator:
name: AnchorGeneratorRPN
anchor_sizes: [32, 64, 128, 256, 512]
aspect_ratios: [0.5, 1.0, 2.0]
stride: [16.0, 16.0]
variance: [1.0, 1.0, 1.0, 1.0]
anchor_target_generator:
name: AnchorTargetGeneratorRPN
batch_size_per_im: 256
fg_fraction: 0.5
negative_overlap: 0.3
positive_overlap: 0.7
straddle_thresh: 0.0
Proposal:
proposal_generator:
name: ProposalGenerator
min_size: 0.0
nms_thresh: 0.7
train_pre_nms_top_n: 2000
train_post_nms_top_n: 2000
infer_pre_nms_top_n: 2000
infer_post_nms_top_n: 2000
return_rois_num: True
proposal_target_generator:
name: ProposalTargetGenerator
batch_size_per_im: 512
bbox_reg_weights: [[0.1, 0.1, 0.2, 0.2],[0.05, 0.05, 0.1, 0.1],[0.333333, 0.333333, 0.666666, 0.666666]]
bg_thresh_hi: [0.5, 0.6, 0.7]
bg_thresh_lo: [0.0, 0.0, 0.0]
fg_thresh: [0.5, 0.6, 0.7]
fg_fraction: 0.25
bbox_post_process: # used in infer
name: BBoxPostProcess
# decode -> clip -> nms
decode_clip_nms:
name: DecodeClipNms
keep_top_k: 100
score_threshold: 0.05
nms_threshold: 0.5
Mask:
mask_target_generator:
name: MaskTargetGenerator
resolution: 14
mask_post_process:
name: MaskPostProcess
# Train
LearningRate:
base_lr: 0.01
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones: [120000, 160000]
- !LinearWarmup
start_factor: 0.3333333333333333
steps: 500
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0001
type: L2
_READER_: 'mask_reader.yml'
architecture: FasterRCNN
use_gpu: true
max_iters: 180000
log_smooth_window: 50
save_dir: output
snapshot_iter: 10000
pretrain_weights: https://paddlemodels.bj.bcebos.com/object_detection/dygraph/resnet50.pdparams
metric: COCO
weights: output/faster_rcnn_r50_1x/model_final
num_classes: 81
open_debug: False
# Model Achitecture
FasterRCNN:
# model anchor info flow
anchor: AnchorRPN
proposal: Proposal
# model feat info flow
backbone: ResNet
rpn_head: RPNHead
bbox_head: BBoxHead
ResNet:
depth: 50
norm_type: 'affine'
freeze_at: 'res2'
RPNHead:
rpn_feat:
name: RPNFeat
feat_in: 1024
feat_out: 1024
anchor_per_position: 15
BBoxHead:
bbox_feat:
name: BBoxFeat
roi_extractor:
name: RoIExtractor
resolution: 14
sampling_ratio: 0
spatial_scale: 0.0625
extractor_type: 'RoIAlign'
feat_out: 512
AnchorRPN:
anchor_generator:
name: AnchorGeneratorRPN
anchor_sizes: [32, 64, 128, 256, 512]
aspect_ratios: [0.5, 1.0, 2.0]
stride: [16.0, 16.0]
variance: [1.0, 1.0, 1.0, 1.0]
anchor_target_generator:
name: AnchorTargetGeneratorRPN
batch_size_per_im: 256
fg_fraction: 0.5
negative_overlap: 0.3
positive_overlap: 0.7
straddle_thresh: 0.0
Proposal:
proposal_generator:
name: ProposalGenerator
min_size: 0.0
nms_thresh: 0.7
train_pre_nms_top_n: 12000
train_post_nms_top_n: 2000
infer_pre_nms_top_n: 12000 # used in infer
infer_post_nms_top_n: 2000 # used in infer
return_rois_num: True
proposal_target_generator:
name: ProposalTargetGenerator
batch_size_per_im: 512
bbox_reg_weights: [[0.1, 0.1, 0.2, 0.2],]
bg_thresh_hi: [0.5,]
bg_thresh_lo: [0.0,]
fg_thresh: [0.5,]
fg_fraction: 0.25
bbox_post_process: # used in infer
name: BBoxPostProcess
# decode -> clip -> nms
decode_clip_nms:
name: DecodeClipNms
keep_top_k: 100
score_threshold: 0.05
nms_threshold: 0.5
# Train
LearningRate:
base_lr: 0.01
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones: [120000, 160000]
- !LinearWarmup
start_factor: 0.3333333333333333
steps: 500
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0001
type: L2
_READER_: 'faster_reader.yml'
TrainReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'gt_bbox', 'gt_class', 'is_crowd']
dataset:
!COCODataSet
image_dir: train2017
anno_path: annotations/instances_train2017.json
dataset_dir: dataset/coco
sample_transforms:
- !DecodeImage
to_rgb: True
- !RandomFlipImage
prob: 0.5
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
target_size: 800
max_size: 1333
interp: 1
use_cv2: true
- !Permute
to_bgr: false
channel_first: true
batch_transforms:
- !PadBatch
pad_to_stride: 0
use_padded_im_info: False
pad_gt: true
batch_size: 1
shuffle: true
worker_num: 2
use_process: false
EvalReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'im_shape']
dataset:
!COCODataSet
image_dir: val2017
anno_path: annotations/instances_val2017.json
dataset_dir: dataset/coco
sample_transforms:
- !DecodeImage
to_rgb: true
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
interp: 1
max_size: 1333
target_size: 800
use_cv2: true
- !Permute
channel_first: true
to_bgr: false
batch_transforms:
- !PadBatch
pad_to_stride: 32
use_padded_im_info: false
pad_gt: True
batch_size: 2
shuffle: false
drop_empty: false
worker_num: 2
TestReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'im_shape']
dataset:
!ImageFolder
anno_path: annotations/instances_val2017.json
sample_transforms:
- !DecodeImage
to_rgb: true
with_mixup: false
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
interp: 1
max_size: 1333
target_size: 800
use_cv2: true
- !Permute
channel_first: true
to_bgr: false
batch_size: 1
shuffle: false
architecture: MaskRCNN
use_gpu: true
max_iters: 180000
log_smooth_window: 50
save_dir: output
snapshot_iter: 10000
pretrain_weights: https://paddlemodels.bj.bcebos.com/object_detection/dygraph/resnet50.pdparams
metric: COCO
weights: output/mask_rcnn_r50_1x/model_final
num_classes: 81
open_debug: False
# Model Achitecture
MaskRCNN:
# model anchor info flow
anchor: AnchorRPN
proposal: Proposal
mask: Mask
# model feat info flow
backbone: ResNet
rpn_head: RPNHead
bbox_head: BBoxHead
mask_head: MaskHead
ResNet:
norm_type: 'affine'
depth: 50
freeze_at: 'res2'
RPNHead:
rpn_feat:
name: RPNFeat
feat_in: 1024
feat_out: 1024
anchor_per_position: 15
BBoxHead:
bbox_feat:
name: BBoxFeat
roi_extractor:
name: RoIExtractor
resolution: 14
sampling_ratio: 0
spatial_scale: 0.0625
extractor_type: 'RoIAlign'
feat_in: 1024
feat_out: 512
MaskHead:
mask_feat:
name: MaskFeat
feat_in: 2048
feat_out: 256
mask_stages: 1
feat_in: 256
resolution: 14
mask_stages: 1
AnchorRPN:
anchor_generator:
name: AnchorGeneratorRPN
anchor_sizes: [32, 64, 128, 256, 512]
aspect_ratios: [0.5, 1.0, 2.0]
stride: [16.0, 16.0]
variance: [1.0, 1.0, 1.0, 1.0]
anchor_target_generator:
name: AnchorTargetGeneratorRPN
batch_size_per_im: 256
fg_fraction: 0.5
negative_overlap: 0.3
positive_overlap: 0.7
straddle_thresh: 0.0
Proposal:
proposal_generator:
name: ProposalGenerator
min_size: 0.0
nms_thresh: 0.7
train_pre_nms_top_n: 12000
train_post_nms_top_n: 2000
infer_pre_nms_top_n: 12000
infer_post_nms_top_n: 2000
return_rois_num: True
proposal_target_generator:
name: ProposalTargetGenerator
batch_size_per_im: 512
bbox_reg_weights: [[0.1, 0.1, 0.2, 0.2],]
bg_thresh_hi: [0.5,]
bg_thresh_lo: [0.0,]
fg_thresh: [0.5,]
fg_fraction: 0.25
bbox_post_process: # used in infer
name: BBoxPostProcess
# decode -> clip -> nms
decode_clip_nms:
name: DecodeClipNms
keep_top_k: 100
score_threshold: 0.05
nms_threshold: 0.5
Mask:
mask_target_generator:
name: MaskTargetGenerator
resolution: 14
mask_post_process:
name: MaskPostProcess
# Train
LearningRate:
base_lr: 0.01
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones: [120000, 160000]
- !LinearWarmup
start_factor: 0.3333333333333333
steps: 500
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0001
type: L2
_READER_: 'mask_reader.yml'
TrainReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'gt_bbox', 'gt_class', 'is_crowd', 'gt_mask']
dataset:
!COCODataSet
image_dir: train2017
anno_path: annotations/instances_train2017.json
dataset_dir: dataset/coco
sample_transforms:
- !DecodeImage
to_rgb: true
- !RandomFlipImage
prob: 0.5
is_mask_flip: true
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
target_size: 512
max_size: 512
interp: 1
use_cv2: true
- !Permute
to_bgr: false
channel_first: true
batch_transforms:
- !PadBatch
pad_to_stride: 32
use_padded_im_info: false
pad_gt: True
batch_size: 1
shuffle: true
worker_num: 2
drop_last: false
use_process: false
EvalReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'im_shape']
# for voc
#fields: ['image', 'im_info', 'im_id', 'gt_bbox', 'gt_class', 'is_difficult']
dataset:
!COCODataSet
image_dir: val2017
anno_path: annotations/instances_val2017.json
dataset_dir: dataset/coco
sample_transforms:
- !DecodeImage
to_rgb: true
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
interp: 1
max_size: 1333
target_size: 800
use_cv2: true
- !Permute
channel_first: true
to_bgr: false
batch_transforms:
- !PadBatch
pad_to_stride: 32
use_padded_im_info: false
pad_gt: True
batch_size: 1
shuffle: false
drop_last: false
drop_empty: false
worker_num: 2
TestReader:
inputs_def:
fields: ['image', 'im_info', 'im_id', 'im_shape']
dataset:
!ImageFolder
anno_path: annotations/instances_val2017.json
sample_transforms:
- !DecodeImage
to_rgb: true
with_mixup: false
- !NormalizeImage
is_channel_first: false
is_scale: true
mean: [0.485,0.456,0.406]
std: [0.229, 0.224,0.225]
- !ResizeImage
interp: 1
max_size: 1333
target_size: 800
use_cv2: true
- !Permute
channel_first: true
to_bgr: false
batch_size: 1
shuffle: false
drop_last: false
architecture: YOLOv3
use_gpu: true
max_iters: 500000
log_smooth_window: 20
save_dir: output
snapshot_iter: 10000
metric: COCO
pretrain_weights: https://paddlemodels.bj.bcebos.com/yolo/darknet53.pdparams
weights: output/yolov3_darknet/model_final
num_classes: 80
use_fine_grained_loss: false
open_debug: False
YOLOv3:
anchor: AnchorYOLO
backbone: DarkNet
yolo_head: YOLOv3Head
DarkNet:
depth: 53
YOLOv3Head:
yolo_feat:
name: YOLOFeat
feat_in_list: [1024, 768, 384]
anchor_per_position: 3
AnchorYOLO:
anchor_generator:
name: AnchorGeneratorYOLO
anchors: [10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, 373, 326]
anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
anchor_target_generator:
name: AnchorTargetGeneratorYOLO
ignore_thresh: 0.7
downsample_ratio: 32
label_smooth: true
anchor_post_process:
name: BBoxPostProcessYOLO
# decode -> clip
yolo_box:
name: YOLOBox
conf_thresh: 0.005
downsample_ratio: 32
clip_bbox: True
nms:
name: MultiClassNMS
keep_top_k: 100
score_threshold: 0.01
nms_threshold: 0.45
nms_top_k: 1000
normalized: false
background_label: -1
LearningRate:
base_lr: 0.001
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones:
- 400000
- 450000
- !LinearWarmup
start_factor: 0.
steps: 4000
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0005
type: L2
_READER_: 'yolov3_reader.yml'
TrainReader:
inputs_def:
fields: ['image', 'gt_bbox', 'gt_class', 'gt_score']
num_max_boxes: 50
dataset:
!COCODataSet
image_dir: train2017
anno_path: annotations/instances_train2017.json
dataset_dir: dataset/coco
with_background: false
sample_transforms:
- !DecodeImage
to_rgb: True
with_mixup: True
- !MixupImage
alpha: 1.5
beta: 1.5
- !ColorDistort {}
- !RandomExpand
fill_value: [123.675, 116.28, 103.53]
- !RandomCrop {}
- !RandomFlipImage
is_normalized: false
- !NormalizeBox {}
- !PadBox
num_max_boxes: 50
- !BboxXYXY2XYWH {}
batch_transforms:
- !RandomShape
sizes: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608]
random_inter: True
- !NormalizeImage
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
is_scale: True
is_channel_first: false
- !Permute
to_bgr: false
channel_first: True
# Gt2YoloTarget is only used when use_fine_grained_loss set as true,
# this operator will be deleted automatically if use_fine_grained_loss
# is set as false
- !Gt2YoloTarget
anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
anchors: [[10, 13], [16, 30], [33, 23],
[30, 61], [62, 45], [59, 119],
[116, 90], [156, 198], [373, 326]]
downsample_ratios: [32, 16, 8]
batch_size: 8
shuffle: true
mixup_epoch: 250
drop_last: true
worker_num: 8
bufsize: 16
use_process: true
EvalReader:
inputs_def:
fields: ['image', 'im_size', 'im_id']
num_max_boxes: 50
dataset:
!COCODataSet
image_dir: val2017
anno_path: annotations/instances_val2017.json
dataset_dir: dataset/coco
with_background: false
sample_transforms:
- !DecodeImage
to_rgb: True
- !ResizeImage
target_size: 608
interp: 2
- !NormalizeImage
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
is_scale: True
is_channel_first: false
- !PadBox
num_max_boxes: 50
- !Permute
to_bgr: false
channel_first: True
batch_size: 8
drop_empty: false
worker_num: 8
bufsize: 16
TestReader:
inputs_def:
image_shape: [3, 608, 608]
fields: ['image', 'im_size', 'im_id']
dataset:
!ImageFolder
anno_path: annotations/instances_val2017.json
with_background: false
sample_transforms:
- !DecodeImage
to_rgb: True
- !ResizeImage
target_size: 608
interp: 2
- !NormalizeImage
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
is_scale: True
is_channel_first: false
- !Permute
to_bgr: false
channel_first: True
batch_size: 1
...@@ -199,13 +199,13 @@ def create(cls_or_name, **kwargs): ...@@ -199,13 +199,13 @@ def create(cls_or_name, **kwargs):
config.update(kwargs) config.update(kwargs)
config.validate() config.validate()
cls = getattr(config.pymodule, name) cls = getattr(config.pymodule, name)
kwargs = {} kwargs = {}
kwargs.update(global_config[name]) kwargs.update(global_config[name])
# parse `shared` annoation of registered modules # parse `shared` annoation of registered modules
if getattr(config, 'shared', None): if getattr(config, 'shared', None):
for k in config.shared: for k in config.shared:
target_key = config[k] target_key = config[k]
shared_conf = config.schema[k].default shared_conf = config.schema[k].default
assert isinstance(shared_conf, SharedConfig) assert isinstance(shared_conf, SharedConfig)
...@@ -225,9 +225,22 @@ def create(cls_or_name, **kwargs): ...@@ -225,9 +225,22 @@ def create(cls_or_name, **kwargs):
# optional dependency # optional dependency
if target_key is None: if target_key is None:
continue continue
# also accept dictionaries and serialized objects
if isinstance(target_key, dict) or hasattr(target_key, '__dict__'): if isinstance(target_key, dict) or hasattr(target_key, '__dict__'):
continue if 'name' not in target_key.keys():
continue
inject_name = str(target_key['name'])
if inject_name not in global_config:
raise ValueError(
"Missing injection name {} and check it's name in cfg file".
format(k))
target = global_config[inject_name]
for i, v in target_key.items():
if i == 'name':
continue
target[i] = v
if isinstance(target, SchemaDict):
kwargs[k] = create(inject_name)
elif isinstance(target_key, str): elif isinstance(target_key, str):
if target_key not in global_config: if target_key not in global_config:
raise ValueError("Missing injection config:", target_key) raise ValueError("Missing injection config:", target_key)
...@@ -235,10 +248,10 @@ def create(cls_or_name, **kwargs): ...@@ -235,10 +248,10 @@ def create(cls_or_name, **kwargs):
if isinstance(target, SchemaDict): if isinstance(target, SchemaDict):
kwargs[k] = create(target_key) kwargs[k] = create(target_key)
elif hasattr(target, '__dict__'): # serialized object elif hasattr(target, '__dict__'): # serialized object
kwargs[k] = target kwargs[k] = new_dict
else: else:
raise ValueError("Unsupported injection type:", target_key) raise ValueError("Unsupported injection type:", target_key)
# prevent modification of global config values of reference types # prevent modification of global config values of reference types
# (e.g., list, dict) from within the created module instances # (e.g., list, dict) from within the created module instances
kwargs = copy.deepcopy(kwargs) #kwargs = copy.deepcopy(kwargs)
return cls(**kwargs) return cls(**kwargs)
...@@ -47,10 +47,11 @@ class PadBatch(BaseOperator): ...@@ -47,10 +47,11 @@ class PadBatch(BaseOperator):
height and width is divisible by `pad_to_stride`. height and width is divisible by `pad_to_stride`.
""" """
def __init__(self, pad_to_stride=0, use_padded_im_info=True): def __init__(self, pad_to_stride=0, use_padded_im_info=True, pad_gt=False):
super(PadBatch, self).__init__() super(PadBatch, self).__init__()
self.pad_to_stride = pad_to_stride self.pad_to_stride = pad_to_stride
self.use_padded_im_info = use_padded_im_info self.use_padded_im_info = use_padded_im_info
self.pad_gt = pad_gt
def __call__(self, samples, context=None): def __call__(self, samples, context=None):
""" """
...@@ -60,9 +61,9 @@ class PadBatch(BaseOperator): ...@@ -60,9 +61,9 @@ class PadBatch(BaseOperator):
coarsest_stride = self.pad_to_stride coarsest_stride = self.pad_to_stride
if coarsest_stride == 0: if coarsest_stride == 0:
return samples return samples
max_shape = np.array([data['image'].shape for data in samples]).max( max_shape = np.array([data['image'].shape for data in samples]).max(
axis=0) axis=0)
if coarsest_stride > 0: if coarsest_stride > 0:
max_shape[1] = int( max_shape[1] = int(
np.ceil(max_shape[1] / coarsest_stride) * coarsest_stride) np.ceil(max_shape[1] / coarsest_stride) * coarsest_stride)
...@@ -79,6 +80,52 @@ class PadBatch(BaseOperator): ...@@ -79,6 +80,52 @@ class PadBatch(BaseOperator):
data['image'] = padding_im data['image'] = padding_im
if self.use_padded_im_info: if self.use_padded_im_info:
data['im_info'][:2] = max_shape[1:3] data['im_info'][:2] = max_shape[1:3]
if self.pad_gt:
gt_num = []
if data['gt_poly'] is not None and len(data['gt_poly']) > 0:
pad_mask = True
else:
pad_mask = False
if pad_mask:
poly_num = []
poly_part_num = []
point_num = []
for data in samples:
gt_num.append(data['gt_bbox'].shape[0])
if pad_mask:
poly_num.append(len(data['gt_poly']))
for poly in data['gt_poly']:
poly_part_num.append(int(len(poly)))
for p_p in poly:
point_num.append(int(len(p_p) / 2))
gt_num_max = max(gt_num)
gt_box_data = np.zeros([gt_num_max, 4])
gt_class_data = np.zeros([gt_num_max])
is_crowd_data = np.ones([gt_num_max])
if pad_mask:
poly_num_max = max(poly_num)
poly_part_num_max = max(poly_part_num)
point_num_max = max(point_num)
gt_masks_data = -np.ones(
[poly_num_max, poly_part_num_max, point_num_max, 2])
for i, data in enumerate(samples):
gt_num = data['gt_bbox'].shape[0]
gt_box_data[0:gt_num, :] = data['gt_bbox']
gt_class_data[0:gt_num] = np.squeeze(data['gt_class'])
is_crowd_data[0:gt_num] = np.squeeze(data['is_crowd'])
if pad_mask:
for j, poly in enumerate(data['gt_poly']):
for k, p_p in enumerate(poly):
pp_np = np.array(p_p).reshape(-1, 2)
gt_masks_data[j, k, :pp_np.shape[0], :] = pp_np
data['gt_poly'] = gt_masks_data
data['gt_bbox'] = gt_box_data
data['gt_class'] = gt_class_data
data['is_crowd_data'] = is_crowd_data
return samples return samples
......
...@@ -43,8 +43,7 @@ class PiecewiseDecay(object): ...@@ -43,8 +43,7 @@ class PiecewiseDecay(object):
milestones (list): steps at which to decay learning rate milestones (list): steps at which to decay learning rate
""" """
def __init__(self, gamma=[0.1, 0.1], milestones=[60000, 80000], def __init__(self, gamma=[0.1, 0.01], milestones=[60000, 80000]):
values=None):
super(PiecewiseDecay, self).__init__() super(PiecewiseDecay, self).__init__()
if type(gamma) is not list: if type(gamma) is not list:
self.gamma = [] self.gamma = []
...@@ -53,126 +52,16 @@ class PiecewiseDecay(object): ...@@ -53,126 +52,16 @@ class PiecewiseDecay(object):
else: else:
self.gamma = gamma self.gamma = gamma
self.milestones = milestones self.milestones = milestones
self.values = values
def __call__(self, base_lr=None, learning_rate=None): def __call__(self, base_lr=None, boundary=None, value=None):
if self.values is not None: if boundary is not None:
return fluid.layers.piecewise_decay(self.milestones, self.values) boundary.extend(self.milestones)
assert base_lr is not None, "either base LR or values should be provided"
values = [base_lr]
for g in self.gamma:
new_lr = base_lr * g
values.append(new_lr)
return fluid.layers.piecewise_decay(self.milestones, values)
if value is not None:
for i in self.gamma:
value.append(base_lr * i)
@serializable return fluid.dygraph.PiecewiseDecay(boundary, value, begin=0, step=1)
class PolynomialDecay(object):
"""
Applies polynomial decay to the initial learning rate.
Args:
max_iter (int): The learning rate decay steps.
end_lr (float): End learning rate.
power (float): Polynomial attenuation coefficient
"""
def __init__(self, max_iter=180000, end_lr=0.0001, power=1.0):
super(PolynomialDecay).__init__()
self.max_iter = max_iter
self.end_lr = end_lr
self.power = power
def __call__(self, base_lr=None, learning_rate=None):
assert base_lr is not None, "either base LR or values should be provided"
lr = fluid.layers.polynomial_decay(base_lr, self.max_iter, self.end_lr,
self.power)
return lr
@serializable
class ExponentialDecay(object):
"""
Applies exponential decay to the learning rate.
Args:
max_iter (int): The learning rate decay steps.
decay_rate (float): The learning rate decay rate.
"""
def __init__(self, max_iter, decay_rate):
super(ExponentialDecay).__init__()
self.max_iter = max_iter
self.decay_rate = decay_rate
def __call__(self, base_lr=None, learning_rate=None):
assert base_lr is not None, "either base LR or values should be provided"
lr = fluid.layers.exponential_decay(base_lr, self.max_iter,
self.decay_rate)
return lr
@serializable
class CosineDecay(object):
"""
Cosine learning rate decay
Args:
max_iters (float): max iterations for the training process.
if you commbine cosine decay with warmup, it is recommended that
the max_iter is much larger than the warmup iter
"""
def __init__(self, max_iters=180000):
self.max_iters = max_iters
def __call__(self, base_lr=None, learning_rate=None):
assert base_lr is not None, "either base LR or values should be provided"
lr = fluid.layers.cosine_decay(base_lr, 1, self.max_iters)
return lr
@serializable
class CosineDecayWithSkip(object):
"""
Cosine decay, with explicit support for warm up
Args:
total_steps (int): total steps over which to apply the decay
skip_steps (int): skip some steps at the beginning, e.g., warm up
"""
def __init__(self, total_steps, skip_steps=None):
super(CosineDecayWithSkip, self).__init__()
assert (not skip_steps or skip_steps > 0), \
"skip steps must be greater than zero"
assert total_steps > 0, "total step must be greater than zero"
assert (not skip_steps or skip_steps < total_steps), \
"skip steps must be smaller than total steps"
self.total_steps = total_steps
self.skip_steps = skip_steps
def __call__(self, base_lr=None, learning_rate=None):
steps = _decay_step_counter()
total = self.total_steps
if self.skip_steps is not None:
total -= self.skip_steps
lr = fluid.layers.tensor.create_global_var(
shape=[1],
value=base_lr,
dtype='float32',
persistable=True,
name="learning_rate")
def decay():
cos_lr = base_lr * .5 * (cos(steps * (math.pi / total)) + 1)
fluid.layers.tensor.assign(input=cos_lr, output=lr)
if self.skip_steps is None:
decay()
else:
skipped = steps >= self.skip_steps
fluid.layers.cond(skipped, decay)
return lr
@serializable @serializable
...@@ -190,14 +79,17 @@ class LinearWarmup(object): ...@@ -190,14 +79,17 @@ class LinearWarmup(object):
self.steps = steps self.steps = steps
self.start_factor = start_factor self.start_factor = start_factor
def __call__(self, base_lr, learning_rate): def __call__(self, base_lr):
start_lr = base_lr * self.start_factor boundary = []
value = []
return fluid.layers.linear_lr_warmup( for i in range(self.steps):
learning_rate=learning_rate, alpha = i / self.steps
warmup_steps=self.steps, factor = self.start_factor * (1 - alpha) + alpha
start_lr=start_lr, lr = base_lr * factor
end_lr=base_lr) value.append(lr)
if i > 0:
boundary.append(i)
return boundary, value
@register @register
...@@ -219,10 +111,12 @@ class LearningRate(object): ...@@ -219,10 +111,12 @@ class LearningRate(object):
self.schedulers = schedulers self.schedulers = schedulers
def __call__(self): def __call__(self):
lr = None # TODO: split warmup & decay
for sched in self.schedulers: # warmup
lr = sched(self.base_lr, lr) boundary, value = self.schedulers[1](self.base_lr)
return lr # decay
decay_lr = self.schedulers[0](self.base_lr, boundary, value)
return decay_lr
@register @register
...@@ -246,21 +140,24 @@ class OptimizerBuilder(): ...@@ -246,21 +140,24 @@ class OptimizerBuilder():
self.regularizer = regularizer self.regularizer = regularizer
self.optimizer = optimizer self.optimizer = optimizer
def __call__(self, learning_rate): def __call__(self, learning_rate, params=None):
if self.clip_grad_by_norm is not None: if self.clip_grad_by_norm is not None:
fluid.clip.set_gradient_clip( fluid.clip.set_gradient_clip(
clip=fluid.clip.GradientClipByGlobalNorm( clip=fluid.clip.GradientClipByGlobalNorm(
clip_norm=self.clip_grad_by_norm)) clip_norm=self.clip_grad_by_norm))
if self.regularizer: if self.regularizer:
reg_type = self.regularizer['type'] + 'Decay' reg_type = self.regularizer['type'] + 'Decay'
reg_factor = self.regularizer['factor'] reg_factor = self.regularizer['factor']
regularization = getattr(regularizer, reg_type)(reg_factor) regularization = getattr(regularizer, reg_type)(reg_factor)
else: else:
regularization = None regularization = None
optim_args = self.optimizer.copy() optim_args = self.optimizer.copy()
optim_type = optim_args['type'] optim_type = optim_args['type']
del optim_args['type'] del optim_args['type']
op = getattr(optimizer, optim_type) op = getattr(optimizer, optim_type)
return op(learning_rate=learning_rate, return op(learning_rate=learning_rate,
parameter_list=params,
regularization=regularization, regularization=regularization,
**optim_args) **optim_args)
# 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 absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
import errno
import os import os
import shutil
import tempfile
import time import time
import numpy as np
import re import re
import numpy as np
import paddle.fluid as fluid import paddle.fluid as fluid
from .download import get_weights_path from .download import get_weights_path
import logging
logger = logging.getLogger(__name__)
__all__ = [
'load_checkpoint',
'load_and_fusebn',
'load_params',
'save',
]
def is_url(path):
"""
Whether path is URL.
Args:
path (string): URL string or not.
"""
return path.startswith('http://') or path.startswith('https://')
def get_ckpt_path(path):
def _get_weight_path(path): if path.startswith('http://') or path.startswith('https://'):
env = os.environ env = os.environ
if 'PADDLE_TRAINERS_NUM' in env and 'PADDLE_TRAINER_ID' in env: if 'PADDLE_TRAINERS_NUM' in env and 'PADDLE_TRAINER_ID' in env:
trainer_id = int(env['PADDLE_TRAINER_ID']) trainer_id = int(env['PADDLE_TRAINER_ID'])
num_trainers = int(env['PADDLE_TRAINERS_NUM']) num_trainers = int(env['PADDLE_TRAINERS_NUM'])
if num_trainers <= 1: if num_trainers <= 1:
path = get_weights_path(path) path = get_weights_path(path)
else:
from ppdet.utils.download import map_path, WEIGHTS_HOME
weight_path = map_path(path, WEIGHTS_HOME)
lock_path = weight_path + '.lock'
if not os.path.exists(weight_path):
try:
os.makedirs(os.path.dirname(weight_path))
except OSError as e:
if e.errno != errno.EEXIST:
raise
with open(lock_path, 'w'): # touch
os.utime(lock_path, None)
if trainer_id == 0:
get_weights_path(path)
os.remove(lock_path)
else:
while os.path.exists(lock_path):
time.sleep(1)
path = weight_path
else: else:
from ppdet.utils.download import map_path, WEIGHTS_HOME path = get_weights_path(path)
weight_path = map_path(path, WEIGHTS_HOME)
lock_path = weight_path + '.lock'
if not os.path.exists(weight_path):
try:
os.makedirs(os.path.dirname(weight_path))
except OSError as e:
if e.errno != errno.EEXIST:
raise
with open(lock_path, 'w'): # touch
os.utime(lock_path, None)
if trainer_id == 0:
get_weights_path(path)
os.remove(lock_path)
else:
while os.path.exists(lock_path):
time.sleep(1)
path = weight_path
else:
path = get_weights_path(path)
return path
def _load_state(path):
if os.path.exists(path + '.pdopt'):
# XXX another hack to ignore the optimizer state
tmp = tempfile.mkdtemp()
dst = os.path.join(tmp, os.path.basename(os.path.normpath(path)))
shutil.copy(path + '.pdparams', dst + '.pdparams')
state = fluid.io.load_program_state(dst)
shutil.rmtree(tmp)
else:
state = fluid.io.load_program_state(path)
return state
def _strip_postfix(path):
path, ext = os.path.splitext(path)
assert ext in ['', '.pdparams', '.pdopt', '.pdmodel'], \
"Unknown postfix {} from weights".format(ext)
return path return path
def load_params(exe, prog, path, ignore_params=[]): def load_dygraph_ckpt(model,
""" optimizer,
Load model from the given path. pretrain_ckpt=None,
Args: ckpt=None,
exe (fluid.Executor): The fluid.Executor object. ckpt_type='pretrain',
prog (fluid.Program): load weight to which Program object. exclude_params=[],
path (string): URL string or loca model path. open_debug=False):
ignore_params (list): ignore variable to load when finetuning.
It can be specified by finetune_exclude_pretrained_params if ckpt_type == 'pretrain':
and the usage can refer to docs/advanced_tutorials/TRANSFER_LEARNING.md ckpt = pretrain_ckpt
""" ckpt = get_ckpt_path(ckpt)
if ckpt is not None and os.path.exists(ckpt):
if is_url(path): param_state_dict, optim_state_dict = fluid.load_dygraph(ckpt)
path = _get_weight_path(path) if open_debug:
print("Loading Weights: ", param_state_dict.keys())
path = _strip_postfix(path)
if not (os.path.isdir(path) or os.path.exists(path + '.pdparams')): if len(exclude_params) != 0:
raise ValueError("Model pretrain path {} does not " for k in exclude_params:
"exists.".format(path)) param_state_dict.pop(k, None)
logger.debug('Loading parameters from {}...'.format(path)) if ckpt_type == 'pretrain':
model.backbone.set_dict(param_state_dict)
ignore_set = set() elif ckpt_type == 'finetune':
state = _load_state(path) model.set_dict(param_state_dict, use_structured_name=True)
else:
# ignore the parameter which mismatch the shape model.set_dict(param_state_dict)
# between the model and pretrain weight.
all_var_shape = {} if ckpt_type == 'resume':
for block in prog.blocks: if optim_state_dict is None:
for param in block.all_parameters(): print("Can't Resume Last Training's Optimizer State!!!")
all_var_shape[param.name] = param.shape else:
ignore_set.update([ optimizer.set_dict(optim_state_dict)
name for name, shape in all_var_shape.items() return model
if name in state and shape != state[name].shape
])
def save_dygraph_ckpt(model, optimizer, save_dir):
if ignore_params: if not os.path.exists(save_dir):
all_var_names = [var.name for var in prog.list_vars()] os.makedirs(save_dir)
ignore_list = filter( fluid.dygraph.save_dygraph(model.state_dict(), save_dir)
lambda var: any([re.match(name, var) for name in ignore_params]), fluid.dygraph.save_dygraph(optimizer.state_dict(), save_dir)
all_var_names) print("Save checkpoint:", save_dir)
ignore_set.update(list(ignore_list))
if len(ignore_set) > 0:
for k in ignore_set:
if k in state:
logger.warning('variable {} not used'.format(k))
del state[k]
fluid.io.set_program_state(prog, state)
def load_checkpoint(exe, prog, path):
"""
Load model from the given path.
Args:
exe (fluid.Executor): The fluid.Executor object.
prog (fluid.Program): load weight to which Program object.
path (string): URL string or loca model path.
"""
if is_url(path):
path = _get_weight_path(path)
path = _strip_postfix(path)
if not (os.path.isdir(path) or os.path.exists(path + '.pdparams')):
raise ValueError("Model pretrain path {} does not "
"exists.".format(path))
fluid.load(prog, path, executor=exe)
def global_step(scope=None):
"""
Load global step in scope.
Args:
scope (fluid.Scope): load global step from which scope. If None,
from default global_scope().
Returns:
global step: int.
"""
if scope is None:
scope = fluid.global_scope()
v = scope.find_var('@LR_DECAY_COUNTER@')
step = np.array(v.get_tensor())[0] if v else 0
return step
def save(exe, prog, path):
"""
Load model from the given path.
Args:
exe (fluid.Executor): The fluid.Executor object.
prog (fluid.Program): save weight from which Program object.
path (string): the path to save model.
"""
if os.path.isdir(path):
shutil.rmtree(path)
logger.info('Save model to {}.'.format(path))
fluid.save(prog, path)
def load_and_fusebn(exe, prog, path):
"""
Fuse params of batch norm to scale and bias.
Args:
exe (fluid.Executor): The fluid.Executor object.
prog (fluid.Program): save weight from which Program object.
path (string): the path to save model.
"""
logger.debug('Load model and fuse batch norm if have from {}...'.format(
path))
if is_url(path):
path = _get_weight_path(path)
if not os.path.exists(path):
raise ValueError("Model path {} does not exists.".format(path))
# Since the program uses affine-channel, there is no running mean and var
# in the program, here append running mean and var.
# NOTE, the params of batch norm should be like:
# x_scale
# x_offset
# x_mean
# x_variance
# x is any prefix
mean_variances = set()
bn_vars = []
state = _load_state(path)
def check_mean_and_bias(prefix):
m = prefix + 'mean'
v = prefix + 'variance'
return v in state and m in state
has_mean_bias = True
with fluid.program_guard(prog, fluid.Program()):
for block in prog.blocks:
ops = list(block.ops)
if not has_mean_bias:
break
for op in ops:
if op.type == 'affine_channel':
# remove 'scale' as prefix
scale_name = op.input('Scale')[0] # _scale
bias_name = op.input('Bias')[0] # _offset
prefix = scale_name[:-5]
mean_name = prefix + 'mean'
variance_name = prefix + 'variance'
if not check_mean_and_bias(prefix):
has_mean_bias = False
break
bias = block.var(bias_name)
mean_vb = block.create_var(
name=mean_name,
type=bias.type,
shape=bias.shape,
dtype=bias.dtype)
variance_vb = block.create_var(
name=variance_name,
type=bias.type,
shape=bias.shape,
dtype=bias.dtype)
mean_variances.add(mean_vb)
mean_variances.add(variance_vb)
bn_vars.append(
[scale_name, bias_name, mean_name, variance_name])
if not has_mean_bias:
fluid.io.set_program_state(prog, state)
logger.warning(
"There is no paramters of batch norm in model {}. "
"Skip to fuse batch norm. And load paramters done.".format(path))
return
fluid.load(prog, path, exe)
eps = 1e-5
for names in bn_vars:
scale_name, bias_name, mean_name, var_name = names
scale = fluid.global_scope().find_var(scale_name).get_tensor()
bias = fluid.global_scope().find_var(bias_name).get_tensor()
mean = fluid.global_scope().find_var(mean_name).get_tensor()
var = fluid.global_scope().find_var(var_name).get_tensor()
scale_arr = np.array(scale)
bias_arr = np.array(bias)
mean_arr = np.array(mean)
var_arr = np.array(var)
bn_std = np.sqrt(np.add(var_arr, eps))
new_scale = np.float32(np.divide(scale_arr, bn_std))
new_bias = bias_arr - mean_arr * new_scale
# fuse to scale and bias in affine_channel
scale.set(new_scale, exe.place)
bias.set(new_bias, exe.place)
...@@ -35,7 +35,7 @@ class BufferDict(dict): ...@@ -35,7 +35,7 @@ class BufferDict(dict):
def debug(self, dshape=True, dvalue=True, dtype=False): def debug(self, dshape=True, dvalue=True, dtype=False):
if self['open_debug']: if self['open_debug']:
if self['debug_names'] is None: if 'debug_names' not in self.keys():
ditems = self.keys() ditems = self.keys()
else: else:
ditems = self['debug_names'] ditems = self['debug_names']
......
# 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 absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import logging
import numpy as np
import os
import time
import paddle.fluid as fluid
from .voc_eval import bbox_eval as voc_bbox_eval
from .post_process import mstest_box_post_process, mstest_mask_post_process, box_flip
__all__ = ['parse_fetches', 'eval_run', 'eval_results', 'json_eval_results']
logger = logging.getLogger(__name__)
def parse_fetches(fetches, prog=None, extra_keys=None):
"""
Parse fetch variable infos from model fetches,
values for fetch_list and keys for stat
"""
keys, values = [], []
cls = []
for k, v in fetches.items():
if hasattr(v, 'name'):
keys.append(k)
#v.persistable = True
values.append(v.name)
else:
cls.append(v)
if prog is not None and extra_keys is not None:
for k in extra_keys:
try:
v = fluid.framework._get_var(k, prog)
keys.append(k)
values.append(v.name)
except Exception:
pass
return keys, values, cls
def length2lod(length_lod):
offset_lod = [0]
for i in length_lod:
offset_lod.append(offset_lod[-1] + i)
return [offset_lod]
def get_sub_feed(input, place):
new_dict = {}
res_feed = {}
key_name = ['bbox', 'im_info', 'im_id', 'im_shape', 'bbox_flip']
for k in key_name:
if k in input.keys():
new_dict[k] = input[k]
for k in input.keys():
if 'image' in k:
new_dict[k] = input[k]
for k, v in new_dict.items():
data_t = fluid.LoDTensor()
data_t.set(v[0], place)
if 'bbox' in k:
lod = length2lod(v[1][0])
data_t.set_lod(lod)
res_feed[k] = data_t
return res_feed
def clean_res(result, keep_name_list):
clean_result = {}
for k in result.keys():
if k in keep_name_list:
clean_result[k] = result[k]
result.clear()
return clean_result
def eval_run(exe,
compile_program,
loader,
keys,
values,
cls,
cfg=None,
sub_prog=None,
sub_keys=None,
sub_values=None,
resolution=None):
"""
Run evaluation program, return program outputs.
"""
iter_id = 0
results = []
if len(cls) != 0:
values = []
for i in range(len(cls)):
_, accum_map = cls[i].get_map_var()
cls[i].reset(exe)
values.append(accum_map)
images_num = 0
start_time = time.time()
has_bbox = 'bbox' in keys
try:
loader.start()
while True:
outs = exe.run(compile_program,
fetch_list=values,
return_numpy=False)
res = {
k: (np.array(v), v.recursive_sequence_lengths())
for k, v in zip(keys, outs)
}
multi_scale_test = getattr(cfg, 'MultiScaleTEST', None)
mask_multi_scale_test = multi_scale_test and 'Mask' in cfg.architecture
if multi_scale_test:
post_res = mstest_box_post_process(res, multi_scale_test,
cfg.num_classes)
res.update(post_res)
if mask_multi_scale_test:
place = fluid.CUDAPlace(0) if cfg.use_gpu else fluid.CPUPlace()
sub_feed = get_sub_feed(res, place)
sub_prog_outs = exe.run(sub_prog,
feed=sub_feed,
fetch_list=sub_values,
return_numpy=False)
sub_prog_res = {
k: (np.array(v), v.recursive_sequence_lengths())
for k, v in zip(sub_keys, sub_prog_outs)
}
post_res = mstest_mask_post_process(sub_prog_res, cfg)
res.update(post_res)
if multi_scale_test:
res = clean_res(
res, ['im_info', 'bbox', 'im_id', 'im_shape', 'mask'])
if 'mask' in res:
from ppdet.utils.post_process import mask_encode
res['mask'] = mask_encode(res, resolution)
post_config = getattr(cfg, 'PostProcess', None)
if 'Corner' in cfg.architecture and post_config is not None:
from ppdet.utils.post_process import corner_post_process
corner_post_process(res, post_config, cfg.num_classes)
results.append(res)
if iter_id % 100 == 0:
logger.info('Test iter {}'.format(iter_id))
iter_id += 1
if len(res['bbox'][1]) == 0:
has_bbox = False
images_num += len(res['bbox'][1][0]) if has_bbox else 1
except (StopIteration, fluid.core.EOFException):
loader.reset()
logger.info('Test finish iter {}'.format(iter_id))
end_time = time.time()
fps = images_num / (end_time - start_time)
if has_bbox:
logger.info('Total number of images: {}, inference time: {} fps.'.
format(images_num, fps))
else:
logger.info('Total iteration: {}, inference time: {} batch/s.'.format(
images_num, fps))
return results
def eval_results(results,
metric,
num_classes,
resolution=None,
is_bbox_normalized=False,
output_directory=None,
map_type='11point',
dataset=None,
save_only=False):
"""Evaluation for evaluation program results"""
box_ap_stats = []
if metric == 'COCO':
from ppdet.utils.coco_eval import proposal_eval, bbox_eval, mask_eval
anno_file = dataset.get_anno()
with_background = dataset.with_background
if 'proposal' in results[0]:
output = 'proposal.json'
if output_directory:
output = os.path.join(output_directory, 'proposal.json')
proposal_eval(results, anno_file, output)
if 'bbox' in results[0]:
output = 'bbox.json'
if output_directory:
output = os.path.join(output_directory, 'bbox.json')
box_ap_stats = bbox_eval(
results,
anno_file,
output,
with_background,
is_bbox_normalized=is_bbox_normalized,
save_only=save_only)
if 'mask' in results[0]:
output = 'mask.json'
if output_directory:
output = os.path.join(output_directory, 'mask.json')
mask_eval(
results, anno_file, output, resolution, save_only=save_only)
else:
if 'accum_map' in results[-1]:
res = np.mean(results[-1]['accum_map'][0])
logger.info('mAP: {:.2f}'.format(res * 100.))
box_ap_stats.append(res * 100.)
elif 'bbox' in results[0]:
box_ap = voc_bbox_eval(
results,
num_classes,
is_bbox_normalized=is_bbox_normalized,
map_type=map_type)
box_ap_stats.append(box_ap)
return box_ap_stats
def json_eval_results(metric, json_directory=None, dataset=None): def json_eval_results(metric, json_directory=None, dataset=None):
""" """
...@@ -259,3 +24,51 @@ def json_eval_results(metric, json_directory=None, dataset=None): ...@@ -259,3 +24,51 @@ def json_eval_results(metric, json_directory=None, dataset=None):
cocoapi_eval(v_json, coco_eval_style[i], anno_file=anno_file) cocoapi_eval(v_json, coco_eval_style[i], anno_file=anno_file)
else: else:
logger.info("{} not exists!".format(v_json)) logger.info("{} not exists!".format(v_json))
def coco_eval_results(outs_res=None,
include_mask=False,
batch_size=1,
dataset=None):
print("start evaluate bbox using coco api")
import io
import six
import json
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
from ppdet.py_op.post_process import get_det_res, get_seg_res
anno_file = os.path.join(dataset.dataset_dir, dataset.anno_path)
cocoGt = COCO(anno_file)
catid = {i + 1: v for i, v in enumerate(cocoGt.getCatIds())}
if outs_res is not None and len(outs_res) > 0:
det_res = []
for outs in outs_res:
det_res += get_det_res(outs['bbox_nums'], outs['bbox'],
outs['im_id'], outs['im_shape'], catid,
batch_size)
with io.open("bbox_eval.json", 'w') as outfile:
encode_func = unicode if six.PY2 else str
outfile.write(encode_func(json.dumps(det_res)))
cocoDt = cocoGt.loadRes("bbox_eval.json")
cocoEval = COCOeval(cocoGt, cocoDt, 'bbox')
cocoEval.evaluate()
cocoEval.accumulate()
cocoEval.summarize()
if outs_res is not None and len(outs_res) > 0 and include_mask:
seg_res = []
for outs in outs_res:
seg_res += get_seg_res(outs['bbox_nums'], outs['mask'],
outs['im_id'], catid, batch_size)
with io.open("mask_eval.json", 'w') as outfile:
encode_func = unicode if six.PY2 else str
outfile.write(encode_func(json.dumps(seg_res)))
cocoSg = cocoGt.loadRes("mask_eval.json")
cocoEval = COCOeval(cocoGt, cocoSg, 'bbox')
cocoEval.evaluate()
cocoEval.accumulate()
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import time
# ignore numba warning
import warnings
warnings.filterwarnings('ignore')
import random
import numpy as np
import paddle.fluid as fluid
from ppdet.core.workspace import load_config, merge_config, create
from ppdet.utils.check import check_gpu, check_version, check_config
from ppdet.utils.cli import ArgsParser
from ppdet.utils.eval_utils import coco_eval_results
from ppdet.data.reader import create_reader
def parse_args():
parser = ArgsParser()
parser.add_argument(
"--output_eval",
default=None,
type=str,
help="Evaluation directory, default is current directory.")
parser.add_argument(
'--json_eval', action='store_true', default=False, help='')
parser.add_argument(
'--use_gpu', action='store_true', default=False, help='')
args = parser.parse_args()
return args
def run(FLAGS, cfg):
# Model
main_arch = cfg.architecture
model = create(cfg.architecture, mode='infer', open_debug=cfg.open_debug)
# Init Model
if os.path.isfile(cfg.weights):
param_state_dict, opti_state_dict = fluid.load_dygraph(cfg.weights)
model.set_dict(param_state_dict)
# Data Reader
if FLAGS.use_gpu:
devices_num = 1
else:
devices_num = int(os.environ.get('CPU_NUM', 1))
eval_reader = create_reader(cfg.EvalReader, devices_num=devices_num)
# Run Eval
outs_res = []
for iter_id, data in enumerate(eval_reader()):
start_time = time.time()
# forward
model.eval()
outs = model(data, cfg['EvalReader']['inputs_def']['fields'])
outs_res.append(outs)
# log
cost_time = time.time() - start_time
print("Eval iter: {}, time: {}".format(iter_id, cost_time))
# Metric
coco_eval_results(
outs_res,
include_mask=True if 'MaskHed' in cfg else False,
dataset=cfg['EvalReader']['dataset'])
def main():
FLAGS = parse_args()
cfg = load_config(FLAGS.config)
merge_config(FLAGS.opt)
check_config(cfg)
check_gpu(cfg.use_gpu)
check_version()
place = fluid.CUDAPlace(fluid.dygraph.parallel.Env()
.dev_id) if cfg.use_gpu else fluid.CPUPlace()
with fluid.dygraph.guard(place):
run(FLAGS, cfg)
if __name__ == '__main__':
main()
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import time
# ignore numba warning
import warnings
warnings.filterwarnings('ignore')
import random
import numpy as np
import paddle.fluid as fluid
from ppdet.core.workspace import load_config, merge_config, create
from ppdet.data.reader import create_reader
from ppdet.utils.check import check_gpu, check_version, check_config
from ppdet.utils.cli import ArgsParser
from ppdet.utils.checkpoint import load_dygraph_ckpt, save_dygraph_ckpt
def parse_args():
parser = ArgsParser()
parser.add_argument(
"-ckpt_type",
default='pretrain',
type=str,
help="Loading Checkpoints only support 'pretrain', 'finetune', 'resume'."
)
parser.add_argument(
"--fp16",
action='store_true',
default=False,
help="Enable mixed precision training.")
parser.add_argument(
"--loss_scale",
default=8.,
type=float,
help="Mixed precision training loss scale.")
parser.add_argument(
"--eval",
action='store_true',
default=False,
help="Whether to perform evaluation in train")
parser.add_argument(
"--output_eval",
default=None,
type=str,
help="Evaluation directory, default is current directory.")
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/scalar",
help='Tensorboard logging directory for scalar.')
parser.add_argument(
"--enable_ce",
type=bool,
default=False,
help="If set True, enable continuous evaluation job."
"This flag is only used for internal test.")
parser.add_argument(
"--use_gpu", action='store_true', default=False, help="data parallel")
parser.add_argument(
"--use_parallel",
action='store_true',
default=False,
help="data parallel")
parser.add_argument(
'--is_profiler',
type=int,
default=0,
help='The switch of profiler tools. (used for benchmark)')
args = parser.parse_args()
return args
def run(FLAGS, cfg):
env = os.environ
FLAGS.dist = 'PADDLE_TRAINER_ID' in env and 'PADDLE_TRAINERS_NUM' in env
if FLAGS.dist:
trainer_id = int(env['PADDLE_TRAINER_ID'])
local_seed = (99 + trainer_id)
random.seed(local_seed)
np.random.seed(local_seed)
if FLAGS.enable_ce or cfg.open_debug:
fluid.default_startup_program().random_seed = 1000
fluid.default_main_program().random_seed = 1000
random.seed(0)
np.random.seed(0)
if FLAGS.use_parallel:
strategy = fluid.dygraph.parallel.prepare_context()
parallel_log = "Note: use parallel "
# Model
main_arch = cfg.architecture
model = create(cfg.architecture, mode='train', open_debug=cfg.open_debug)
# Parallel Model
if FLAGS.use_parallel:
#strategy = fluid.dygraph.parallel.prepare_context()
model = fluid.dygraph.parallel.DataParallel(model, strategy)
parallel_log += "with data parallel!"
print(parallel_log)
# Optimizer
lr = create('LearningRate')()
optimizer = create('OptimizerBuilder')(lr, model.parameters())
# Init Model & Optimzer
model = load_dygraph_ckpt(
model,
optimizer,
cfg.pretrain_weights,
cfg.weights,
FLAGS.ckpt_type,
open_debug=cfg.open_debug)
# Data Reader
start_iter = 0
if cfg.use_gpu:
devices_num = fluid.core.get_cuda_device_count(
) if FLAGS.use_parallel else 1
else:
devices_num = int(os.environ.get('CPU_NUM', 1))
train_reader = create_reader(
cfg.TrainReader, (cfg.max_iters - start_iter) * devices_num,
cfg,
devices_num=devices_num)
# Run Train
for iter_id, data in enumerate(train_reader()):
start_time = time.time()
# Model Forward
model.train()
outputs = model(data, cfg['TrainReader']['inputs_def']['fields'])
# Model Backward
loss = outputs['loss']
if FLAGS.use_parallel:
loss = model.scale_loss(loss)
loss.backward()
model.apply_collective_grads()
else:
loss.backward()
optimizer.minimize(loss)
model.clear_gradients()
# Log state
cost_time = time.time() - start_time
# TODO: check this method
curr_lr = optimizer.current_step_lr()
log_info = "iter: {}, time: {:.4f}, lr: {:.6f}".format(
iter_id, cost_time, curr_lr)
for k, v in outputs.items():
log_info += ", {}: {:.6f}".format(k, v.numpy()[0])
print(log_info)
# Debug
if cfg.open_debug and iter_id > 10:
break
# Save Stage
if iter_id > 0 and iter_id % int(cfg.snapshot_iter) == 0:
cfg_name = os.path.basename(FLAGS.config).split('.')[0]
save_name = str(
iter_id) if iter_id != cfg.max_iters - 1 else "model_final"
save_dir = os.path.join(cfg.save_dir, cfg_name, save_name)
save_dygraph_ckpt(model, optimizer, save_dir)
def main():
FLAGS = parse_args()
cfg = load_config(FLAGS.config)
merge_config(FLAGS.opt)
check_config(cfg)
check_gpu(cfg.use_gpu)
check_version()
place = fluid.CUDAPlace(fluid.dygraph.parallel.Env().dev_id) \
if FLAGS.use_parallel else fluid.CUDAPlace(0) \
if cfg.use_gpu else fluid.CPUPlace()
with fluid.dygraph.guard(place):
run(FLAGS, cfg)
if __name__ == "__main__":
main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册