Skip to content

Commit 01c560c

Browse files
add o2_rtdetr dotav1.5
1 parent d49038e commit 01c560c

5 files changed

Lines changed: 385 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# dataset settings
2+
dataset_type = 'DOTAv15Dataset'
3+
data_root = 'data/split_ss_dota1.5/'
4+
5+
backend_args = None
6+
7+
train_pipeline = [
8+
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
9+
dict(type='mmdet.LoadAnnotations', with_bbox=True, box_type='qbox'),
10+
dict(type='ConvertBoxType', box_type_mapping=dict(gt_bboxes='rbox')),
11+
dict(type='mmdet.Resize', scale=(1024, 1024), keep_ratio=True),
12+
dict(
13+
type='mmdet.RandomFlip',
14+
prob=0.75,
15+
direction=['horizontal', 'vertical', 'diagonal']),
16+
dict(
17+
type='RandomRotate',
18+
prob=0.5,
19+
angle_range=180,
20+
rect_obj_labels=[9, 11]),
21+
dict(
22+
type='mmdet.Pad', size=(1024, 1024),
23+
pad_val=dict(img=(114, 114, 114))),
24+
dict(type='mmdet.PackDetInputs')
25+
]
26+
val_pipeline = [
27+
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
28+
dict(type='mmdet.Resize', scale=(1024, 1024), keep_ratio=True),
29+
# avoid bboxes being resized
30+
dict(type='mmdet.LoadAnnotations', with_bbox=True, box_type='qbox'),
31+
dict(type='ConvertBoxType', box_type_mapping=dict(gt_bboxes='rbox')),
32+
dict(
33+
type='mmdet.Pad', size=(1024, 1024),
34+
pad_val=dict(img=(114, 114, 114))),
35+
dict(
36+
type='mmdet.PackDetInputs',
37+
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
38+
'scale_factor'))
39+
]
40+
test_pipeline = [
41+
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
42+
dict(type='mmdet.Resize', scale=(1024, 1024), keep_ratio=True),
43+
dict(
44+
type='mmdet.Pad', size=(1024, 1024),
45+
pad_val=dict(img=(114, 114, 114))),
46+
dict(
47+
type='mmdet.PackDetInputs',
48+
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
49+
'scale_factor'))
50+
]
51+
train_dataloader = dict(
52+
batch_size=4,
53+
num_workers=4,
54+
persistent_workers=True,
55+
sampler=dict(type='DefaultSampler', shuffle=True),
56+
batch_sampler=None,
57+
pin_memory=False,
58+
dataset=dict(
59+
type=dataset_type,
60+
data_root=data_root,
61+
ann_file='trainval/annfiles/',
62+
data_prefix=dict(img_path='trainval/images/'),
63+
filter_cfg=dict(filter_empty_gt=True),
64+
pipeline=train_pipeline))
65+
val_dataloader = dict(
66+
batch_size=4,
67+
num_workers=4,
68+
persistent_workers=True,
69+
drop_last=False,
70+
sampler=dict(type='DefaultSampler', shuffle=False),
71+
dataset=dict(
72+
type=dataset_type,
73+
data_root=data_root,
74+
ann_file='trainval/annfiles/',
75+
data_prefix=dict(img_path='trainval/images/'),
76+
test_mode=True,
77+
pipeline=val_pipeline))
78+
# test_dataloader = val_dataloader
79+
80+
val_evaluator = dict(type='DOTAMetric', metric='mAP')
81+
# test_evaluator = val_evaluator
82+
83+
# inference on test dataset and format the output results
84+
# for submission. Note: the test set has no annotation.
85+
test_dataloader = dict(
86+
batch_size=4,
87+
num_workers=4,
88+
persistent_workers=False,
89+
drop_last=False,
90+
sampler=dict(type='DefaultSampler', shuffle=False),
91+
dataset=dict(
92+
type=dataset_type,
93+
data_root=data_root,
94+
data_prefix=dict(img_path='test/images/'),
95+
test_mode=True,
96+
pipeline=test_pipeline))
97+
test_evaluator = dict(
98+
type='DOTAMetric',
99+
format_only=True,
100+
merge_patches=True,
101+
outfile_prefix='./work_dirs/Task1')
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from mmengine.config import read_base
2+
with read_base():
3+
from .o2_rtdetr_r50vd_2xb4_72e_dotav15 import *
4+
5+
pretrained = ('https://www.modelscope.cn/models/wokaikaixinxin/ai4rs/resolve/'
6+
'master/rtdetr/resnet101vd_ssld_pretrained_64ed664a.pth') # noqa
7+
8+
model.update(
9+
backbone=dict(
10+
depth=101, init_cfg=dict(type='Pretrained', checkpoint=pretrained)),
11+
neck=dict(out_channels=384),
12+
encoder=dict(
13+
in_channels=[384, 384, 384],
14+
fpn_cfg=dict(in_channels=[384, 384, 384]),
15+
layer_cfg=dict(
16+
self_attn_cfg=dict(embed_dims=384),
17+
ffn_cfg=dict(embed_dims=384, feedforward_channels=2048))))
18+
19+
# optimizer
20+
optim_wrapper.update(
21+
paramwise_cfg=dict(
22+
custom_keys={'backbone': dict(lr_mult=0.01)}, norm_decay_mult=1))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from mmengine.config import read_base
2+
with read_base():
3+
from .o2_rtdetr_r50vd_2xb4_72e_dotav15 import *
4+
5+
pretrained = ('https://www.modelscope.cn/models/wokaikaixinxin/ai4rs/resolve/'
6+
'master/rtdetr/resnet18vd_pretrained_55f5a0d6.pth') # noqa
7+
8+
model.update(
9+
backbone=dict(
10+
depth=18,
11+
frozen_stages=-1,
12+
norm_cfg=dict(requires_grad=True),
13+
norm_eval=False,
14+
init_cfg=dict(type='Pretrained', checkpoint=pretrained)),
15+
neck=dict(in_channels=[128, 256, 512]),
16+
encoder=dict(fpn_cfg=dict(expansion=0.5)),
17+
decoder=dict(num_layers=3))
18+
19+
# set all norm layers in backbone to lr_mult=0.1 and decay_mult=0.0
20+
# set all other layers in backbone to lr_mult=0.1
21+
num_blocks_list = (2, 2, 2, 2) # r18
22+
downsample_norm_idx_list = (2, 3, 3, 3) # r18
23+
backbone_norm_multi = dict(lr_mult=0.1, decay_mult=0.0)
24+
custom_keys = {'backbone': dict(lr_mult=0.1)}
25+
custom_keys.update({
26+
f'backbone.layer{stage_id + 1}.{block_id}.bn': backbone_norm_multi
27+
for stage_id, num_blocks in enumerate(num_blocks_list)
28+
for block_id in range(num_blocks)
29+
})
30+
custom_keys.update({
31+
f'backbone.layer{stage_id + 1}.{block_id}.downsample.{downsample_norm_idx - 1}': # noqa
32+
backbone_norm_multi
33+
for stage_id, (num_blocks, downsample_norm_idx) in enumerate(
34+
zip(num_blocks_list, downsample_norm_idx_list))
35+
for block_id in range(num_blocks)
36+
})
37+
38+
# optimizer
39+
optim_wrapper.paramwise_cfg.pop('custom_keys')
40+
optim_wrapper.update(
41+
paramwise_cfg=dict(custom_keys=dict(**custom_keys)))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from mmengine.config import read_base
2+
with read_base():
3+
from .o2_rtdetr_r50vd_2xb4_72e_dotav15 import *
4+
5+
pretrained = ('https://www.modelscope.cn/models/wokaikaixinxin/ai4rs/resolve/'
6+
'master/rtdetr/resnet34vd_pretrained_f6a72dc5.pth') # noqa
7+
8+
model.update(
9+
backbone=dict(
10+
depth=34,
11+
frozen_stages=-1,
12+
norm_cfg=dict(requires_grad=True),
13+
norm_eval=False,
14+
init_cfg=dict(type='Pretrained', checkpoint=pretrained)),
15+
neck=dict(in_channels=[128, 256, 512]),
16+
encoder=dict(fpn_cfg=dict(expansion=0.5)),
17+
decoder=dict(num_layers=4))
18+
19+
# set all norm layers in backbone to lr_mult=0.1 and decay_mult=0.0
20+
# set all other layers in backbone to lr_mult=0.1
21+
num_blocks_list = (3, 4, 6, 3) # r34
22+
downsample_norm_idx_list = (2, 3, 3, 3) # r34
23+
backbone_norm_multi = dict(lr_mult=0.1, decay_mult=0.0)
24+
custom_keys = {'backbone': dict(lr_mult=0.1)}
25+
custom_keys.update({
26+
f'backbone.layer{stage_id + 1}.{block_id}.bn': backbone_norm_multi
27+
for stage_id, num_blocks in enumerate(num_blocks_list)
28+
for block_id in range(num_blocks)
29+
})
30+
custom_keys.update({
31+
f'backbone.layer{stage_id + 1}.{block_id}.downsample.{downsample_norm_idx - 1}': # noqa
32+
backbone_norm_multi
33+
for stage_id, (num_blocks, downsample_norm_idx) in enumerate(
34+
zip(num_blocks_list, downsample_norm_idx_list))
35+
for block_id in range(num_blocks)
36+
})
37+
38+
# optimizer
39+
optim_wrapper.paramwise_cfg.pop('custom_keys')
40+
optim_wrapper.update(
41+
paramwise_cfg=dict(custom_keys=dict(**custom_keys)))
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from torch.optim.adamw import AdamW
2+
from mmengine.config import read_base
3+
from mmengine.runner.loops import EpochBasedTrainLoop, TestLoop, ValLoop
4+
from mmengine.optim.optimizer import OptimWrapper
5+
from mmengine.optim.scheduler.lr_scheduler import LinearLR
6+
from mmengine.hooks.ema_hook import EMAHook
7+
from mmdet.models.data_preprocessors import DetDataPreprocessor
8+
from mmdet.models.necks import ChannelMapper
9+
from mmdet.models.losses import L1Loss
10+
from mmdet.models.task_modules import FocalLossCost, HungarianAssigner
11+
from mmdet.models.layers.ema import ExpMomentumEMA
12+
from ai4rs.models.losses import GDLoss
13+
from projects.rotated_dino.rotated_dino.match_cost import ChamferCost, GDCost
14+
from projects.rotated_rtdetr.rotated_rtdetr import (RotatedRTDETR, RTDETRFPN, ResNetV1dPaddle,
15+
RotatedRTDETRHead, RTDETRVarifocalLoss)
16+
17+
with read_base():
18+
from .dotav15_rr import *
19+
from .default_runtime import *
20+
21+
pretrained = ('https://www.modelscope.cn/models/wokaikaixinxin/ai4rs/resolve/'
22+
'master/rtdetr/resnet50vd_ssld_v2_pretrained_d037e232.pth') # noqa
23+
24+
angle_cfg = dict(
25+
width_longer=True,
26+
start_angle=0,
27+
)
28+
angle_factor=3.1415926535897932384626433832795
29+
30+
31+
model = dict(
32+
type=RotatedRTDETR,
33+
num_queries=300, # num_matching_queries, 900 for DINO
34+
with_box_refine=True,
35+
as_two_stage=True,
36+
data_preprocessor=dict(
37+
type=DetDataPreprocessor,
38+
mean=[103.53, 116.28, 123.675],
39+
std=[57.375, 57.12, 58.395],
40+
bgr_to_rgb=False,
41+
boxtype2tensor=False,
42+
batch_augments=None),
43+
backbone=dict(
44+
type=ResNetV1dPaddle, # ResNet for DINO
45+
depth=50,
46+
num_stages=4,
47+
out_indices=(1, 2, 3),
48+
frozen_stages=0, # -1 for DINO
49+
norm_cfg=dict(type='BN', requires_grad=False), # BN for DINO
50+
norm_eval=True,
51+
style='pytorch',
52+
init_cfg=dict(type='Pretrained', checkpoint=pretrained)),
53+
neck=dict(
54+
type=ChannelMapper,
55+
in_channels=[512, 1024, 2048],
56+
kernel_size=1,
57+
out_channels=256,
58+
act_cfg=None,
59+
norm_cfg=dict(type='BN', requires_grad=True), # GN for DINO
60+
num_outs=3, # 4 for DINO
61+
init_cfg=dict(
62+
type='Kaiming',
63+
layer='Conv2d',
64+
a=5**0.5,
65+
distribution='uniform',
66+
mode='fan_in',
67+
nonlinearity='leaky_relu')),
68+
encoder=dict(
69+
use_encoder_idx=[-1],
70+
num_encoder_layers=1,
71+
in_channels=[256, 256, 256],
72+
fpn_cfg=dict(
73+
type=RTDETRFPN,
74+
in_channels=[256, 256, 256],
75+
out_channels=256,
76+
expansion=1.0,
77+
norm_cfg=dict(type='BN', requires_grad=True)),
78+
layer_cfg=dict(
79+
self_attn_cfg=dict(embed_dims=256, num_heads=8, dropout=0.0),
80+
ffn_cfg=dict(
81+
embed_dims=256,
82+
feedforward_channels=1024, # 2048 for DINO
83+
ffn_drop=0.0,
84+
act_cfg=dict(type='GELU')))), # ReLU for DINO
85+
decoder=dict(
86+
num_layers=6,
87+
return_intermediate=True,
88+
angle_factor=angle_factor,
89+
layer_cfg=dict(
90+
self_attn_cfg=dict(embed_dims=256, num_heads=8, dropout=0.0),
91+
cross_attn_cfg=dict(
92+
embed_dims=256,
93+
num_levels=3, # 4 for DINO
94+
dropout=0.0),
95+
ffn_cfg=dict(
96+
embed_dims=256,
97+
feedforward_channels=1024, # 2048 for DINO
98+
ffn_drop=0.0)),
99+
post_norm_cfg=None),
100+
bbox_head=dict(
101+
type=RotatedRTDETRHead,
102+
num_classes=16,
103+
angle_cfg=angle_cfg,
104+
angle_factor=angle_factor,
105+
sync_cls_avg_factor=True,
106+
loss_cls=dict(
107+
type=RTDETRVarifocalLoss,
108+
varifocal_loss_iou_type='hbox_iou', # hbox_iou, rbox_iou, prob_iou
109+
use_sigmoid=True,
110+
alpha=0.75,
111+
gamma=2.0,
112+
iou_weighted=True,
113+
loss_weight=1.0),
114+
loss_bbox=dict(type=L1Loss, loss_weight=5.0),
115+
loss_iou=dict(
116+
type=GDLoss,
117+
loss_type='kld',
118+
fun='log1p',
119+
tau=1,
120+
sqrt=False,
121+
loss_weight=2.0)),
122+
dn_cfg=dict( # TODO: Move to model.train_cfg ?
123+
label_noise_scale=0.5,
124+
box_noise_scale=1.0,
125+
angle_cfg=angle_cfg,
126+
angle_factor=angle_factor,
127+
noise_mode='only_xyxy', # 'only_xyxy', 'only_angle', 'only_xywh', 'all_xyxya'
128+
group_cfg=dict(dynamic=True,
129+
num_groups=None,
130+
num_dn_queries=100)), # TODO: half num_dn_queries
131+
# training and testing settings
132+
train_cfg=dict(
133+
assigner=dict(
134+
type=HungarianAssigner,
135+
match_costs=[
136+
dict(type=FocalLossCost, weight=2.0),
137+
dict(type=ChamferCost, weight=5.0, box_format='xywha'),
138+
dict(
139+
type=GDCost,
140+
loss_type='kld',
141+
fun='log1p',
142+
tau=1,
143+
sqrt=False,
144+
weight=2.0)])),
145+
test_cfg=dict(max_per_img=300))
146+
147+
148+
# optimizer
149+
optim_wrapper = dict(
150+
type=OptimWrapper,
151+
optimizer=dict(type=AdamW, lr=0.0001, weight_decay=0.0001),
152+
clip_grad=dict(max_norm=0.1, norm_type=2),
153+
paramwise_cfg=dict(
154+
custom_keys={'backbone': dict(lr_mult=0.1)},
155+
norm_decay_mult=0,
156+
bypass_duplicate=True))
157+
158+
# learning policy
159+
max_epochs = 72
160+
train_cfg = dict(
161+
type=EpochBasedTrainLoop, max_epochs=max_epochs, val_interval=6)
162+
val_cfg = dict(type=ValLoop)
163+
test_cfg = dict(type=TestLoop)
164+
param_scheduler = [
165+
dict(
166+
type=LinearLR, start_factor=0.001, by_epoch=False, begin=0, end=2000)
167+
]
168+
custom_hooks = [
169+
dict(
170+
type=EMAHook,
171+
ema_type=ExpMomentumEMA,
172+
momentum=0.0001,
173+
update_buffers=True,
174+
priority=49)
175+
]
176+
177+
# NOTE: `auto_scale_lr` is for automatically scaling LR,
178+
# USER SHOULD NOT CHANGE ITS VALUES.
179+
# base_batch_size = (2 GPUs) x (4 samples per GPU)
180+
auto_scale_lr = dict(enable=False, base_batch_size=8)

0 commit comments

Comments
 (0)