Commit 879a6ae4 authored by Kai Chen's avatar Kai Chen
Browse files

bug fix and cleaning

parent 1e35964c
...@@ -104,4 +104,5 @@ venv.bak/ ...@@ -104,4 +104,5 @@ venv.bak/
.mypy_cache/ .mypy_cache/
# cython generated cpp # cython generated cpp
mmdet/ops/nms/*.cpp mmdet/ops/nms/*.cpp
\ No newline at end of file data
from .train_engine import *
from .test_engine import *
from .rpn_ops import * from .rpn_ops import *
from .bbox_ops import * from .bbox_ops import *
from .mask_ops import * from .mask_ops import *
......
...@@ -244,6 +244,7 @@ def bbox_sampling(assigned_gt_inds, ...@@ -244,6 +244,7 @@ def bbox_sampling(assigned_gt_inds,
num_expected_pos = int(num_expected * pos_fraction) num_expected_pos = int(num_expected * pos_fraction)
pos_inds = sample_positives(assigned_gt_inds, num_expected_pos, pos_inds = sample_positives(assigned_gt_inds, num_expected_pos,
pos_balance_sampling) pos_balance_sampling)
pos_inds = pos_inds.unique()
num_sampled_pos = pos_inds.numel() num_sampled_pos = pos_inds.numel()
num_neg_max = int( num_neg_max = int(
neg_pos_ub * neg_pos_ub *
...@@ -252,10 +253,10 @@ def bbox_sampling(assigned_gt_inds, ...@@ -252,10 +253,10 @@ def bbox_sampling(assigned_gt_inds,
neg_inds = sample_negatives(assigned_gt_inds, num_expected_neg, neg_inds = sample_negatives(assigned_gt_inds, num_expected_neg,
max_overlaps, neg_balance_thr, max_overlaps, neg_balance_thr,
neg_hard_fraction) neg_hard_fraction)
neg_inds = neg_inds.unique()
return pos_inds, neg_inds return pos_inds, neg_inds
def sample_proposals(proposals_list, gt_bboxes_list, gt_crowds_list, def sample_proposals(proposals_list, gt_bboxes_list, gt_crowds_list,
gt_labels_list, cfg): gt_labels_list, cfg):
cfg_list = [cfg for _ in range(len(proposals_list))] cfg_list = [cfg for _ in range(len(proposals_list))]
...@@ -265,11 +266,7 @@ def sample_proposals(proposals_list, gt_bboxes_list, gt_crowds_list, ...@@ -265,11 +266,7 @@ def sample_proposals(proposals_list, gt_bboxes_list, gt_crowds_list,
return tuple(map(list, zip(*results))) return tuple(map(list, zip(*results)))
def sample_proposals_single(proposals, def sample_proposals_single(proposals, gt_bboxes, gt_crowds, gt_labels, cfg):
gt_bboxes,
gt_crowds,
gt_labels,
cfg):
proposals = proposals[:, :4] proposals = proposals[:, :4]
assigned_gt_inds, assigned_labels, argmax_overlaps, max_overlaps = \ assigned_gt_inds, assigned_labels, argmax_overlaps, max_overlaps = \
bbox_assign( bbox_assign(
......
...@@ -84,18 +84,18 @@ def bbox_flip(bboxes, img_shape): ...@@ -84,18 +84,18 @@ def bbox_flip(bboxes, img_shape):
return mmcv.bbox_flip(bboxes, img_shape) return mmcv.bbox_flip(bboxes, img_shape)
def bbox_mapping(bboxes, img_shape, flip): def bbox_mapping(bboxes, img_shape, scale_factor, flip):
"""Map bboxes from the original image scale to testing scale""" """Map bboxes from the original image scale to testing scale"""
new_bboxes = bboxes * img_shape[-1] new_bboxes = bboxes * scale_factor
if flip: if flip:
new_bboxes = bbox_flip(new_bboxes, img_shape) new_bboxes = bbox_flip(new_bboxes, img_shape)
return new_bboxes return new_bboxes
def bbox_mapping_back(bboxes, img_shape, flip): def bbox_mapping_back(bboxes, img_shape, scale_factor, flip):
"""Map bboxes from testing scale to original image scale""" """Map bboxes from testing scale to original image scale"""
new_bboxes = bbox_flip(bboxes, img_shape) if flip else bboxes new_bboxes = bbox_flip(bboxes, img_shape) if flip else bboxes
new_bboxes = new_bboxes / img_shape[-1] new_bboxes = new_bboxes / scale_factor
return new_bboxes return new_bboxes
......
from .class_names import (voc_classes, imagenet_det_classes, from .class_names import (voc_classes, imagenet_det_classes,
imagenet_vid_classes, coco_classes, dataset_aliases, imagenet_vid_classes, coco_classes, dataset_aliases,
get_classes) get_classes)
from .coco_utils import coco_eval
from .mean_ap import average_precision, eval_map, print_map_summary from .mean_ap import average_precision, eval_map, print_map_summary
from .recall import (eval_recalls, print_recall_summary, plot_num_recall, from .recall import (eval_recalls, print_recall_summary, plot_num_recall,
plot_iou_recall) plot_iou_recall)
...@@ -9,5 +10,5 @@ __all__ = [ ...@@ -9,5 +10,5 @@ __all__ = [
'voc_classes', 'imagenet_det_classes', 'imagenet_vid_classes', 'voc_classes', 'imagenet_det_classes', 'imagenet_vid_classes',
'coco_classes', 'dataset_aliases', 'get_classes', 'average_precision', 'coco_classes', 'dataset_aliases', 'get_classes', 'average_precision',
'eval_map', 'print_map_summary', 'eval_recalls', 'print_recall_summary', 'eval_map', 'print_map_summary', 'eval_recalls', 'print_recall_summary',
'plot_num_recall', 'plot_iou_recall' 'plot_num_recall', 'plot_iou_recall', 'coco_eval'
] ]
import mmcv
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
def coco_eval(result_file, result_types, coco, max_dets=(100, 300, 1000)):
assert result_file.endswith('.json')
for res_type in result_types:
assert res_type in ['proposal', 'bbox', 'segm', 'keypoints']
if mmcv.is_str(coco):
coco = COCO(coco)
assert isinstance(coco, COCO)
coco_dets = coco.loadRes(result_file)
img_ids = coco.getImgIds()
for res_type in result_types:
iou_type = 'bbox' if res_type == 'proposal' else res_type
cocoEval = COCOeval(coco, coco_dets, iou_type)
cocoEval.params.imgIds = img_ids
if res_type == 'proposal':
cocoEval.params.useCats = 0
cocoEval.params.maxDets = list(max_dets)
cocoEval.evaluate()
cocoEval.accumulate()
cocoEval.summarize()
# TODO merge naive and weighted loss to one function. # TODO merge naive and weighted loss.
import torch import torch
import torch.nn.functional as F import torch.nn.functional as F
from ..bbox_ops import bbox_transform_inv, bbox_overlaps
def weighted_nll_loss(pred, label, weight, avg_factor=None):
if avg_factor is None:
avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
raw = F.nll_loss(pred, label, reduction='none')
return torch.sum(raw * weight)[None] / avg_factor
def weighted_nll_loss(pred, label, weight, ave_factor=None):
if ave_factor is None:
ave_factor = max(torch.sum(weight > 0).float().item(), 1.)
raw = F.nll_loss(pred, label, size_average=False, reduce=False)
return torch.sum(raw * weight)[None] / ave_factor
def weighted_cross_entropy(pred, label, weight, avg_factor=None):
if avg_factor is None:
avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
raw = F.cross_entropy(pred, label, reduction='none')
return torch.sum(raw * weight)[None] / avg_factor
def weighted_cross_entropy(pred, label, weight, ave_factor=None):
if ave_factor is None:
ave_factor = max(torch.sum(weight > 0).float().item(), 1.)
raw = F.cross_entropy(pred, label, size_average=False, reduce=False)
return torch.sum(raw * weight)[None] / ave_factor
def weighted_binary_cross_entropy(pred, label, weight, avg_factor=None):
def weighted_binary_cross_entropy(pred, label, weight, ave_factor=None): if avg_factor is None:
if ave_factor is None: avg_factor = max(torch.sum(weight > 0).float().item(), 1.)
ave_factor = max(torch.sum(weight > 0).float().item(), 1.)
return F.binary_cross_entropy_with_logits( return F.binary_cross_entropy_with_logits(
pred, label.float(), weight.float(), pred, label.float(), weight.float(),
size_average=False)[None] / ave_factor reduction='sum')[None] / avg_factor
def sigmoid_focal_loss(pred, def sigmoid_focal_loss(pred,
...@@ -46,13 +44,13 @@ def weighted_sigmoid_focal_loss(pred, ...@@ -46,13 +44,13 @@ def weighted_sigmoid_focal_loss(pred,
weight, weight,
gamma=2.0, gamma=2.0,
alpha=0.25, alpha=0.25,
ave_factor=None, avg_factor=None,
num_classes=80): num_classes=80):
if ave_factor is None: if avg_factor is None:
ave_factor = torch.sum(weight > 0).float().item() / num_classes + 1e-6 avg_factor = torch.sum(weight > 0).float().item() / num_classes + 1e-6
return sigmoid_focal_loss( return sigmoid_focal_loss(
pred, target, weight, gamma=gamma, alpha=alpha, pred, target, weight, gamma=gamma, alpha=alpha,
size_average=False)[None] / ave_factor reduction='sum')[None] / avg_factor
def mask_cross_entropy(pred, target, label): def mask_cross_entropy(pred, target, label):
...@@ -60,7 +58,7 @@ def mask_cross_entropy(pred, target, label): ...@@ -60,7 +58,7 @@ def mask_cross_entropy(pred, target, label):
inds = torch.arange(0, num_rois, dtype=torch.long, device=pred.device) inds = torch.arange(0, num_rois, dtype=torch.long, device=pred.device)
pred_slice = pred[inds, label].squeeze(1) pred_slice = pred[inds, label].squeeze(1)
return F.binary_cross_entropy_with_logits( return F.binary_cross_entropy_with_logits(
pred_slice, target, size_average=True)[None] pred_slice, target, reduction='sum')[None]
def weighted_mask_cross_entropy(pred, target, weight, label): def weighted_mask_cross_entropy(pred, target, weight, label):
...@@ -73,24 +71,27 @@ def weighted_mask_cross_entropy(pred, target, weight, label): ...@@ -73,24 +71,27 @@ def weighted_mask_cross_entropy(pred, target, weight, label):
pred_slice, target, weight, size_average=False)[None] / num_samples pred_slice, target, weight, size_average=False)[None] / num_samples
def smooth_l1_loss(pred, target, beta=1.0, size_average=True, reduce=True): def smooth_l1_loss(pred, target, beta=1.0, reduction='elementwise_mean'):
assert beta > 0 assert beta > 0
assert pred.size() == target.size() and target.numel() > 0 assert pred.size() == target.size() and target.numel() > 0
diff = torch.abs(pred - target) diff = torch.abs(pred - target)
loss = torch.where(diff < beta, 0.5 * diff * diff / beta, loss = torch.where(diff < beta, 0.5 * diff * diff / beta,
diff - 0.5 * beta) diff - 0.5 * beta)
if size_average: reduction = F._Reduction.get_enum(reduction)
loss /= pred.numel() # none: 0, elementwise_mean:1, sum: 2
if reduce: if reduction == 0:
loss = loss.sum() return loss
return loss elif reduction == 1:
return loss.sum() / pred.numel()
elif reduction == 2:
def weighted_smoothl1(pred, target, weight, beta=1.0, ave_factor=None): return loss.sum()
if ave_factor is None:
ave_factor = torch.sum(weight > 0).float().item() / 4 + 1e-6
loss = smooth_l1_loss(pred, target, beta, size_average=False, reduce=False) def weighted_smoothl1(pred, target, weight, beta=1.0, avg_factor=None):
return torch.sum(loss * weight)[None] / ave_factor if avg_factor is None:
avg_factor = torch.sum(weight > 0).float().item() / 4 + 1e-6
loss = smooth_l1_loss(pred, target, beta, reduction='none')
return torch.sum(loss * weight)[None] / avg_factor
def accuracy(pred, target, topk=1): def accuracy(pred, target, topk=1):
......
import cvbase as cvb
import numpy as np
import pycocotools.mask as mask_utils
import mmcv import mmcv
......
import torch import torch
from mmdet.ops import nms
import numpy as np import numpy as np
from mmdet.ops import nms
from ..bbox_ops import bbox_mapping_back from ..bbox_ops import bbox_mapping_back
...@@ -21,11 +21,12 @@ def merge_aug_proposals(aug_proposals, img_metas, rpn_test_cfg): ...@@ -21,11 +21,12 @@ def merge_aug_proposals(aug_proposals, img_metas, rpn_test_cfg):
""" """
recovered_proposals = [] recovered_proposals = []
for proposals, img_info in zip(aug_proposals, img_metas): for proposals, img_info in zip(aug_proposals, img_metas):
shape_scale = img_info['shape_scale'][0] img_shape = img_info['img_shape']
flip = img_info['flip'][0] scale_factor = img_info['scale_factor']
flip = img_info['flip']
_proposals = proposals.clone() _proposals = proposals.clone()
_proposals[:, :4] = bbox_mapping_back(_proposals[:, :4], shape_scale, _proposals[:, :4] = bbox_mapping_back(_proposals[:, :4], img_shape,
flip) scale_factor, flip)
recovered_proposals.append(_proposals) recovered_proposals.append(_proposals)
aug_proposals = torch.cat(recovered_proposals, dim=0) aug_proposals = torch.cat(recovered_proposals, dim=0)
nms_keep = nms(aug_proposals, rpn_test_cfg.nms_thr, nms_keep = nms(aug_proposals, rpn_test_cfg.nms_thr,
...@@ -53,9 +54,10 @@ def merge_aug_bboxes(aug_bboxes, aug_scores, img_metas, rcnn_test_cfg): ...@@ -53,9 +54,10 @@ def merge_aug_bboxes(aug_bboxes, aug_scores, img_metas, rcnn_test_cfg):
""" """
recovered_bboxes = [] recovered_bboxes = []
for bboxes, img_info in zip(aug_bboxes, img_metas): for bboxes, img_info in zip(aug_bboxes, img_metas):
shape_scale = img_info['shape_scale'][0] img_shape = img_info['img_shape']
flip = img_info['flip'][0] scale_factor = img_info['scale_factor']
bboxes = bbox_mapping_back(bboxes, shape_scale, flip) flip = img_info['flip']
bboxes = bbox_mapping_back(bboxes, img_shape, scale_factor, flip)
recovered_bboxes.append(bboxes) recovered_bboxes.append(bboxes)
bboxes = torch.stack(recovered_bboxes).mean(dim=0) bboxes = torch.stack(recovered_bboxes).mean(dim=0)
if aug_scores is None: if aug_scores is None:
......
...@@ -50,15 +50,18 @@ class AnchorGenerator(object): ...@@ -50,15 +50,18 @@ class AnchorGenerator(object):
return yy, xx return yy, xx
def grid_anchors(self, featmap_size, stride=16, device='cuda'): def grid_anchors(self, featmap_size, stride=16, device='cuda'):
base_anchors = self.base_anchors.to(device)
feat_h, feat_w = featmap_size feat_h, feat_w = featmap_size
shift_x = torch.arange(0, feat_w, device=device) * stride shift_x = torch.arange(0, feat_w, device=device) * stride
shift_y = torch.arange(0, feat_h, device=device) * stride shift_y = torch.arange(0, feat_h, device=device) * stride
shift_xx, shift_yy = self._meshgrid(shift_x, shift_y) shift_xx, shift_yy = self._meshgrid(shift_x, shift_y)
shifts = torch.stack([shift_xx, shift_yy, shift_xx, shift_yy], dim=-1) shifts = torch.stack([shift_xx, shift_yy, shift_xx, shift_yy], dim=-1)
shifts = shifts.type_as(base_anchors)
# first feat_w elements correspond to the first row of shifts # first feat_w elements correspond to the first row of shifts
# add A anchors (1, A, 4) to K shifts (K, 1, 4) to get # add A anchors (1, A, 4) to K shifts (K, 1, 4) to get
# shifted anchors (K, A, 4), reshape to (K*A, 4) # shifted anchors (K, A, 4), reshape to (K*A, 4)
base_anchors = self.base_anchors.to(device)
all_anchors = base_anchors[None, :, :] + shifts[:, None, :] all_anchors = base_anchors[None, :, :] + shifts[:, None, :]
all_anchors = all_anchors.view(-1, 4) all_anchors = all_anchors.view(-1, 4)
# first A rows correspond to A anchors of (0, 0) in feature map, # first A rows correspond to A anchors of (0, 0) in feature map,
......
...@@ -4,12 +4,14 @@ from ..bbox_ops import (bbox_assign, bbox_transform, bbox_sampling) ...@@ -4,12 +4,14 @@ from ..bbox_ops import (bbox_assign, bbox_transform, bbox_sampling)
def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list, def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list,
img_shapes, target_means, target_stds, cfg): img_metas, target_means, target_stds, cfg):
"""Compute anchor regression and classification targets """Compute regression and classification targets for anchors.
There may be multiple feature levels,
Args: Args:
anchor_list(list): anchors of each feature map level anchor_list(list): anchors of each feature map level
featuremap_sizes(list): feature map sizes featmap_sizes(list): feature map sizes
gt_bboxes_list(list): ground truth bbox of images in a mini-batch gt_bboxes_list(list): ground truth bbox of images in a mini-batch
img_shapes(list): shape of each image in a mini-batch img_shapes(list): shape of each image in a mini-batch
cfg(dict): configs cfg(dict): configs
...@@ -17,15 +19,16 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list, ...@@ -17,15 +19,16 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list,
Returns: Returns:
tuple tuple
""" """
if len(featmap_sizes) == len(anchor_list): num_imgs = len(img_metas)
num_levels = len(featmap_sizes)
if len(anchor_list) == num_levels:
all_anchors = torch.cat(anchor_list, 0) all_anchors = torch.cat(anchor_list, 0)
anchor_nums = [anchors.size(0) for anchors in anchor_list] anchor_nums = [anchors.size(0) for anchors in anchor_list]
use_isomerism_anchors = False use_isomerism_anchors = False
elif len(img_shapes) == len(anchor_list): elif len(anchor_list) == num_imgs:
# using different anchors for different images # using different anchors for different images
all_anchors_list = [ all_anchors_list = [
torch.cat(anchor_list[img_id], 0) torch.cat(anchor_list[img_id], 0) for img_id in range(num_imgs)
for img_id in range(len(img_shapes))
] ]
anchor_nums = [anchors.size(0) for anchors in anchor_list[0]] anchor_nums = [anchors.size(0) for anchors in anchor_list[0]]
use_isomerism_anchors = True use_isomerism_anchors = True
...@@ -37,7 +40,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list, ...@@ -37,7 +40,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list,
all_bbox_targets = [] all_bbox_targets = []
all_bbox_weights = [] all_bbox_weights = []
num_total_sampled = 0 num_total_sampled = 0
for img_id in range(len(img_shapes)): for img_id in range(num_imgs):
if isinstance(valid_flag_list[img_id], list): if isinstance(valid_flag_list[img_id], list):
valid_flags = torch.cat(valid_flag_list[img_id], 0) valid_flags = torch.cat(valid_flag_list[img_id], 0)
else: else:
...@@ -45,7 +48,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list, ...@@ -45,7 +48,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list,
if use_isomerism_anchors: if use_isomerism_anchors:
all_anchors = all_anchors_list[img_id] all_anchors = all_anchors_list[img_id]
inside_flags = anchor_inside_flags(all_anchors, valid_flags, inside_flags = anchor_inside_flags(all_anchors, valid_flags,
img_shapes[img_id][:2], img_metas[img_id]['img_shape'][:2],
cfg.allowed_border) cfg.allowed_border)
if not inside_flags.any(): if not inside_flags.any():
return None return None
...@@ -83,7 +86,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list, ...@@ -83,7 +86,7 @@ def anchor_target(anchor_list, valid_flag_list, featmap_sizes, gt_bboxes_list,
def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means, def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means,
target_stds, cfg): target_stds, cfg):
num_total_anchors = all_anchors.size(0) # assign gt and sample anchors
anchors = all_anchors[inside_flags, :] anchors = all_anchors[inside_flags, :]
assigned_gt_inds, argmax_overlaps, max_overlaps = bbox_assign( assigned_gt_inds, argmax_overlaps, max_overlaps = bbox_assign(
anchors, anchors,
...@@ -99,10 +102,9 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means, ...@@ -99,10 +102,9 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means,
bbox_targets = torch.zeros_like(anchors) bbox_targets = torch.zeros_like(anchors)
bbox_weights = torch.zeros_like(anchors) bbox_weights = torch.zeros_like(anchors)
labels = torch.zeros_like(assigned_gt_inds) labels = torch.zeros_like(assigned_gt_inds)
label_weights = torch.zeros_like(assigned_gt_inds, dtype=torch.float) label_weights = torch.zeros_like(assigned_gt_inds, dtype=anchors.dtype)
if len(pos_inds) > 0: if len(pos_inds) > 0:
pos_inds = unique(pos_inds)
pos_anchors = anchors[pos_inds, :] pos_anchors = anchors[pos_inds, :]
pos_gt_bbox = gt_bboxes[assigned_gt_inds[pos_inds] - 1, :] pos_gt_bbox = gt_bboxes[assigned_gt_inds[pos_inds] - 1, :]
pos_bbox_targets = bbox_transform(pos_anchors, pos_gt_bbox, pos_bbox_targets = bbox_transform(pos_anchors, pos_gt_bbox,
...@@ -115,10 +117,10 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means, ...@@ -115,10 +117,10 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means,
else: else:
label_weights[pos_inds] = cfg.pos_weight label_weights[pos_inds] = cfg.pos_weight
if len(neg_inds) > 0: if len(neg_inds) > 0:
neg_inds = unique(neg_inds)
label_weights[neg_inds] = 1.0 label_weights[neg_inds] = 1.0
# map up to original set of anchors # map up to original set of anchors
num_total_anchors = all_anchors.size(0)
labels = unmap(labels, num_total_anchors, inside_flags) labels = unmap(labels, num_total_anchors, inside_flags)
label_weights = unmap(label_weights, num_total_anchors, inside_flags) label_weights = unmap(label_weights, num_total_anchors, inside_flags)
bbox_targets = unmap(bbox_targets, num_total_anchors, inside_flags) bbox_targets = unmap(bbox_targets, num_total_anchors, inside_flags)
...@@ -127,8 +129,9 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means, ...@@ -127,8 +129,9 @@ def anchor_target_single(all_anchors, inside_flags, gt_bboxes, target_means,
return (labels, label_weights, bbox_targets, bbox_weights, pos_inds, return (labels, label_weights, bbox_targets, bbox_weights, pos_inds,
neg_inds) neg_inds)
def anchor_inside_flags(all_anchors, valid_flags, img_shape, allowed_border=0): def anchor_inside_flags(all_anchors, valid_flags, img_shape, allowed_border=0):
img_h, img_w = img_shape.float() img_h, img_w = img_shape[:2]
if allowed_border >= 0: if allowed_border >= 0:
inside_flags = valid_flags & \ inside_flags = valid_flags & \
(all_anchors[:, 0] >= -allowed_border) & \ (all_anchors[:, 0] >= -allowed_border) & \
...@@ -139,6 +142,7 @@ def anchor_inside_flags(all_anchors, valid_flags, img_shape, allowed_border=0): ...@@ -139,6 +142,7 @@ def anchor_inside_flags(all_anchors, valid_flags, img_shape, allowed_border=0):
inside_flags = valid_flags inside_flags = valid_flags
return inside_flags return inside_flags
def unique(tensor): def unique(tensor):
if tensor.is_cuda: if tensor.is_cuda:
u_tensor = np.unique(tensor.cpu().numpy()) u_tensor = np.unique(tensor.cpu().numpy())
...@@ -146,6 +150,7 @@ def unique(tensor): ...@@ -146,6 +150,7 @@ def unique(tensor):
else: else:
return torch.unique(tensor) return torch.unique(tensor)
def unmap(data, count, inds, fill=0): def unmap(data, count, inds, fill=0):
""" Unmap a subset of item (data) back to the original set of items (of """ Unmap a subset of item (data) back to the original set of items (of
size count) """ size count) """
......
from mmdet.datasets import collate
from mmdet.nn.parallel import scatter
__all__ = ['_data_func']
def _data_func(data, gpu_id):
imgs, img_metas = tuple(
scatter(collate([data], samples_per_gpu=1), [gpu_id])[0])
return dict(
img=imgs,
img_meta=img_metas,
return_loss=False,
return_bboxes=True,
rescale=True)
import numpy as np
import torch
from collections import OrderedDict
from mmdet.nn.parallel import scatter
def parse_losses(losses):
log_vars = OrderedDict()
for loss_key, loss_value in losses.items():
if isinstance(loss_value, dict):
for _key, _value in loss_value.items():
if isinstance(_value, list):
_value = sum([_loss.mean() for _loss in _value])
else:
_value = _value.mean()
log_vars[_keys] = _value
elif isinstance(loss_value, list):
log_vars[loss_key] = sum(_loss.mean() for _loss in loss_value)
else:
log_vars[loss_key] = loss_value.mean()
loss = sum(_value for _key, _value in log_vars.items() if 'loss' in _key)
log_vars['loss'] = loss
for _key, _value in log_vars.items():
log_vars[_key] = _value.item()
return loss, log_vars
def batch_processor(model, data, train_mode, args=None):
data = scatter(data, [torch.cuda.current_device()])[0]
losses = model(**data)
loss, log_vars = parse_losses(losses)
outputs = dict(
loss=loss / args.world_size,
log_vars=log_vars,
num_samples=len(data['img'].data))
return outputs
...@@ -3,11 +3,11 @@ import torch ...@@ -3,11 +3,11 @@ import torch
import torch.multiprocessing as mp import torch.multiprocessing as mp
import torch.distributed as dist import torch.distributed as dist
from torch.nn.utils import clip_grad from torch.nn.utils import clip_grad
from mmcv.torchpack import Hook, OptimizerStepperHook from mmcv.torchpack import Hook, OptimizerHook
__all__ = [ __all__ = [
'init_dist', 'average_gradients', 'broadcast_params', 'init_dist', 'average_gradients', 'broadcast_params', 'DistOptimizerHook',
'DistOptimizerStepperHook', 'DistSamplerSeedHook' 'DistSamplerSeedHook'
] ]
...@@ -40,17 +40,16 @@ def broadcast_params(model): ...@@ -40,17 +40,16 @@ def broadcast_params(model):
dist.broadcast(p, 0) dist.broadcast(p, 0)
class DistOptimizerStepperHook(OptimizerStepperHook): class DistOptimizerHook(OptimizerHook):
def after_train_iter(self, runner): def after_train_iter(self, runner):
runner.optimizer.zero_grad() runner.optimizer.zero_grad()
runner.outputs['loss'].backward() runner.outputs['loss'].backward()
average_gradients(runner.model) average_gradients(runner.model)
if self.grad_clip: if self.grad_clip is not None:
clip_grad.clip_grad_norm_( clip_grad.clip_grad_norm_(
filter(lambda p: p.requires_grad, runner.model.parameters()), filter(lambda p: p.requires_grad, runner.model.parameters()),
max_norm=self.max_norm, **self.grad_clip)
norm_type=self.norm_type)
runner.optimizer.step() runner.optimizer.step()
......
...@@ -7,7 +7,7 @@ import mmcv ...@@ -7,7 +7,7 @@ import mmcv
import numpy as np import numpy as np
import torch import torch
from mmcv.torchpack import Hook from mmcv.torchpack import Hook
from mmdet.datasets import collate from mmdet.datasets.loader import collate
from mmdet.nn.parallel import scatter from mmdet.nn.parallel import scatter
from pycocotools.cocoeval import COCOeval from pycocotools.cocoeval import COCOeval
......
import subprocess
import mmcv import mmcv
import numpy as np import numpy as np
import torch import torch
...@@ -7,20 +5,14 @@ import torch ...@@ -7,20 +5,14 @@ import torch
__all__ = ['tensor2imgs', 'unique', 'unmap', 'results2json'] __all__ = ['tensor2imgs', 'unique', 'unmap', 'results2json']
def tensor2imgs(tensor, def tensor2imgs(tensor, mean=(0, 0, 0), std=(1, 1, 1), to_rgb=True):
color_order='RGB', num_imgs = tensor.size(0)
color_mean=(0.485, 0.456, 0.406), mean = np.array(mean, dtype=np.float32)
color_std=(0.229, 0.224, 0.225)): std = np.array(std, dtype=np.float32)
assert color_order in ['RGB', 'BGR']
img_per_gpu = tensor.size(0)
color_mean = np.array(color_mean, dtype=np.float32)
color_std = np.array(color_std, dtype=np.float32)
imgs = [] imgs = []
for img_id in range(img_per_gpu): for img_id in range(num_imgs):
img = tensor[img_id, ...].cpu().numpy().transpose(1, 2, 0) img = tensor[img_id, ...].cpu().numpy().transpose(1, 2, 0)
if color_order == 'RGB': img = mmcv.imdenorm(img, mean, std, to_bgr=to_rgb).astype(np.uint8)
img = mmcv.rgb2bgr(img)
img = img * color_std + color_mean
imgs.append(np.ascontiguousarray(img)) imgs.append(np.ascontiguousarray(img))
return imgs return imgs
...@@ -45,6 +37,7 @@ def unmap(data, count, inds, fill=0): ...@@ -45,6 +37,7 @@ def unmap(data, count, inds, fill=0):
ret[inds, :] = data ret[inds, :] = data
return ret return ret
def xyxy2xywh(bbox): def xyxy2xywh(bbox):
_bbox = bbox.tolist() _bbox = bbox.tolist()
return [ return [
...@@ -54,6 +47,7 @@ def xyxy2xywh(bbox): ...@@ -54,6 +47,7 @@ def xyxy2xywh(bbox):
_bbox[3] - _bbox[1] + 1, _bbox[3] - _bbox[1] + 1,
] ]
def det2json(dataset, results): def det2json(dataset, results):
json_results = [] json_results = []
for idx in range(len(dataset)): for idx in range(len(dataset)):
......
...@@ -14,14 +14,24 @@ def scatter(inputs, target_gpus, dim=0): ...@@ -14,14 +14,24 @@ def scatter(inputs, target_gpus, dim=0):
def scatter_map(obj): def scatter_map(obj):
if isinstance(obj, torch.Tensor): if isinstance(obj, torch.Tensor):
return OrigScatter.apply(target_gpus, None, dim, obj) return OrigScatter.apply(target_gpus, None, dim, obj)
if isinstance(obj, DataContainer) and isinstance(obj.data, list): if isinstance(obj, DataContainer):
return Scatter.forward(target_gpus, obj.data) # print('data container', obj)
if obj.cpu_only:
return obj.data
else:
return Scatter.forward(target_gpus, obj.data)
if isinstance(obj, tuple) and len(obj) > 0: if isinstance(obj, tuple) and len(obj) > 0:
return list(zip(*map(scatter_map, obj))) return list(zip(*map(scatter_map, obj)))
if isinstance(obj, list) and len(obj) > 0: if isinstance(obj, list) and len(obj) > 0:
return list(map(list, zip(*map(scatter_map, obj)))) # print('list', obj)
out = list(map(list, zip(*map(scatter_map, obj))))
# print('list out', out)
return out
if isinstance(obj, dict) and len(obj) > 0: if isinstance(obj, dict) and len(obj) > 0:
return list(map(type(obj), zip(*map(scatter_map, obj.items())))) # print('dict\n', obj)
out = list(map(type(obj), zip(*map(scatter_map, obj.items()))))
# print('dict output\n', out)
return out
return [obj for targets in target_gpus] return [obj for targets in target_gpus]
# After scatter_map is called, a scatter_map cell will exist. This cell # After scatter_map is called, a scatter_map cell will exist. This cell
......
...@@ -8,7 +8,7 @@ def readme(): ...@@ -8,7 +8,7 @@ def readme():
def get_version(): def get_version():
version_file = 'mmcv/version.py' version_file = 'mmdet/version.py'
with open(version_file, 'r') as f: with open(version_file, 'r') as f:
exec(compile(f.read(), version_file, 'exec')) exec(compile(f.read(), version_file, 'exec'))
return locals()['__version__'] return locals()['__version__']
......
from argparse import ArgumentParser
from mmdet.core import coco_eval
def main():
parser = ArgumentParser(description='COCO Evaluation')
parser.add_argument('result', help='result file path')
parser.add_argument('--ann', help='annotation file path')
parser.add_argument(
'--types', type=str, nargs='+', default=['bbox'], help='result types')
parser.add_argument(
'--max-dets',
type=int,
nargs='+',
default=[100, 300, 1000],
help='result types')
args = parser.parse_args()
coco_eval(args.result, args.types, args.ann, args.max_dets)
if __name__ == '__main__':
main()
# model settings # model settings
model = dict( model = dict(
pretrained= type='FasterRCNN',
'/mnt/lustre/pangjiangmiao/initmodel/pytorch/resnet50-19c8e357.pth', pretrained='modelzoo://resnet50',
backbone=dict( backbone=dict(
type='resnet', type='resnet',
depth=50, depth=50,
...@@ -25,7 +25,7 @@ model = dict( ...@@ -25,7 +25,7 @@ model = dict(
target_means=[.0, .0, .0, .0], target_means=[.0, .0, .0, .0],
target_stds=[1.0, 1.0, 1.0, 1.0], target_stds=[1.0, 1.0, 1.0, 1.0],
use_sigmoid_cls=True), use_sigmoid_cls=True),
roi_block=dict( bbox_roi_extractor=dict(
type='SingleLevelRoI', type='SingleLevelRoI',
roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2), roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),
out_channels=256, out_channels=256,
...@@ -40,8 +40,9 @@ model = dict( ...@@ -40,8 +40,9 @@ model = dict(
target_means=[0., 0., 0., 0.], target_means=[0., 0., 0., 0.],
target_stds=[0.1, 0.1, 0.2, 0.2], target_stds=[0.1, 0.1, 0.2, 0.2],
reg_class_agnostic=False)) reg_class_agnostic=False))
meta_params = dict( # model training and testing settings
rpn_train_cfg = dict( train_cfg = dict(
rpn=dict(
pos_fraction=0.5, pos_fraction=0.5,
pos_balance_sampling=False, pos_balance_sampling=False,
neg_pos_ub=256, neg_pos_ub=256,
...@@ -54,14 +55,7 @@ meta_params = dict( ...@@ -54,14 +55,7 @@ meta_params = dict(
pos_weight=-1, pos_weight=-1,
smoothl1_beta=1 / 9.0, smoothl1_beta=1 / 9.0,
debug=False), debug=False),
rpn_test_cfg = dict( rcnn=dict(
nms_across_levels=False,
nms_pre=2000,
nms_post=2000,
max_num=2000,
nms_thr=0.7,
min_bbox_size=0),
rcnn_train_cfg = dict(
pos_iou_thr=0.5, pos_iou_thr=0.5,
neg_iou_thr=0.5, neg_iou_thr=0.5,
crowd_thr=1.1, crowd_thr=1.1,
...@@ -72,54 +66,65 @@ meta_params = dict( ...@@ -72,54 +66,65 @@ meta_params = dict(
neg_pos_ub=512, neg_pos_ub=512,
neg_balance_thr=0, neg_balance_thr=0,
pos_weight=-1, pos_weight=-1,
debug=False), debug=False))
rcnn_test_cfg = dict(score_thr=1e-3, max_per_img=100, nms_thr=0.5) test_cfg = dict(
) rpn=dict(
nms_across_levels=False,
nms_pre=2000,
nms_post=2000,
max_num=2000,
nms_thr=0.7,
min_bbox_size=0),
rcnn=dict(score_thr=1e-3, max_per_img=100, nms_thr=0.5))
# dataset settings # dataset settings
data_root = '/mnt/lustre/pangjiangmiao/dataset/coco/' dataset_type = 'CocoDataset'
data_root = '../data/coco/'
img_norm_cfg = dict( img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
std=[58.395, 57.12, 57.375], data = dict(
to_rgb=True) imgs_per_gpu=2,
img_per_gpu = 1 workers_per_gpu=2,
data_workers = 2 train=dict(
train_dataset = dict( type=dataset_type,
ann_file=data_root + 'annotations/instances_train2017.json', ann_file=data_root + 'annotations/instances_train2017.json',
img_prefix=data_root + 'train2017/', img_prefix=data_root + 'train2017/',
img_scale=(1333, 800), img_scale=(1333, 800),
img_norm_cfg=img_norm_cfg, img_norm_cfg=img_norm_cfg,
size_divisor=32, size_divisor=32,
flip_ratio=0.5) flip_ratio=0.5),
test_dataset = dict( test=dict(
ann_file=data_root + 'annotations/instances_val2017.json', type=dataset_type,
img_prefix=data_root + 'val2017/', ann_file=data_root + 'annotations/instances_val2017.json',
img_scale=(1333, 800), img_prefix=data_root + 'val2017/',
img_norm_cfg=img_norm_cfg, img_scale=(1333, 800),
size_divisor=32) flip_ratio=0,
img_norm_cfg=img_norm_cfg,
size_divisor=32))
# optimizer # optimizer
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001) optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
grad_clip_config = dict(grad_clip=True, max_norm=35, norm_type=2) optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
# learning policy # learning policy
lr_policy = dict( lr_config = dict(
policy='step', policy='step',
warmup='linear', warmup='linear',
warmup_iters=500, warmup_iters=500,
warmup_ratio=0.333, warmup_ratio=1.0 / 3,
step=[8, 11]) step=[8, 11])
max_epoch = 12
checkpoint_config = dict(interval=1) checkpoint_config = dict(interval=1)
dist_params = dict(backend='nccl', port='29500', master_ip='127.0.0.1')
# logging settings
log_level = 'INFO'
# yapf:disable # yapf:disable
log_config = dict( log_config = dict(
interval=50, interval=50,
hooks=[ hooks=[
dict(type='TextLoggerHook'), dict(type='TextLoggerHook'),
# ('TensorboardLoggerHook', dict(log_dir=work_dir + '/log')), # dict(type='TensorboardLoggerHook', log_dir=work_dir + '/log')
]) ])
# yapf:enable # yapf:enable
work_dir = './model/r50_fpn_frcnn_1x' # runtime settings
total_epochs = 12
device_ids = range(8)
dist_params = dict(backend='nccl', port='29500', master_ip='127.0.0.1')
log_level = 'INFO'
work_dir = './work_dirs/fpn_faster_rcnn_r50_1x'
load_from = None load_from = None
resume_from = None resume_from = None
workflow = [('train', 1)] workflow = [('train', 1)]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment