Upload 200 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- code/.DS_Store +0 -0
- code/configs/base/dataloader.yml +39 -0
- code/configs/base/deim.yml +48 -0
- code/configs/base/dfine_hgnetv2.yml +90 -0
- code/configs/base/optimizer.yml +35 -0
- code/configs/base/rt_deim.yml +49 -0
- code/configs/base/rt_optimizer.yml +37 -0
- code/configs/base/rtdetrv2_r50vd.yml +90 -0
- code/configs/dataset/coco_detection.yml +41 -0
- code/configs/dataset/crowdhuman_detection.yml +41 -0
- code/configs/dataset/custom_detection.yml +41 -0
- code/configs/dataset/obj365_detection.yml +41 -0
- code/configs/dataset/voc_detection.yml +40 -0
- code/configs/deim_dfine/deim_hgnetv2_l_coco.yml +37 -0
- code/configs/deim_dfine/deim_hgnetv2_m_coco.yml +39 -0
- code/configs/deim_dfine/deim_hgnetv2_n_coco.yml +44 -0
- code/configs/deim_dfine/deim_hgnetv2_s_coco.yml +39 -0
- code/configs/deim_dfine/deim_hgnetv2_x_coco.yml +37 -0
- code/configs/deim_dfine/dfine_hgnetv2_l_coco.yml +44 -0
- code/configs/deim_dfine/dfine_hgnetv2_m_coco.yml +60 -0
- code/configs/deim_dfine/dfine_hgnetv2_n_coco.yml +82 -0
- code/configs/deim_dfine/dfine_hgnetv2_s_coco.yml +61 -0
- code/configs/deim_dfine/dfine_hgnetv2_x_coco.yml +56 -0
- code/configs/deim_dfine/object365/deim_hgnetv2_x_obj2coco_24e.yml +50 -0
- code/configs/deim_dfine/object365/dfine_hgnetv2_x_obj2coco.yml +57 -0
- code/configs/deim_rtdetrv2/deim_r101vd_60e_coco.yml +36 -0
- code/configs/deim_rtdetrv2/deim_r18vd_120e_coco.yml +32 -0
- code/configs/deim_rtdetrv2/deim_r34vd_120e_coco.yml +36 -0
- code/configs/deim_rtdetrv2/deim_r50vd_60e_coco.yml +35 -0
- code/configs/deim_rtdetrv2/deim_r50vd_m_60e_coco.yml +39 -0
- code/configs/deim_rtdetrv2/rtdetrv2_r101vd_6x_coco.yml +40 -0
- code/configs/deim_rtdetrv2/rtdetrv2_r18vd_120e_coco.yml +44 -0
- code/configs/deim_rtdetrv2/rtdetrv2_r34vd_120e_coco.yml +57 -0
- code/configs/deim_rtdetrv2/rtdetrv2_r50vd_6x_coco.yml +25 -0
- code/configs/deim_rtdetrv2/rtdetrv2_r50vd_m_7x_coco.yml +43 -0
- code/configs/runtime.yml +20 -0
- code/engine/__init__.py +16 -0
- code/engine/backbone/__init__.py +20 -0
- code/engine/backbone/common.py +116 -0
- code/engine/backbone/csp_darknet.py +179 -0
- code/engine/backbone/csp_resnet.py +277 -0
- code/engine/backbone/hgnetv2.py +543 -0
- code/engine/backbone/presnet.py +259 -0
- code/engine/backbone/test_resnet.py +80 -0
- code/engine/backbone/timm_model.py +69 -0
- code/engine/backbone/torchvision_model.py +49 -0
- code/engine/backbone/utils.py +54 -0
- code/engine/core/__init__.py +9 -0
- code/engine/core/_config.py +299 -0
- code/engine/core/workspace.py +180 -0
code/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
code/configs/base/dataloader.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
train_dataloader:
|
| 3 |
+
dataset:
|
| 4 |
+
transforms:
|
| 5 |
+
ops:
|
| 6 |
+
- {type: RandomPhotometricDistort, p: 0.5}
|
| 7 |
+
- {type: RandomZoomOut, fill: 0}
|
| 8 |
+
- {type: RandomIoUCrop, p: 0.8}
|
| 9 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 10 |
+
- {type: RandomHorizontalFlip}
|
| 11 |
+
- {type: Resize, size: [640, 640], }
|
| 12 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 13 |
+
- {type: ConvertPILImage, dtype: 'float32', scale: True}
|
| 14 |
+
- {type: ConvertBoxes, fmt: 'cxcywh', normalize: True}
|
| 15 |
+
policy:
|
| 16 |
+
name: stop_epoch
|
| 17 |
+
epoch: 72 # epoch in [71, ~) stop `ops`
|
| 18 |
+
ops: ['Mosaic', 'RandomPhotometricDistort', 'RandomZoomOut', 'RandomIoUCrop']
|
| 19 |
+
|
| 20 |
+
collate_fn:
|
| 21 |
+
type: BatchImageCollateFunction
|
| 22 |
+
base_size: 640
|
| 23 |
+
base_size_repeat: 3
|
| 24 |
+
stop_epoch: 72 # epoch in [72, ~) stop `multiscales`
|
| 25 |
+
|
| 26 |
+
shuffle: True
|
| 27 |
+
total_batch_size: 32 # total batch size equals to 32 (4 * 8)
|
| 28 |
+
num_workers: 4
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
val_dataloader:
|
| 32 |
+
dataset:
|
| 33 |
+
transforms:
|
| 34 |
+
ops:
|
| 35 |
+
- {type: Resize, size: [640, 640], }
|
| 36 |
+
- {type: ConvertPILImage, dtype: 'float32', scale: True}
|
| 37 |
+
shuffle: False
|
| 38 |
+
total_batch_size: 64
|
| 39 |
+
num_workers: 4
|
code/configs/base/deim.yml
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dense O2O
|
| 2 |
+
train_dataloader:
|
| 3 |
+
dataset:
|
| 4 |
+
transforms:
|
| 5 |
+
ops:
|
| 6 |
+
- {type: Mosaic, output_size: 320, rotation_range: 10, translation_range: [0.1, 0.1], scaling_range: [0.5, 1.5],
|
| 7 |
+
probability: 1.0, fill_value: 0, use_cache: False, max_cached_images: 50, random_pop: True}
|
| 8 |
+
- {type: RandomPhotometricDistort, p: 0.5}
|
| 9 |
+
- {type: RandomZoomOut, fill: 0}
|
| 10 |
+
- {type: RandomIoUCrop, p: 0.8}
|
| 11 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 12 |
+
- {type: RandomHorizontalFlip}
|
| 13 |
+
- {type: Resize, size: [640, 640], }
|
| 14 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 15 |
+
- {type: ConvertPILImage, dtype: 'float32', scale: True}
|
| 16 |
+
- {type: ConvertBoxes, fmt: 'cxcywh', normalize: True}
|
| 17 |
+
policy:
|
| 18 |
+
epoch: [4, 29, 50] # list
|
| 19 |
+
ops: ['Mosaic', 'RandomPhotometricDistort', 'RandomZoomOut', 'RandomIoUCrop']
|
| 20 |
+
mosaic_prob: 0.5
|
| 21 |
+
|
| 22 |
+
collate_fn:
|
| 23 |
+
mixup_prob: 0.5
|
| 24 |
+
mixup_epochs: [4, 29]
|
| 25 |
+
stop_epoch: 50 # epoch in [72, ~) stop `multiscales`
|
| 26 |
+
|
| 27 |
+
# Unfreezing BN
|
| 28 |
+
HGNetv2:
|
| 29 |
+
freeze_at: -1 # 0 default
|
| 30 |
+
freeze_norm: False # True default
|
| 31 |
+
|
| 32 |
+
# Activation
|
| 33 |
+
DFINETransformer:
|
| 34 |
+
activation: silu
|
| 35 |
+
mlp_act: silu
|
| 36 |
+
|
| 37 |
+
## Our LR-Scheduler
|
| 38 |
+
lrsheduler: flatcosine
|
| 39 |
+
lr_gamma: 0.5
|
| 40 |
+
warmup_iter: 2000
|
| 41 |
+
flat_epoch: 29 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 42 |
+
no_aug_epoch: 8
|
| 43 |
+
|
| 44 |
+
## Our Loss
|
| 45 |
+
DEIMCriterion:
|
| 46 |
+
weight_dict: {loss_mal: 1, loss_bbox: 5, loss_giou: 2, loss_fgl: 0.15, loss_ddf: 1.5}
|
| 47 |
+
losses: ['mal', 'boxes', 'local']
|
| 48 |
+
gamma: 1.5
|
code/configs/base/dfine_hgnetv2.yml
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
model: DEIM
|
| 4 |
+
criterion: DEIMCriterion
|
| 5 |
+
postprocessor: PostProcessor
|
| 6 |
+
|
| 7 |
+
use_focal_loss: True
|
| 8 |
+
eval_spatial_size: [640, 640] # h w
|
| 9 |
+
checkpoint_freq: 4 # save freq
|
| 10 |
+
|
| 11 |
+
DEIM:
|
| 12 |
+
backbone: HGNetv2
|
| 13 |
+
encoder: HybridEncoder
|
| 14 |
+
decoder: DFINETransformer
|
| 15 |
+
|
| 16 |
+
# Add, default for step lr scheduler
|
| 17 |
+
lrsheduler: flatcosine
|
| 18 |
+
lr_gamma: 1
|
| 19 |
+
warmup_iter: 500
|
| 20 |
+
flat_epoch: 4000000
|
| 21 |
+
no_aug_epoch: 0
|
| 22 |
+
|
| 23 |
+
HGNetv2:
|
| 24 |
+
pretrained: True
|
| 25 |
+
local_model_dir: ../RT-DETR-main/D-FINE/weight/hgnetv2/
|
| 26 |
+
|
| 27 |
+
HybridEncoder:
|
| 28 |
+
in_channels: [512, 1024, 2048]
|
| 29 |
+
feat_strides: [8, 16, 32]
|
| 30 |
+
|
| 31 |
+
# intra
|
| 32 |
+
hidden_dim: 256
|
| 33 |
+
use_encoder_idx: [2]
|
| 34 |
+
num_encoder_layers: 1
|
| 35 |
+
nhead: 8
|
| 36 |
+
dim_feedforward: 1024
|
| 37 |
+
dropout: 0.
|
| 38 |
+
enc_act: 'gelu'
|
| 39 |
+
|
| 40 |
+
# cross
|
| 41 |
+
expansion: 1.0
|
| 42 |
+
depth_mult: 1
|
| 43 |
+
act: 'silu'
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
DFINETransformer:
|
| 47 |
+
feat_channels: [256, 256, 256]
|
| 48 |
+
feat_strides: [8, 16, 32]
|
| 49 |
+
hidden_dim: 256
|
| 50 |
+
num_levels: 3
|
| 51 |
+
|
| 52 |
+
num_layers: 6
|
| 53 |
+
eval_idx: -1
|
| 54 |
+
num_queries: 300
|
| 55 |
+
|
| 56 |
+
num_denoising: 100
|
| 57 |
+
label_noise_ratio: 0.5
|
| 58 |
+
box_noise_scale: 1.0
|
| 59 |
+
|
| 60 |
+
# NEW
|
| 61 |
+
reg_max: 32
|
| 62 |
+
reg_scale: 4
|
| 63 |
+
|
| 64 |
+
# Auxiliary decoder layers dimension scaling
|
| 65 |
+
# "eg. If num_layers: 6 eval_idx: -4,
|
| 66 |
+
# then layer 3, 4, 5 are auxiliary decoder layers."
|
| 67 |
+
layer_scale: 1 # 2
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
num_points: [3, 6, 3] # [4, 4, 4] [3, 6, 3]
|
| 71 |
+
cross_attn_method: default # default, discrete
|
| 72 |
+
query_select_method: default # default, agnostic
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
PostProcessor:
|
| 76 |
+
num_top_queries: 300
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
DEIMCriterion:
|
| 80 |
+
weight_dict: {loss_vfl: 1, loss_bbox: 5, loss_giou: 2, loss_fgl: 0.15, loss_ddf: 1.5}
|
| 81 |
+
losses: ['vfl', 'boxes', 'local']
|
| 82 |
+
alpha: 0.75
|
| 83 |
+
gamma: 2.0
|
| 84 |
+
reg_max: 32
|
| 85 |
+
|
| 86 |
+
matcher:
|
| 87 |
+
type: HungarianMatcher
|
| 88 |
+
weight_dict: {cost_class: 2, cost_bbox: 5, cost_giou: 2}
|
| 89 |
+
alpha: 0.25
|
| 90 |
+
gamma: 2.0
|
code/configs/base/optimizer.yml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
use_amp: True
|
| 2 |
+
use_ema: True
|
| 3 |
+
ema:
|
| 4 |
+
type: ModelEMA
|
| 5 |
+
decay: 0.9999
|
| 6 |
+
warmups: 1000
|
| 7 |
+
start: 0
|
| 8 |
+
|
| 9 |
+
epoches: 72
|
| 10 |
+
clip_max_norm: 0.1
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
optimizer:
|
| 14 |
+
type: AdamW
|
| 15 |
+
params:
|
| 16 |
+
-
|
| 17 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 18 |
+
lr: 0.0000125
|
| 19 |
+
-
|
| 20 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 21 |
+
weight_decay: 0.
|
| 22 |
+
|
| 23 |
+
lr: 0.00025
|
| 24 |
+
betas: [0.9, 0.999]
|
| 25 |
+
weight_decay: 0.000125
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
lr_scheduler:
|
| 29 |
+
type: MultiStepLR
|
| 30 |
+
milestones: [500]
|
| 31 |
+
gamma: 0.1
|
| 32 |
+
|
| 33 |
+
lr_warmup_scheduler:
|
| 34 |
+
type: LinearWarmup
|
| 35 |
+
warmup_duration: 500
|
code/configs/base/rt_deim.yml
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dense O2O
|
| 2 |
+
train_dataloader:
|
| 3 |
+
dataset:
|
| 4 |
+
transforms:
|
| 5 |
+
ops:
|
| 6 |
+
- {type: Mosaic, output_size: 320, rotation_range: 10, translation_range: [0.1, 0.1], scaling_range: [0.5, 1.5],
|
| 7 |
+
probability: 1.0, fill_value: 0, use_cache: False, max_cached_images: 50, random_pop: True}
|
| 8 |
+
- {type: RandomPhotometricDistort, p: 0.5}
|
| 9 |
+
- {type: RandomZoomOut, fill: 0}
|
| 10 |
+
- {type: RandomIoUCrop, p: 0.8}
|
| 11 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 12 |
+
- {type: RandomHorizontalFlip}
|
| 13 |
+
- {type: Resize, size: [640, 640], }
|
| 14 |
+
- {type: SanitizeBoundingBoxes, min_size: 1}
|
| 15 |
+
- {type: ConvertPILImage, dtype: 'float32', scale: True}
|
| 16 |
+
- {type: ConvertBoxes, fmt: 'cxcywh', normalize: True}
|
| 17 |
+
policy:
|
| 18 |
+
epoch: [4, 29, 50] # list
|
| 19 |
+
ops: ['Mosaic', 'RandomPhotometricDistort', 'RandomZoomOut', 'RandomIoUCrop']
|
| 20 |
+
mosaic_prob: 0.5
|
| 21 |
+
|
| 22 |
+
collate_fn:
|
| 23 |
+
mixup_prob: 0.5
|
| 24 |
+
mixup_epochs: [4, 29]
|
| 25 |
+
stop_epoch: 50 # epoch in [72, ~) stop `multiscales`
|
| 26 |
+
|
| 27 |
+
# Unfreezing BN
|
| 28 |
+
PResNet:
|
| 29 |
+
freeze_at: -1 # default 0
|
| 30 |
+
freeze_norm: False # default True
|
| 31 |
+
|
| 32 |
+
# Activation
|
| 33 |
+
RTDETRTransformerv2:
|
| 34 |
+
query_pos_method: as_reg
|
| 35 |
+
activation: silu
|
| 36 |
+
mlp_act: silu
|
| 37 |
+
|
| 38 |
+
## Our LR-Scheduler
|
| 39 |
+
lrsheduler: flatcosine
|
| 40 |
+
lr_gamma: 0.5
|
| 41 |
+
warmup_iter: 2000
|
| 42 |
+
flat_epoch: 29 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 43 |
+
no_aug_epoch: 8
|
| 44 |
+
|
| 45 |
+
## Our Loss
|
| 46 |
+
DEIMCriterion:
|
| 47 |
+
weight_dict: {loss_mal: 1, loss_bbox: 5, loss_giou: 2}
|
| 48 |
+
losses: ['mal', 'boxes', ]
|
| 49 |
+
gamma: 1.5
|
code/configs/base/rt_optimizer.yml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
use_amp: True
|
| 2 |
+
use_ema: True
|
| 3 |
+
ema:
|
| 4 |
+
type: ModelEMA
|
| 5 |
+
decay: 0.9999
|
| 6 |
+
warmups: 2000
|
| 7 |
+
start: 0
|
| 8 |
+
|
| 9 |
+
epoches: 72
|
| 10 |
+
clip_max_norm: 0.1
|
| 11 |
+
|
| 12 |
+
train_dataloader:
|
| 13 |
+
total_batch_size: 16
|
| 14 |
+
|
| 15 |
+
optimizer:
|
| 16 |
+
type: AdamW
|
| 17 |
+
params:
|
| 18 |
+
-
|
| 19 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 20 |
+
lr: 0.00001
|
| 21 |
+
-
|
| 22 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 23 |
+
weight_decay: 0.
|
| 24 |
+
|
| 25 |
+
lr: 0.0001
|
| 26 |
+
betas: [0.9, 0.999]
|
| 27 |
+
weight_decay: 0.0001
|
| 28 |
+
|
| 29 |
+
lr_scheduler:
|
| 30 |
+
type: MultiStepLR
|
| 31 |
+
milestones: [1000]
|
| 32 |
+
gamma: 0.1
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
lr_warmup_scheduler:
|
| 36 |
+
type: LinearWarmup
|
| 37 |
+
warmup_duration: 2000
|
code/configs/base/rtdetrv2_r50vd.yml
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
model: DEIM
|
| 4 |
+
criterion: DEIMCriterion
|
| 5 |
+
postprocessor: PostProcessor
|
| 6 |
+
|
| 7 |
+
use_focal_loss: True
|
| 8 |
+
eval_spatial_size: [640, 640] # h w
|
| 9 |
+
checkpoint_freq: 4 # save freq
|
| 10 |
+
|
| 11 |
+
DEIM:
|
| 12 |
+
backbone: PResNet
|
| 13 |
+
encoder: HybridEncoder
|
| 14 |
+
decoder: RTDETRTransformerv2
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# Add, default for step lr scheduler
|
| 18 |
+
lrsheduler: flatcosine
|
| 19 |
+
lr_gamma: 1
|
| 20 |
+
warmup_iter: 2000
|
| 21 |
+
flat_epoch: 4000000
|
| 22 |
+
no_aug_epoch: 0
|
| 23 |
+
|
| 24 |
+
PResNet:
|
| 25 |
+
depth: 50
|
| 26 |
+
variant: d
|
| 27 |
+
freeze_at: 0
|
| 28 |
+
return_idx: [1, 2, 3]
|
| 29 |
+
num_stages: 4
|
| 30 |
+
freeze_norm: True
|
| 31 |
+
pretrained: True
|
| 32 |
+
local_model_dir: ../RT-DETR-main/rtdetrv2_pytorch/INK1k/
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
HybridEncoder:
|
| 36 |
+
in_channels: [512, 1024, 2048]
|
| 37 |
+
feat_strides: [8, 16, 32]
|
| 38 |
+
|
| 39 |
+
# intra
|
| 40 |
+
hidden_dim: 256
|
| 41 |
+
use_encoder_idx: [2]
|
| 42 |
+
num_encoder_layers: 1
|
| 43 |
+
nhead: 8
|
| 44 |
+
dim_feedforward: 1024
|
| 45 |
+
dropout: 0.
|
| 46 |
+
enc_act: 'gelu'
|
| 47 |
+
|
| 48 |
+
# cross
|
| 49 |
+
expansion: 1.0
|
| 50 |
+
depth_mult: 1
|
| 51 |
+
act: 'silu'
|
| 52 |
+
version: rt_detrv2 # pay attention to this
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
RTDETRTransformerv2:
|
| 56 |
+
feat_channels: [256, 256, 256]
|
| 57 |
+
feat_strides: [8, 16, 32]
|
| 58 |
+
hidden_dim: 256
|
| 59 |
+
num_levels: 3
|
| 60 |
+
|
| 61 |
+
num_layers: 6
|
| 62 |
+
num_queries: 300
|
| 63 |
+
|
| 64 |
+
num_denoising: 100
|
| 65 |
+
label_noise_ratio: 0.5
|
| 66 |
+
box_noise_scale: 1.0 # 1.0 0.4
|
| 67 |
+
|
| 68 |
+
eval_idx: -1
|
| 69 |
+
|
| 70 |
+
# NEW, can be chosen
|
| 71 |
+
num_points: [4, 4, 4] # [3,3,3] [2,2,2]
|
| 72 |
+
cross_attn_method: default # default, discrete
|
| 73 |
+
query_select_method: default # default, agnostic
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
PostProcessor:
|
| 77 |
+
num_top_queries: 300
|
| 78 |
+
|
| 79 |
+
DEIMCriterion:
|
| 80 |
+
weight_dict: {loss_vfl: 1, loss_bbox: 5, loss_giou: 2,}
|
| 81 |
+
losses: ['vfl', 'boxes', ]
|
| 82 |
+
alpha: 0.75
|
| 83 |
+
gamma: 2.0
|
| 84 |
+
use_uni_set: False
|
| 85 |
+
|
| 86 |
+
matcher:
|
| 87 |
+
type: HungarianMatcher
|
| 88 |
+
weight_dict: {cost_class: 2, cost_bbox: 5, cost_giou: 2}
|
| 89 |
+
alpha: 0.25
|
| 90 |
+
gamma: 2.0
|
code/configs/dataset/coco_detection.yml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
evaluator:
|
| 4 |
+
type: CocoEvaluator
|
| 5 |
+
iou_types: ['bbox', ]
|
| 6 |
+
|
| 7 |
+
num_classes: 80
|
| 8 |
+
remap_mscoco_category: True
|
| 9 |
+
|
| 10 |
+
train_dataloader:
|
| 11 |
+
type: DataLoader
|
| 12 |
+
dataset:
|
| 13 |
+
type: CocoDetection
|
| 14 |
+
img_folder: /datassd/COCO/train2017/
|
| 15 |
+
ann_file: /datassd/COCO/annotations/instances_train2017.json
|
| 16 |
+
return_masks: False
|
| 17 |
+
transforms:
|
| 18 |
+
type: Compose
|
| 19 |
+
ops: ~
|
| 20 |
+
shuffle: True
|
| 21 |
+
num_workers: 4
|
| 22 |
+
drop_last: True
|
| 23 |
+
collate_fn:
|
| 24 |
+
type: BatchImageCollateFunction
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
val_dataloader:
|
| 28 |
+
type: DataLoader
|
| 29 |
+
dataset:
|
| 30 |
+
type: CocoDetection
|
| 31 |
+
img_folder: /datassd/COCO/val2017/
|
| 32 |
+
ann_file: /datassd/COCO/annotations/instances_val2017.json
|
| 33 |
+
return_masks: False
|
| 34 |
+
transforms:
|
| 35 |
+
type: Compose
|
| 36 |
+
ops: ~
|
| 37 |
+
shuffle: False
|
| 38 |
+
num_workers: 4
|
| 39 |
+
drop_last: False
|
| 40 |
+
collate_fn:
|
| 41 |
+
type: BatchImageCollateFunction
|
code/configs/dataset/crowdhuman_detection.yml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
evaluator:
|
| 4 |
+
type: CocoEvaluator
|
| 5 |
+
iou_types: ['bbox', ]
|
| 6 |
+
|
| 7 |
+
num_classes: 2 # your dataset classes
|
| 8 |
+
remap_mscoco_category: False
|
| 9 |
+
|
| 10 |
+
train_dataloader:
|
| 11 |
+
type: DataLoader
|
| 12 |
+
dataset:
|
| 13 |
+
type: CocoDetection
|
| 14 |
+
img_folder: /datassd/coco/crowd_human_coco/CrowdHuman_train
|
| 15 |
+
ann_file: /datassd/coco/crowd_human_coco/Chuman-train.json
|
| 16 |
+
return_masks: False
|
| 17 |
+
transforms:
|
| 18 |
+
type: Compose
|
| 19 |
+
ops: ~
|
| 20 |
+
shuffle: True
|
| 21 |
+
num_workers: 4
|
| 22 |
+
drop_last: True
|
| 23 |
+
collate_fn:
|
| 24 |
+
type: BatchImageCollateFunction
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
val_dataloader:
|
| 28 |
+
type: DataLoader
|
| 29 |
+
dataset:
|
| 30 |
+
type: CocoDetection
|
| 31 |
+
img_folder: /datassd/coco/crowd_human_coco/CrowdHuman_val
|
| 32 |
+
ann_file: /datassd/coco/crowd_human_coco/Chuman-val.json
|
| 33 |
+
return_masks: False
|
| 34 |
+
transforms:
|
| 35 |
+
type: Compose
|
| 36 |
+
ops: ~
|
| 37 |
+
shuffle: False
|
| 38 |
+
num_workers: 4
|
| 39 |
+
drop_last: False
|
| 40 |
+
collate_fn:
|
| 41 |
+
type: BatchImageCollateFunction
|
code/configs/dataset/custom_detection.yml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
evaluator:
|
| 4 |
+
type: CocoEvaluator
|
| 5 |
+
iou_types: ['bbox', ]
|
| 6 |
+
|
| 7 |
+
num_classes: 777 # your dataset classes
|
| 8 |
+
remap_mscoco_category: False
|
| 9 |
+
|
| 10 |
+
train_dataloader:
|
| 11 |
+
type: DataLoader
|
| 12 |
+
dataset:
|
| 13 |
+
type: CocoDetection
|
| 14 |
+
img_folder: /data/yourdataset/train
|
| 15 |
+
ann_file: /data/yourdataset/train/train.json
|
| 16 |
+
return_masks: False
|
| 17 |
+
transforms:
|
| 18 |
+
type: Compose
|
| 19 |
+
ops: ~
|
| 20 |
+
shuffle: True
|
| 21 |
+
num_workers: 4
|
| 22 |
+
drop_last: True
|
| 23 |
+
collate_fn:
|
| 24 |
+
type: BatchImageCollateFunction
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
val_dataloader:
|
| 28 |
+
type: DataLoader
|
| 29 |
+
dataset:
|
| 30 |
+
type: CocoDetection
|
| 31 |
+
img_folder: /data/yourdataset/val
|
| 32 |
+
ann_file: /data/yourdataset/val/val.json
|
| 33 |
+
return_masks: False
|
| 34 |
+
transforms:
|
| 35 |
+
type: Compose
|
| 36 |
+
ops: ~
|
| 37 |
+
shuffle: False
|
| 38 |
+
num_workers: 4
|
| 39 |
+
drop_last: False
|
| 40 |
+
collate_fn:
|
| 41 |
+
type: BatchImageCollateFunction
|
code/configs/dataset/obj365_detection.yml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
evaluator:
|
| 4 |
+
type: CocoEvaluator
|
| 5 |
+
iou_types: ['bbox', ]
|
| 6 |
+
|
| 7 |
+
num_classes: 366
|
| 8 |
+
remap_mscoco_category: False
|
| 9 |
+
|
| 10 |
+
train_dataloader:
|
| 11 |
+
type: DataLoader
|
| 12 |
+
dataset:
|
| 13 |
+
type: CocoDetection
|
| 14 |
+
img_folder: /home/Dataset/objects365/train
|
| 15 |
+
ann_file: /home/Dataset/objects365/train/new_zhiyuan_objv2_train_resized640.json
|
| 16 |
+
return_masks: False
|
| 17 |
+
transforms:
|
| 18 |
+
type: Compose
|
| 19 |
+
ops: ~
|
| 20 |
+
shuffle: True
|
| 21 |
+
num_workers: 4
|
| 22 |
+
drop_last: True
|
| 23 |
+
collate_fn:
|
| 24 |
+
type: BatchImageCollateFunction
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
val_dataloader:
|
| 28 |
+
type: DataLoader
|
| 29 |
+
dataset:
|
| 30 |
+
type: CocoDetection
|
| 31 |
+
img_folder: /home/Dataset/objects365/val
|
| 32 |
+
ann_file: /home/Dataset/objects365/val/new_zhiyuan_objv2_val_resized640.json
|
| 33 |
+
return_masks: False
|
| 34 |
+
transforms:
|
| 35 |
+
type: Compose
|
| 36 |
+
ops: ~
|
| 37 |
+
shuffle: False
|
| 38 |
+
num_workers: 4
|
| 39 |
+
drop_last: False
|
| 40 |
+
collate_fn:
|
| 41 |
+
type: BatchImageCollateFunction
|
code/configs/dataset/voc_detection.yml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
task: detection
|
| 2 |
+
|
| 3 |
+
evaluator:
|
| 4 |
+
type: CocoEvaluator
|
| 5 |
+
iou_types: ['bbox', ]
|
| 6 |
+
|
| 7 |
+
num_classes: 20
|
| 8 |
+
|
| 9 |
+
train_dataloader:
|
| 10 |
+
type: DataLoader
|
| 11 |
+
dataset:
|
| 12 |
+
type: VOCDetection
|
| 13 |
+
root: ./dataset/voc/
|
| 14 |
+
ann_file: trainval.txt
|
| 15 |
+
label_file: label_list.txt
|
| 16 |
+
transforms:
|
| 17 |
+
type: Compose
|
| 18 |
+
ops: ~
|
| 19 |
+
shuffle: True
|
| 20 |
+
num_workers: 4
|
| 21 |
+
drop_last: True
|
| 22 |
+
collate_fn:
|
| 23 |
+
type: BatchImageCollateFunction
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
val_dataloader:
|
| 27 |
+
type: DataLoader
|
| 28 |
+
dataset:
|
| 29 |
+
type: VOCDetection
|
| 30 |
+
root: ./dataset/voc/
|
| 31 |
+
ann_file: test.txt
|
| 32 |
+
label_file: label_list.txt
|
| 33 |
+
transforms:
|
| 34 |
+
type: Compose
|
| 35 |
+
ops: ~
|
| 36 |
+
shuffle: False
|
| 37 |
+
num_workers: 4
|
| 38 |
+
drop_last: False
|
| 39 |
+
collate_fn:
|
| 40 |
+
type: BatchImageCollateFunction
|
code/configs/deim_dfine/deim_hgnetv2_l_coco.yml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_l_coco.yml',
|
| 3 |
+
'../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_hgnetv2_l_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 13 |
+
lr: 0.000025
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0005
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.000125
|
| 21 |
+
|
| 22 |
+
# Increase to search for the optimal ema
|
| 23 |
+
epoches: 58 # 72 + 2n
|
| 24 |
+
|
| 25 |
+
## Our LR-Scheduler
|
| 26 |
+
flat_epoch: 29 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 27 |
+
no_aug_epoch: 8
|
| 28 |
+
|
| 29 |
+
train_dataloader:
|
| 30 |
+
dataset:
|
| 31 |
+
transforms:
|
| 32 |
+
policy:
|
| 33 |
+
epoch: [4, 29, 50] # list
|
| 34 |
+
|
| 35 |
+
collate_fn:
|
| 36 |
+
mixup_epochs: [4, 29]
|
| 37 |
+
stop_epoch: 50
|
code/configs/deim_dfine/deim_hgnetv2_m_coco.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_m_coco.yml',
|
| 3 |
+
'../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_hgnetv2_m_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*bn).*$'
|
| 13 |
+
lr: 0.00004
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0004
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.0001
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# Increase to search for the optimal ema
|
| 24 |
+
epoches: 102 # 120 + 4n
|
| 25 |
+
|
| 26 |
+
## Our LR-Scheduler
|
| 27 |
+
flat_epoch: 49 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 28 |
+
no_aug_epoch: 12
|
| 29 |
+
|
| 30 |
+
## Our DataAug
|
| 31 |
+
train_dataloader:
|
| 32 |
+
dataset:
|
| 33 |
+
transforms:
|
| 34 |
+
policy:
|
| 35 |
+
epoch: [4, 49, 90] # list
|
| 36 |
+
|
| 37 |
+
collate_fn:
|
| 38 |
+
mixup_epochs: [4, 49]
|
| 39 |
+
stop_epoch: 90
|
code/configs/deim_dfine/deim_hgnetv2_n_coco.yml
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_n_coco.yml',
|
| 3 |
+
'../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./deim_outputs/deim_hgnetv2_n_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 13 |
+
lr: 0.0004
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*backbone)(?=.*norm|bn).*$'
|
| 16 |
+
lr: 0.0004
|
| 17 |
+
weight_decay: 0.
|
| 18 |
+
-
|
| 19 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn|bias)).*$'
|
| 20 |
+
weight_decay: 0.
|
| 21 |
+
|
| 22 |
+
lr: 0.0008
|
| 23 |
+
betas: [0.9, 0.999]
|
| 24 |
+
weight_decay: 0.0001
|
| 25 |
+
|
| 26 |
+
# Increase to search for the optimal ema
|
| 27 |
+
epoches: 160 # 148 + 12
|
| 28 |
+
|
| 29 |
+
## Our LR-Scheduler
|
| 30 |
+
flat_epoch: 7800 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 31 |
+
no_aug_epoch: 12
|
| 32 |
+
lr_gamma: 1.0
|
| 33 |
+
|
| 34 |
+
## Our DataAug
|
| 35 |
+
train_dataloader:
|
| 36 |
+
dataset:
|
| 37 |
+
transforms:
|
| 38 |
+
policy:
|
| 39 |
+
epoch: [4, 78, 148] # list
|
| 40 |
+
|
| 41 |
+
collate_fn:
|
| 42 |
+
mixup_epochs: [4, 78]
|
| 43 |
+
stop_epoch: 148
|
| 44 |
+
base_size_repeat: ~
|
code/configs/deim_dfine/deim_hgnetv2_s_coco.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_s_coco.yml',
|
| 3 |
+
'../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_hgnetv2_s_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*bn).*$'
|
| 13 |
+
lr: 0.0002
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:norm|bn)).*$' # except bias
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0004
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.0001
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# Increase to search for the optimal ema
|
| 24 |
+
epoches: 132 # 120 + 4n
|
| 25 |
+
|
| 26 |
+
## Our LR-Scheduler
|
| 27 |
+
flat_epoch: 64 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 28 |
+
no_aug_epoch: 12
|
| 29 |
+
|
| 30 |
+
## Our DataAug
|
| 31 |
+
train_dataloader:
|
| 32 |
+
dataset:
|
| 33 |
+
transforms:
|
| 34 |
+
policy:
|
| 35 |
+
epoch: [4, 64, 120] # list
|
| 36 |
+
|
| 37 |
+
collate_fn:
|
| 38 |
+
mixup_epochs: [4, 64]
|
| 39 |
+
stop_epoch: 120
|
code/configs/deim_dfine/deim_hgnetv2_x_coco.yml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_x_coco.yml',
|
| 3 |
+
'../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_hgnetv2_x_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 13 |
+
lr: 0.000005
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0005
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.000125
|
| 21 |
+
|
| 22 |
+
# Increase to search for the optimal ema
|
| 23 |
+
epoches: 58 # 72 + 2n
|
| 24 |
+
|
| 25 |
+
## Our LR-Scheduler
|
| 26 |
+
flat_epoch: 29 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 27 |
+
no_aug_epoch: 8
|
| 28 |
+
|
| 29 |
+
train_dataloader:
|
| 30 |
+
dataset:
|
| 31 |
+
transforms:
|
| 32 |
+
policy:
|
| 33 |
+
epoch: [4, 29, 50] # list
|
| 34 |
+
|
| 35 |
+
collate_fn:
|
| 36 |
+
mixup_epochs: [4, 29]
|
| 37 |
+
stop_epoch: 50
|
code/configs/deim_dfine/dfine_hgnetv2_l_coco.yml
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/optimizer.yml',
|
| 6 |
+
'../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./outputs/dfine_hgnetv2_l_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
HGNetv2:
|
| 13 |
+
name: 'B4'
|
| 14 |
+
return_idx: [1, 2, 3]
|
| 15 |
+
freeze_stem_only: True
|
| 16 |
+
freeze_at: 0
|
| 17 |
+
freeze_norm: True
|
| 18 |
+
|
| 19 |
+
optimizer:
|
| 20 |
+
type: AdamW
|
| 21 |
+
params:
|
| 22 |
+
-
|
| 23 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 24 |
+
lr: 0.0000125
|
| 25 |
+
-
|
| 26 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 27 |
+
weight_decay: 0.
|
| 28 |
+
|
| 29 |
+
lr: 0.00025
|
| 30 |
+
betas: [0.9, 0.999]
|
| 31 |
+
weight_decay: 0.000125
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
# Increase to search for the optimal ema
|
| 35 |
+
epoches: 80 # 72 + 2n
|
| 36 |
+
train_dataloader:
|
| 37 |
+
dataset:
|
| 38 |
+
transforms:
|
| 39 |
+
policy:
|
| 40 |
+
epoch: 72
|
| 41 |
+
collate_fn:
|
| 42 |
+
stop_epoch: 72
|
| 43 |
+
ema_restart_decay: 0.9999
|
| 44 |
+
base_size_repeat: 4
|
code/configs/deim_dfine/dfine_hgnetv2_m_coco.yml
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/optimizer.yml',
|
| 6 |
+
'../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./output/dfine_hgnetv2_m_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
DEIM:
|
| 13 |
+
backbone: HGNetv2
|
| 14 |
+
|
| 15 |
+
HGNetv2:
|
| 16 |
+
name: 'B2'
|
| 17 |
+
return_idx: [1, 2, 3]
|
| 18 |
+
freeze_at: -1
|
| 19 |
+
freeze_norm: False
|
| 20 |
+
use_lab: True
|
| 21 |
+
|
| 22 |
+
DFINETransformer:
|
| 23 |
+
num_layers: 4 # 5 6
|
| 24 |
+
eval_idx: -1 # -2 -3
|
| 25 |
+
|
| 26 |
+
HybridEncoder:
|
| 27 |
+
in_channels: [384, 768, 1536]
|
| 28 |
+
hidden_dim: 256
|
| 29 |
+
depth_mult: 0.67
|
| 30 |
+
|
| 31 |
+
optimizer:
|
| 32 |
+
type: AdamW
|
| 33 |
+
params:
|
| 34 |
+
-
|
| 35 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 36 |
+
lr: 0.00002
|
| 37 |
+
-
|
| 38 |
+
params: '^(?=.*backbone)(?=.*norm|bn).*$'
|
| 39 |
+
lr: 0.00002
|
| 40 |
+
weight_decay: 0.
|
| 41 |
+
-
|
| 42 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn|bias)).*$'
|
| 43 |
+
weight_decay: 0.
|
| 44 |
+
|
| 45 |
+
lr: 0.0002
|
| 46 |
+
betas: [0.9, 0.999]
|
| 47 |
+
weight_decay: 0.0001
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# Increase to search for the optimal ema
|
| 51 |
+
epoches: 132 # 120 + 4n
|
| 52 |
+
train_dataloader:
|
| 53 |
+
dataset:
|
| 54 |
+
transforms:
|
| 55 |
+
policy:
|
| 56 |
+
epoch: 120
|
| 57 |
+
collate_fn:
|
| 58 |
+
stop_epoch: 120
|
| 59 |
+
ema_restart_decay: 0.9999
|
| 60 |
+
base_size_repeat: 6
|
code/configs/deim_dfine/dfine_hgnetv2_n_coco.yml
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/optimizer.yml',
|
| 6 |
+
'../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./output/dfine_hgnetv2_n_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
DEIM:
|
| 13 |
+
backbone: HGNetv2
|
| 14 |
+
|
| 15 |
+
HGNetv2:
|
| 16 |
+
name: 'B0'
|
| 17 |
+
return_idx: [2, 3]
|
| 18 |
+
freeze_at: -1
|
| 19 |
+
freeze_norm: False
|
| 20 |
+
use_lab: True
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
HybridEncoder:
|
| 24 |
+
in_channels: [512, 1024]
|
| 25 |
+
feat_strides: [16, 32]
|
| 26 |
+
|
| 27 |
+
# intra
|
| 28 |
+
hidden_dim: 128
|
| 29 |
+
use_encoder_idx: [1]
|
| 30 |
+
dim_feedforward: 512
|
| 31 |
+
|
| 32 |
+
# cross
|
| 33 |
+
expansion: 0.34
|
| 34 |
+
depth_mult: 0.5
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
DFINETransformer:
|
| 38 |
+
feat_channels: [128, 128]
|
| 39 |
+
feat_strides: [16, 32]
|
| 40 |
+
hidden_dim: 128
|
| 41 |
+
dim_feedforward: 512
|
| 42 |
+
num_levels: 2
|
| 43 |
+
|
| 44 |
+
num_layers: 3
|
| 45 |
+
eval_idx: -1
|
| 46 |
+
|
| 47 |
+
num_points: [6, 6]
|
| 48 |
+
|
| 49 |
+
optimizer:
|
| 50 |
+
type: AdamW
|
| 51 |
+
params:
|
| 52 |
+
-
|
| 53 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 54 |
+
lr: 0.0004
|
| 55 |
+
-
|
| 56 |
+
params: '^(?=.*backbone)(?=.*norm|bn).*$'
|
| 57 |
+
lr: 0.0004
|
| 58 |
+
weight_decay: 0.
|
| 59 |
+
-
|
| 60 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn|bias)).*$'
|
| 61 |
+
weight_decay: 0.
|
| 62 |
+
|
| 63 |
+
lr: 0.0008
|
| 64 |
+
betas: [0.9, 0.999]
|
| 65 |
+
weight_decay: 0.0001
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
# Increase to search for the optimal ema
|
| 69 |
+
epoches: 160 # 148 + 4n
|
| 70 |
+
train_dataloader:
|
| 71 |
+
total_batch_size: 128
|
| 72 |
+
dataset:
|
| 73 |
+
transforms:
|
| 74 |
+
policy:
|
| 75 |
+
epoch: 148
|
| 76 |
+
collate_fn:
|
| 77 |
+
stop_epoch: 148
|
| 78 |
+
ema_restart_decay: 0.9999
|
| 79 |
+
base_size_repeat: ~
|
| 80 |
+
|
| 81 |
+
val_dataloader:
|
| 82 |
+
total_batch_size: 256
|
code/configs/deim_dfine/dfine_hgnetv2_s_coco.yml
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/optimizer.yml',
|
| 6 |
+
'../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./output/dfine_hgnetv2_s_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
DEIM:
|
| 13 |
+
backbone: HGNetv2
|
| 14 |
+
|
| 15 |
+
HGNetv2:
|
| 16 |
+
name: 'B0'
|
| 17 |
+
return_idx: [1, 2, 3]
|
| 18 |
+
freeze_at: -1
|
| 19 |
+
freeze_norm: False
|
| 20 |
+
use_lab: True
|
| 21 |
+
|
| 22 |
+
DFINETransformer:
|
| 23 |
+
num_layers: 3 # 4 5 6
|
| 24 |
+
eval_idx: -1 # -2 -3 -4
|
| 25 |
+
|
| 26 |
+
HybridEncoder:
|
| 27 |
+
in_channels: [256, 512, 1024]
|
| 28 |
+
hidden_dim: 256
|
| 29 |
+
depth_mult: 0.34
|
| 30 |
+
expansion: 0.5
|
| 31 |
+
|
| 32 |
+
optimizer:
|
| 33 |
+
type: AdamW
|
| 34 |
+
params:
|
| 35 |
+
-
|
| 36 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 37 |
+
lr: 0.0001
|
| 38 |
+
-
|
| 39 |
+
params: '^(?=.*backbone)(?=.*norm|bn).*$'
|
| 40 |
+
lr: 0.0001
|
| 41 |
+
weight_decay: 0.
|
| 42 |
+
-
|
| 43 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn|bias)).*$'
|
| 44 |
+
weight_decay: 0.
|
| 45 |
+
|
| 46 |
+
lr: 0.0002
|
| 47 |
+
betas: [0.9, 0.999]
|
| 48 |
+
weight_decay: 0.0001
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
# Increase to search for the optimal ema
|
| 52 |
+
epoches: 132 # 120 + 4n
|
| 53 |
+
train_dataloader:
|
| 54 |
+
dataset:
|
| 55 |
+
transforms:
|
| 56 |
+
policy:
|
| 57 |
+
epoch: 120
|
| 58 |
+
collate_fn:
|
| 59 |
+
stop_epoch: 120
|
| 60 |
+
ema_restart_decay: 0.9999
|
| 61 |
+
base_size_repeat: 20
|
code/configs/deim_dfine/dfine_hgnetv2_x_coco.yml
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/optimizer.yml',
|
| 6 |
+
'../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./output/dfine_hgnetv2_x_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
DEIM:
|
| 13 |
+
backbone: HGNetv2
|
| 14 |
+
|
| 15 |
+
HGNetv2:
|
| 16 |
+
name: 'B5'
|
| 17 |
+
return_idx: [1, 2, 3]
|
| 18 |
+
freeze_stem_only: True
|
| 19 |
+
freeze_at: 0
|
| 20 |
+
freeze_norm: True
|
| 21 |
+
|
| 22 |
+
HybridEncoder:
|
| 23 |
+
# intra
|
| 24 |
+
hidden_dim: 384
|
| 25 |
+
dim_feedforward: 2048
|
| 26 |
+
|
| 27 |
+
DFINETransformer:
|
| 28 |
+
feat_channels: [384, 384, 384]
|
| 29 |
+
reg_scale: 8
|
| 30 |
+
|
| 31 |
+
optimizer:
|
| 32 |
+
type: AdamW
|
| 33 |
+
params:
|
| 34 |
+
-
|
| 35 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 36 |
+
lr: 0.0000025
|
| 37 |
+
-
|
| 38 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 39 |
+
weight_decay: 0.
|
| 40 |
+
|
| 41 |
+
lr: 0.00025
|
| 42 |
+
betas: [0.9, 0.999]
|
| 43 |
+
weight_decay: 0.000125
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# Increase to search for the optimal ema
|
| 47 |
+
epoches: 80 # 72 + 2n
|
| 48 |
+
train_dataloader:
|
| 49 |
+
dataset:
|
| 50 |
+
transforms:
|
| 51 |
+
policy:
|
| 52 |
+
epoch: 72
|
| 53 |
+
collate_fn:
|
| 54 |
+
stop_epoch: 72
|
| 55 |
+
ema_restart_decay: 0.9998
|
| 56 |
+
base_size_repeat: 3
|
code/configs/deim_dfine/object365/deim_hgnetv2_x_obj2coco_24e.yml
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./dfine_hgnetv2_x_obj2coco.yml',
|
| 3 |
+
'../../base/deim.yml'
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./deim_outputs/deim_hgnetv2_x_obj2coco_24e
|
| 7 |
+
|
| 8 |
+
HGNetv2:
|
| 9 |
+
freeze_at: 0 # 0 default
|
| 10 |
+
freeze_norm: True # True default
|
| 11 |
+
|
| 12 |
+
# Activation
|
| 13 |
+
DFINETransformer:
|
| 14 |
+
activation: relu
|
| 15 |
+
mlp_act: relu
|
| 16 |
+
|
| 17 |
+
optimizer:
|
| 18 |
+
type: AdamW
|
| 19 |
+
params:
|
| 20 |
+
-
|
| 21 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 22 |
+
lr: 0.0000025
|
| 23 |
+
-
|
| 24 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 25 |
+
weight_decay: 0.
|
| 26 |
+
|
| 27 |
+
lr: 0.00025
|
| 28 |
+
betas: [0.9, 0.999]
|
| 29 |
+
weight_decay: 0.000125
|
| 30 |
+
|
| 31 |
+
# Increase to search for the optimal ema
|
| 32 |
+
epoches: 24 # 72 + 2n
|
| 33 |
+
|
| 34 |
+
## Our LR-Scheduler
|
| 35 |
+
lrsheduler: flatcosine
|
| 36 |
+
lr_gamma: 1
|
| 37 |
+
warmup_iter: 0 # 0
|
| 38 |
+
flat_epoch: 12000 # 4 + epoch // 2, e.g., 40 = 4 + 72 / 2
|
| 39 |
+
no_aug_epoch: 4
|
| 40 |
+
|
| 41 |
+
## Our DataAug
|
| 42 |
+
train_dataloader:
|
| 43 |
+
dataset:
|
| 44 |
+
transforms:
|
| 45 |
+
policy:
|
| 46 |
+
epoch: [2, 12, 20] # list
|
| 47 |
+
|
| 48 |
+
collate_fn:
|
| 49 |
+
mixup_epochs: [2, 12]
|
| 50 |
+
stop_epoch: 20
|
code/configs/deim_dfine/object365/dfine_hgnetv2_x_obj2coco.yml
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../../dataset/coco_detection.yml',
|
| 3 |
+
'../../runtime.yml',
|
| 4 |
+
'../../base/dataloader.yml',
|
| 5 |
+
'../../base/optimizer.yml',
|
| 6 |
+
'../../base/dfine_hgnetv2.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./outputs/dfine_hgnetv2_x_obj2coco
|
| 10 |
+
|
| 11 |
+
HGNetv2:
|
| 12 |
+
name: 'B5'
|
| 13 |
+
return_idx: [1, 2, 3]
|
| 14 |
+
freeze_stem_only: True
|
| 15 |
+
freeze_at: 0
|
| 16 |
+
freeze_norm: True
|
| 17 |
+
|
| 18 |
+
HybridEncoder:
|
| 19 |
+
# intra
|
| 20 |
+
hidden_dim: 384
|
| 21 |
+
dim_feedforward: 2048
|
| 22 |
+
|
| 23 |
+
DFINETransformer:
|
| 24 |
+
feat_channels: [384, 384, 384]
|
| 25 |
+
reg_scale: 8
|
| 26 |
+
|
| 27 |
+
optimizer:
|
| 28 |
+
type: AdamW
|
| 29 |
+
params:
|
| 30 |
+
-
|
| 31 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 32 |
+
lr: 0.0000025
|
| 33 |
+
-
|
| 34 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 35 |
+
weight_decay: 0.
|
| 36 |
+
|
| 37 |
+
lr: 0.00025
|
| 38 |
+
betas: [0.9, 0.999]
|
| 39 |
+
weight_decay: 0.000125
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
epoches: 36 # Early stop
|
| 43 |
+
train_dataloader:
|
| 44 |
+
dataset:
|
| 45 |
+
transforms:
|
| 46 |
+
policy:
|
| 47 |
+
epoch: 30
|
| 48 |
+
collate_fn:
|
| 49 |
+
stop_epoch: 30
|
| 50 |
+
ema_restart_decay: 0.9999
|
| 51 |
+
base_size_repeat: 3
|
| 52 |
+
|
| 53 |
+
ema:
|
| 54 |
+
warmups: 0
|
| 55 |
+
|
| 56 |
+
lr_warmup_scheduler:
|
| 57 |
+
warmup_duration: 0
|
code/configs/deim_rtdetrv2/deim_r101vd_60e_coco.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./rtdetrv2_r101vd_6x_coco.yml',
|
| 3 |
+
'../base/rt_deim.yml',
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_rtdetrv2_r101vd_60e_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 13 |
+
lr: 0.000002
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0002
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.0001
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# change part
|
| 24 |
+
epoches: 60
|
| 25 |
+
flat_epoch: 34 # 4 + 60 / 2
|
| 26 |
+
no_aug_epoch: 2
|
| 27 |
+
|
| 28 |
+
train_dataloader:
|
| 29 |
+
dataset:
|
| 30 |
+
transforms:
|
| 31 |
+
policy:
|
| 32 |
+
epoch: [4, 34, 58] # list
|
| 33 |
+
|
| 34 |
+
collate_fn:
|
| 35 |
+
mixup_epochs: [4, 34]
|
| 36 |
+
stop_epoch: 58
|
code/configs/deim_rtdetrv2/deim_r18vd_120e_coco.yml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./rtdetrv2_r18vd_120e_coco.yml',
|
| 3 |
+
'../base/rt_deim.yml',
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./output/deim_rtdetrv2_r18vd_120e_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 13 |
+
weight_decay: 0.
|
| 14 |
+
|
| 15 |
+
lr: 0.0002
|
| 16 |
+
betas: [0.9, 0.999]
|
| 17 |
+
weight_decay: 0.0001
|
| 18 |
+
|
| 19 |
+
# change part
|
| 20 |
+
epoches: 120
|
| 21 |
+
flat_epoch: 64 # 4 + 120 / 2
|
| 22 |
+
no_aug_epoch: 3
|
| 23 |
+
|
| 24 |
+
train_dataloader:
|
| 25 |
+
dataset:
|
| 26 |
+
transforms:
|
| 27 |
+
policy:
|
| 28 |
+
epoch: [4, 64, 117] # list
|
| 29 |
+
|
| 30 |
+
collate_fn:
|
| 31 |
+
mixup_epochs: [4, 64]
|
| 32 |
+
stop_epoch: 117
|
code/configs/deim_rtdetrv2/deim_r34vd_120e_coco.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./rtdetrv2_r34vd_120e_coco.yml',
|
| 3 |
+
'../base/rt_deim.yml',
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_rtdetrv2_r34vd_120e_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 13 |
+
lr: 0.0001
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0002
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.0001
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# change part
|
| 24 |
+
epoches: 120
|
| 25 |
+
flat_epoch: 64
|
| 26 |
+
no_aug_epoch: 3
|
| 27 |
+
|
| 28 |
+
train_dataloader:
|
| 29 |
+
dataset:
|
| 30 |
+
transforms:
|
| 31 |
+
policy:
|
| 32 |
+
epoch: [4, 64, 117] # list
|
| 33 |
+
|
| 34 |
+
collate_fn:
|
| 35 |
+
mixup_epochs: [4, 64]
|
| 36 |
+
stop_epoch: 117
|
code/configs/deim_rtdetrv2/deim_r50vd_60e_coco.yml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./rtdetrv2_r50vd_6x_coco.yml',
|
| 3 |
+
'../base/rt_deim.yml',
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_rtdetrv2_r50vd_60e_coco
|
| 7 |
+
|
| 8 |
+
optimizer:
|
| 9 |
+
type: AdamW
|
| 10 |
+
params:
|
| 11 |
+
-
|
| 12 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 13 |
+
lr: 0.00002
|
| 14 |
+
-
|
| 15 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 16 |
+
weight_decay: 0.
|
| 17 |
+
|
| 18 |
+
lr: 0.0002
|
| 19 |
+
betas: [0.9, 0.999]
|
| 20 |
+
weight_decay: 0.0001
|
| 21 |
+
|
| 22 |
+
# change part
|
| 23 |
+
epoches: 60
|
| 24 |
+
flat_epoch: 34 # 4 + 60 / 2
|
| 25 |
+
no_aug_epoch: 2
|
| 26 |
+
|
| 27 |
+
train_dataloader:
|
| 28 |
+
dataset:
|
| 29 |
+
transforms:
|
| 30 |
+
policy:
|
| 31 |
+
epoch: [4, 34, 58] # list
|
| 32 |
+
|
| 33 |
+
collate_fn:
|
| 34 |
+
mixup_epochs: [4, 34]
|
| 35 |
+
stop_epoch: 58
|
code/configs/deim_rtdetrv2/deim_r50vd_m_60e_coco.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'./rtdetrv2_r50vd_m_7x_coco.yml',
|
| 3 |
+
'../base/rt_deim.yml',
|
| 4 |
+
]
|
| 5 |
+
|
| 6 |
+
output_dir: ./outputs/deim_rtdetrv2_r50vd_m_60e_coco
|
| 7 |
+
|
| 8 |
+
RTDETRTransformerv2:
|
| 9 |
+
eval_idx: 2 # use 3th decoder layer to eval
|
| 10 |
+
num_layers: 3
|
| 11 |
+
|
| 12 |
+
optimizer:
|
| 13 |
+
type: AdamW
|
| 14 |
+
params:
|
| 15 |
+
-
|
| 16 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 17 |
+
lr: 0.00002
|
| 18 |
+
-
|
| 19 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 20 |
+
weight_decay: 0.
|
| 21 |
+
|
| 22 |
+
lr: 0.0002
|
| 23 |
+
betas: [0.9, 0.999]
|
| 24 |
+
weight_decay: 0.0001
|
| 25 |
+
|
| 26 |
+
# change part
|
| 27 |
+
epoches: 60
|
| 28 |
+
flat_epoch: 34 # 4 + 60 / 2
|
| 29 |
+
no_aug_epoch: 2
|
| 30 |
+
|
| 31 |
+
train_dataloader:
|
| 32 |
+
dataset:
|
| 33 |
+
transforms:
|
| 34 |
+
policy:
|
| 35 |
+
epoch: [4, 34, 58] # list
|
| 36 |
+
|
| 37 |
+
collate_fn:
|
| 38 |
+
mixup_epochs: [4, 34]
|
| 39 |
+
stop_epoch: 58
|
code/configs/deim_rtdetrv2/rtdetrv2_r101vd_6x_coco.yml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/rt_optimizer.yml',
|
| 6 |
+
'../base/rtdetrv2_r50vd.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
output_dir: ./outputs/rtdetrv2_r101vd_6x_coco
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
PResNet:
|
| 14 |
+
depth: 101
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
HybridEncoder:
|
| 18 |
+
# intra
|
| 19 |
+
hidden_dim: 384
|
| 20 |
+
dim_feedforward: 2048
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
RTDETRTransformerv2:
|
| 24 |
+
feat_channels: [384, 384, 384]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
optimizer:
|
| 28 |
+
type: AdamW
|
| 29 |
+
params:
|
| 30 |
+
-
|
| 31 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 32 |
+
lr: 0.000001
|
| 33 |
+
-
|
| 34 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$' # only encoder + decoder norm
|
| 35 |
+
weight_decay: 0.
|
| 36 |
+
|
| 37 |
+
lr: 0.0001
|
| 38 |
+
betas: [0.9, 0.999]
|
| 39 |
+
weight_decay: 0.0001
|
| 40 |
+
|
code/configs/deim_rtdetrv2/rtdetrv2_r18vd_120e_coco.yml
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/rt_optimizer.yml',
|
| 6 |
+
'../base/rtdetrv2_r50vd.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
output_dir: ./output/rtdetrv2_r18vd_120e_coco
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
PResNet:
|
| 14 |
+
depth: 18
|
| 15 |
+
freeze_at: -1
|
| 16 |
+
freeze_norm: False
|
| 17 |
+
pretrained: True
|
| 18 |
+
|
| 19 |
+
HybridEncoder:
|
| 20 |
+
in_channels: [128, 256, 512]
|
| 21 |
+
hidden_dim: 256
|
| 22 |
+
expansion: 0.5
|
| 23 |
+
|
| 24 |
+
RTDETRTransformerv2:
|
| 25 |
+
num_layers: 3
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
epoches: 120
|
| 29 |
+
|
| 30 |
+
optimizer:
|
| 31 |
+
type: AdamW
|
| 32 |
+
params:
|
| 33 |
+
-
|
| 34 |
+
params: '^(?=.*(?:norm|bn)).*$'
|
| 35 |
+
weight_decay: 0.
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
train_dataloader:
|
| 39 |
+
dataset:
|
| 40 |
+
transforms:
|
| 41 |
+
policy:
|
| 42 |
+
epoch: 117
|
| 43 |
+
collate_fn:
|
| 44 |
+
scales: ~
|
code/configs/deim_rtdetrv2/rtdetrv2_r34vd_120e_coco.yml
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/rt_optimizer.yml',
|
| 6 |
+
'../base/rtdetrv2_r50vd.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
output_dir: ./outputs/rtdetrv2_r34vd_120e_coco
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
PResNet:
|
| 14 |
+
depth: 34
|
| 15 |
+
freeze_at: -1
|
| 16 |
+
freeze_norm: False
|
| 17 |
+
pretrained: True
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
HybridEncoder:
|
| 21 |
+
in_channels: [128, 256, 512]
|
| 22 |
+
hidden_dim: 256
|
| 23 |
+
expansion: 0.5
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
RTDETRTransformerv2:
|
| 27 |
+
num_layers: 4
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
epoches: 120
|
| 31 |
+
|
| 32 |
+
optimizer:
|
| 33 |
+
type: AdamW
|
| 34 |
+
params:
|
| 35 |
+
-
|
| 36 |
+
params: '^(?=.*backbone)(?!.*norm|bn).*$'
|
| 37 |
+
lr: 0.00005
|
| 38 |
+
-
|
| 39 |
+
params: '^(?=.*backbone)(?=.*norm|bn).*$'
|
| 40 |
+
lr: 0.00005
|
| 41 |
+
weight_decay: 0.
|
| 42 |
+
-
|
| 43 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn|bias)).*$'
|
| 44 |
+
weight_decay: 0.
|
| 45 |
+
|
| 46 |
+
lr: 0.0001
|
| 47 |
+
betas: [0.9, 0.999]
|
| 48 |
+
weight_decay: 0.0001
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
train_dataloader:
|
| 52 |
+
dataset:
|
| 53 |
+
transforms:
|
| 54 |
+
policy:
|
| 55 |
+
epoch: 117
|
| 56 |
+
collate_fn:
|
| 57 |
+
stop_epoch: 117
|
code/configs/deim_rtdetrv2/rtdetrv2_r50vd_6x_coco.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/rt_optimizer.yml',
|
| 6 |
+
'../base/rtdetrv2_r50vd.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
output_dir: ./outputs/rtdetrv2_r50vd_6x_coco
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
optimizer:
|
| 14 |
+
type: AdamW
|
| 15 |
+
params:
|
| 16 |
+
-
|
| 17 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 18 |
+
lr: 0.00001
|
| 19 |
+
-
|
| 20 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 21 |
+
weight_decay: 0.
|
| 22 |
+
|
| 23 |
+
lr: 0.0001
|
| 24 |
+
betas: [0.9, 0.999]
|
| 25 |
+
weight_decay: 0.0001
|
code/configs/deim_rtdetrv2/rtdetrv2_r50vd_m_7x_coco.yml
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__include__: [
|
| 2 |
+
'../dataset/coco_detection.yml',
|
| 3 |
+
'../runtime.yml',
|
| 4 |
+
'../base/dataloader.yml',
|
| 5 |
+
'../base/rt_optimizer.yml',
|
| 6 |
+
'../base/rtdetrv2_r50vd.yml',
|
| 7 |
+
]
|
| 8 |
+
|
| 9 |
+
output_dir: ./outputs/rtdetrv2_r50vd_m_6x_coco
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
HybridEncoder:
|
| 13 |
+
expansion: 0.5
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
RTDETRTransformerv2:
|
| 17 |
+
eval_idx: 2 # use 3th decoder layer to eval
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
epoches: 84
|
| 21 |
+
|
| 22 |
+
optimizer:
|
| 23 |
+
type: AdamW
|
| 24 |
+
params:
|
| 25 |
+
-
|
| 26 |
+
params: '^(?=.*backbone)(?!.*norm).*$'
|
| 27 |
+
lr: 0.00001
|
| 28 |
+
-
|
| 29 |
+
params: '^(?=.*(?:encoder|decoder))(?=.*(?:norm|bn)).*$'
|
| 30 |
+
weight_decay: 0.
|
| 31 |
+
|
| 32 |
+
lr: 0.0001
|
| 33 |
+
betas: [0.9, 0.999]
|
| 34 |
+
weight_decay: 0.0001
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
train_dataloader:
|
| 38 |
+
dataset:
|
| 39 |
+
transforms:
|
| 40 |
+
policy:
|
| 41 |
+
epoch: 81
|
| 42 |
+
collate_fn:
|
| 43 |
+
stop_epoch: 81
|
code/configs/runtime.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
print_freq: 100
|
| 2 |
+
output_dir: './logs'
|
| 3 |
+
checkpoint_freq: 12
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
sync_bn: True
|
| 7 |
+
find_unused_parameters: False
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
use_amp: False
|
| 11 |
+
scaler:
|
| 12 |
+
type: GradScaler
|
| 13 |
+
enabled: True
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
use_ema: False
|
| 17 |
+
ema:
|
| 18 |
+
type: ModelEMA
|
| 19 |
+
decay: 0.9999
|
| 20 |
+
warmups: 1000
|
code/engine/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copyright (c) 2024 The DEIM Authors. All Rights Reserved.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
# for register purpose
|
| 6 |
+
from . import optim
|
| 7 |
+
from . import data
|
| 8 |
+
from . import deim
|
| 9 |
+
|
| 10 |
+
from .backbone import *
|
| 11 |
+
|
| 12 |
+
from .backbone import (
|
| 13 |
+
get_activation,
|
| 14 |
+
FrozenBatchNorm2d,
|
| 15 |
+
freeze_batch_norm2d,
|
| 16 |
+
)
|
code/engine/backbone/__init__.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .common import (
|
| 7 |
+
get_activation,
|
| 8 |
+
FrozenBatchNorm2d,
|
| 9 |
+
freeze_batch_norm2d,
|
| 10 |
+
)
|
| 11 |
+
from .presnet import PResNet
|
| 12 |
+
from .test_resnet import MResNet
|
| 13 |
+
|
| 14 |
+
from .timm_model import TimmModel
|
| 15 |
+
from .torchvision_model import TorchVisionModel
|
| 16 |
+
|
| 17 |
+
from .csp_resnet import CSPResNet
|
| 18 |
+
from .csp_darknet import CSPDarkNet, CSPPAN
|
| 19 |
+
|
| 20 |
+
from .hgnetv2 import HGNetv2
|
code/engine/backbone/common.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class ConvNormLayer(nn.Module):
|
| 11 |
+
def __init__(self, ch_in, ch_out, kernel_size, stride, padding=None, bias=False, act=None):
|
| 12 |
+
super().__init__()
|
| 13 |
+
self.conv = nn.Conv2d(
|
| 14 |
+
ch_in,
|
| 15 |
+
ch_out,
|
| 16 |
+
kernel_size,
|
| 17 |
+
stride,
|
| 18 |
+
padding=(kernel_size-1)//2 if padding is None else padding,
|
| 19 |
+
bias=bias)
|
| 20 |
+
self.norm = nn.BatchNorm2d(ch_out)
|
| 21 |
+
self.act = nn.Identity() if act is None else get_activation(act)
|
| 22 |
+
|
| 23 |
+
def forward(self, x):
|
| 24 |
+
return self.act(self.norm(self.conv(x)))
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class FrozenBatchNorm2d(nn.Module):
|
| 28 |
+
"""copy and modified from https://github.com/facebookresearch/detr/blob/master/models/backbone.py
|
| 29 |
+
BatchNorm2d where the batch statistics and the affine parameters are fixed.
|
| 30 |
+
Copy-paste from torchvision.misc.ops with added eps before rqsrt,
|
| 31 |
+
without which any other models than torchvision.models.resnet[18,34,50,101]
|
| 32 |
+
produce nans.
|
| 33 |
+
"""
|
| 34 |
+
def __init__(self, num_features, eps=1e-5):
|
| 35 |
+
super(FrozenBatchNorm2d, self).__init__()
|
| 36 |
+
n = num_features
|
| 37 |
+
self.register_buffer("weight", torch.ones(n))
|
| 38 |
+
self.register_buffer("bias", torch.zeros(n))
|
| 39 |
+
self.register_buffer("running_mean", torch.zeros(n))
|
| 40 |
+
self.register_buffer("running_var", torch.ones(n))
|
| 41 |
+
self.eps = eps
|
| 42 |
+
self.num_features = n
|
| 43 |
+
|
| 44 |
+
def _load_from_state_dict(self, state_dict, prefix, local_metadata, strict,
|
| 45 |
+
missing_keys, unexpected_keys, error_msgs):
|
| 46 |
+
num_batches_tracked_key = prefix + 'num_batches_tracked'
|
| 47 |
+
if num_batches_tracked_key in state_dict:
|
| 48 |
+
del state_dict[num_batches_tracked_key]
|
| 49 |
+
|
| 50 |
+
super(FrozenBatchNorm2d, self)._load_from_state_dict(
|
| 51 |
+
state_dict, prefix, local_metadata, strict,
|
| 52 |
+
missing_keys, unexpected_keys, error_msgs)
|
| 53 |
+
|
| 54 |
+
def forward(self, x):
|
| 55 |
+
# move reshapes to the beginning
|
| 56 |
+
# to make it fuser-friendly
|
| 57 |
+
w = self.weight.reshape(1, -1, 1, 1)
|
| 58 |
+
b = self.bias.reshape(1, -1, 1, 1)
|
| 59 |
+
rv = self.running_var.reshape(1, -1, 1, 1)
|
| 60 |
+
rm = self.running_mean.reshape(1, -1, 1, 1)
|
| 61 |
+
scale = w * (rv + self.eps).rsqrt()
|
| 62 |
+
bias = b - rm * scale
|
| 63 |
+
return x * scale + bias
|
| 64 |
+
|
| 65 |
+
def extra_repr(self):
|
| 66 |
+
return (
|
| 67 |
+
"{num_features}, eps={eps}".format(**self.__dict__)
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
def freeze_batch_norm2d(module: nn.Module) -> nn.Module:
|
| 71 |
+
if isinstance(module, nn.BatchNorm2d):
|
| 72 |
+
module = FrozenBatchNorm2d(module.num_features)
|
| 73 |
+
else:
|
| 74 |
+
for name, child in module.named_children():
|
| 75 |
+
_child = freeze_batch_norm2d(child)
|
| 76 |
+
if _child is not child:
|
| 77 |
+
setattr(module, name, _child)
|
| 78 |
+
return module
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def get_activation(act: str, inplace: bool=True):
|
| 82 |
+
"""get activation
|
| 83 |
+
"""
|
| 84 |
+
if act is None:
|
| 85 |
+
return nn.Identity()
|
| 86 |
+
|
| 87 |
+
elif isinstance(act, nn.Module):
|
| 88 |
+
return act
|
| 89 |
+
|
| 90 |
+
act = act.lower()
|
| 91 |
+
|
| 92 |
+
if act == 'silu' or act == 'swish':
|
| 93 |
+
m = nn.SiLU()
|
| 94 |
+
|
| 95 |
+
elif act == 'relu':
|
| 96 |
+
m = nn.ReLU()
|
| 97 |
+
|
| 98 |
+
elif act == 'leaky_relu':
|
| 99 |
+
m = nn.LeakyReLU()
|
| 100 |
+
|
| 101 |
+
elif act == 'silu':
|
| 102 |
+
m = nn.SiLU()
|
| 103 |
+
|
| 104 |
+
elif act == 'gelu':
|
| 105 |
+
m = nn.GELU()
|
| 106 |
+
|
| 107 |
+
elif act == 'hardsigmoid':
|
| 108 |
+
m = nn.Hardsigmoid()
|
| 109 |
+
|
| 110 |
+
else:
|
| 111 |
+
raise RuntimeError('')
|
| 112 |
+
|
| 113 |
+
if hasattr(m, 'inplace'):
|
| 114 |
+
m.inplace = inplace
|
| 115 |
+
|
| 116 |
+
return m
|
code/engine/backbone/csp_darknet.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
import torch.nn.functional as F
|
| 9 |
+
|
| 10 |
+
import math
|
| 11 |
+
import warnings
|
| 12 |
+
|
| 13 |
+
from .common import get_activation
|
| 14 |
+
from ..core import register
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def autopad(k, p=None):
|
| 18 |
+
if p is None:
|
| 19 |
+
p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
|
| 20 |
+
return p
|
| 21 |
+
|
| 22 |
+
def make_divisible(c, d):
|
| 23 |
+
return math.ceil(c / d) * d
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class Conv(nn.Module):
|
| 27 |
+
def __init__(self, cin, cout, k=1, s=1, p=None, g=1, act='silu') -> None:
|
| 28 |
+
super().__init__()
|
| 29 |
+
self.conv = nn.Conv2d(cin, cout, k, s, autopad(k, p), groups=g, bias=False)
|
| 30 |
+
self.bn = nn.BatchNorm2d(cout)
|
| 31 |
+
self.act = get_activation(act, inplace=True)
|
| 32 |
+
|
| 33 |
+
def forward(self, x):
|
| 34 |
+
return self.act(self.bn(self.conv(x)))
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class Bottleneck(nn.Module):
|
| 38 |
+
# Standard bottleneck
|
| 39 |
+
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5, act='silu'):
|
| 40 |
+
super().__init__()
|
| 41 |
+
c_ = int(c2 * e) # hidden channels
|
| 42 |
+
self.cv1 = Conv(c1, c_, 1, 1, act=act)
|
| 43 |
+
self.cv2 = Conv(c_, c2, 3, 1, g=g, act=act)
|
| 44 |
+
self.add = shortcut and c1 == c2
|
| 45 |
+
|
| 46 |
+
def forward(self, x):
|
| 47 |
+
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class C3(nn.Module):
|
| 51 |
+
# CSP Bottleneck with 3 convolutions
|
| 52 |
+
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5, act='silu'): # ch_in, ch_out, number, shortcut, groups, expansion
|
| 53 |
+
super().__init__()
|
| 54 |
+
c_ = int(c2 * e) # hidden channels
|
| 55 |
+
self.cv1 = Conv(c1, c_, 1, 1, act=act)
|
| 56 |
+
self.cv2 = Conv(c1, c_, 1, 1, act=act)
|
| 57 |
+
self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0, act=act) for _ in range(n)))
|
| 58 |
+
self.cv3 = Conv(2 * c_, c2, 1, act=act)
|
| 59 |
+
|
| 60 |
+
def forward(self, x):
|
| 61 |
+
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
class SPPF(nn.Module):
|
| 65 |
+
# Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
|
| 66 |
+
def __init__(self, c1, c2, k=5, act='silu'): # equivalent to SPP(k=(5, 9, 13))
|
| 67 |
+
super().__init__()
|
| 68 |
+
c_ = c1 // 2 # hidden channels
|
| 69 |
+
self.cv1 = Conv(c1, c_, 1, 1, act=act)
|
| 70 |
+
self.cv2 = Conv(c_ * 4, c2, 1, 1, act=act)
|
| 71 |
+
self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
|
| 72 |
+
|
| 73 |
+
def forward(self, x):
|
| 74 |
+
x = self.cv1(x)
|
| 75 |
+
with warnings.catch_warnings():
|
| 76 |
+
warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
|
| 77 |
+
y1 = self.m(x)
|
| 78 |
+
y2 = self.m(y1)
|
| 79 |
+
return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
@register()
|
| 83 |
+
class CSPDarkNet(nn.Module):
|
| 84 |
+
__share__ = ['depth_multi', 'width_multi']
|
| 85 |
+
|
| 86 |
+
def __init__(self, in_channels=3, width_multi=1.0, depth_multi=1.0, return_idx=[2, 3, -1], act='silu', ) -> None:
|
| 87 |
+
super().__init__()
|
| 88 |
+
|
| 89 |
+
channels = [64, 128, 256, 512, 1024]
|
| 90 |
+
channels = [make_divisible(c * width_multi, 8) for c in channels]
|
| 91 |
+
|
| 92 |
+
depths = [3, 6, 9, 3]
|
| 93 |
+
depths = [max(round(d * depth_multi), 1) for d in depths]
|
| 94 |
+
|
| 95 |
+
self.layers = nn.ModuleList([Conv(in_channels, channels[0], 6, 2, 2, act=act)])
|
| 96 |
+
for i, (c, d) in enumerate(zip(channels, depths), 1):
|
| 97 |
+
layer = nn.Sequential(*[Conv(c, channels[i], 3, 2, act=act), C3(channels[i], channels[i], n=d, act=act)])
|
| 98 |
+
self.layers.append(layer)
|
| 99 |
+
|
| 100 |
+
self.layers.append(SPPF(channels[-1], channels[-1], k=5, act=act))
|
| 101 |
+
|
| 102 |
+
self.return_idx = return_idx
|
| 103 |
+
self.out_channels = [channels[i] for i in self.return_idx]
|
| 104 |
+
self.strides = [[2, 4, 8, 16, 32][i] for i in self.return_idx]
|
| 105 |
+
self.depths = depths
|
| 106 |
+
self.act = act
|
| 107 |
+
|
| 108 |
+
def forward(self, x):
|
| 109 |
+
outputs = []
|
| 110 |
+
for _, m in enumerate(self.layers):
|
| 111 |
+
x = m(x)
|
| 112 |
+
outputs.append(x)
|
| 113 |
+
|
| 114 |
+
return [outputs[i] for i in self.return_idx]
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
@register()
|
| 118 |
+
class CSPPAN(nn.Module):
|
| 119 |
+
"""
|
| 120 |
+
P5 ---> 1x1 ---------------------------------> concat --> c3 --> det
|
| 121 |
+
| up | conv /2
|
| 122 |
+
P4 ---> concat ---> c3 ---> 1x1 --> concat ---> c3 -----------> det
|
| 123 |
+
| up | conv /2
|
| 124 |
+
P3 -----------------------> concat ---> c3 ---------------------> det
|
| 125 |
+
"""
|
| 126 |
+
__share__ = ['depth_multi', ]
|
| 127 |
+
|
| 128 |
+
def __init__(self, in_channels=[256, 512, 1024], depth_multi=1., act='silu') -> None:
|
| 129 |
+
super().__init__()
|
| 130 |
+
depth = max(round(3 * depth_multi), 1)
|
| 131 |
+
|
| 132 |
+
self.out_channels = in_channels
|
| 133 |
+
self.fpn_stems = nn.ModuleList([Conv(cin, cout, 1, 1, act=act) for cin, cout in zip(in_channels[::-1], in_channels[::-1][1:])])
|
| 134 |
+
self.fpn_csps = nn.ModuleList([C3(cin, cout, depth, False, act=act) for cin, cout in zip(in_channels[::-1], in_channels[::-1][1:])])
|
| 135 |
+
|
| 136 |
+
self.pan_stems = nn.ModuleList([Conv(c, c, 3, 2, act=act) for c in in_channels[:-1]])
|
| 137 |
+
self.pan_csps = nn.ModuleList([C3(c, c, depth, False, act=act) for c in in_channels[1:]])
|
| 138 |
+
|
| 139 |
+
def forward(self, feats):
|
| 140 |
+
fpn_feats = []
|
| 141 |
+
for i, feat in enumerate(feats[::-1]):
|
| 142 |
+
if i == 0:
|
| 143 |
+
feat = self.fpn_stems[i](feat)
|
| 144 |
+
fpn_feats.append(feat)
|
| 145 |
+
else:
|
| 146 |
+
_feat = F.interpolate(fpn_feats[-1], scale_factor=2, mode='nearest')
|
| 147 |
+
feat = torch.concat([_feat, feat], dim=1)
|
| 148 |
+
feat = self.fpn_csps[i-1](feat)
|
| 149 |
+
if i < len(self.fpn_stems):
|
| 150 |
+
feat = self.fpn_stems[i](feat)
|
| 151 |
+
fpn_feats.append(feat)
|
| 152 |
+
|
| 153 |
+
pan_feats = []
|
| 154 |
+
for i, feat in enumerate(fpn_feats[::-1]):
|
| 155 |
+
if i == 0:
|
| 156 |
+
pan_feats.append(feat)
|
| 157 |
+
else:
|
| 158 |
+
_feat = self.pan_stems[i-1](pan_feats[-1])
|
| 159 |
+
feat = torch.concat([_feat, feat], dim=1)
|
| 160 |
+
feat = self.pan_csps[i-1](feat)
|
| 161 |
+
pan_feats.append(feat)
|
| 162 |
+
|
| 163 |
+
return pan_feats
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
if __name__ == '__main__':
|
| 167 |
+
|
| 168 |
+
data = torch.rand(1, 3, 320, 640)
|
| 169 |
+
|
| 170 |
+
width_multi = 0.75
|
| 171 |
+
depth_multi = 0.33
|
| 172 |
+
|
| 173 |
+
m = CSPDarkNet(3, width_multi=width_multi, depth_multi=depth_multi, act='silu')
|
| 174 |
+
outputs = m(data)
|
| 175 |
+
print([o.shape for o in outputs])
|
| 176 |
+
|
| 177 |
+
m = CSPPAN(in_channels=m.out_channels, depth_multi=depth_multi, act='silu')
|
| 178 |
+
outputs = m(outputs)
|
| 179 |
+
print([o.shape for o in outputs])
|
code/engine/backbone/csp_resnet.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.6/ppdet/modeling/backbones/cspresnet.py
|
| 3 |
+
|
| 4 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
import torch.nn as nn
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from collections import OrderedDict
|
| 11 |
+
|
| 12 |
+
from .common import get_activation
|
| 13 |
+
|
| 14 |
+
from ..core import register
|
| 15 |
+
|
| 16 |
+
__all__ = ['CSPResNet']
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
donwload_url = {
|
| 20 |
+
's': 'https://github.com/lyuwenyu/storage/releases/download/v0.1/CSPResNetb_s_pretrained_from_paddle.pth',
|
| 21 |
+
'm': 'https://github.com/lyuwenyu/storage/releases/download/v0.1/CSPResNetb_m_pretrained_from_paddle.pth',
|
| 22 |
+
'l': 'https://github.com/lyuwenyu/storage/releases/download/v0.1/CSPResNetb_l_pretrained_from_paddle.pth',
|
| 23 |
+
'x': 'https://github.com/lyuwenyu/storage/releases/download/v0.1/CSPResNetb_x_pretrained_from_paddle.pth',
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class ConvBNLayer(nn.Module):
|
| 28 |
+
def __init__(self, ch_in, ch_out, filter_size=3, stride=1, groups=1, padding=0, act=None):
|
| 29 |
+
super().__init__()
|
| 30 |
+
self.conv = nn.Conv2d(ch_in, ch_out, filter_size, stride, padding, groups=groups, bias=False)
|
| 31 |
+
self.bn = nn.BatchNorm2d(ch_out)
|
| 32 |
+
self.act = get_activation(act)
|
| 33 |
+
|
| 34 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 35 |
+
x = self.conv(x)
|
| 36 |
+
x = self.bn(x)
|
| 37 |
+
x = self.act(x)
|
| 38 |
+
return x
|
| 39 |
+
|
| 40 |
+
class RepVggBlock(nn.Module):
|
| 41 |
+
def __init__(self, ch_in, ch_out, act='relu', alpha: bool=False):
|
| 42 |
+
super().__init__()
|
| 43 |
+
self.ch_in = ch_in
|
| 44 |
+
self.ch_out = ch_out
|
| 45 |
+
self.conv1 = ConvBNLayer(
|
| 46 |
+
ch_in, ch_out, 3, stride=1, padding=1, act=None)
|
| 47 |
+
self.conv2 = ConvBNLayer(
|
| 48 |
+
ch_in, ch_out, 1, stride=1, padding=0, act=None)
|
| 49 |
+
self.act = get_activation(act)
|
| 50 |
+
|
| 51 |
+
if alpha:
|
| 52 |
+
self.alpha = nn.Parameter(torch.ones(1, ))
|
| 53 |
+
else:
|
| 54 |
+
self.alpha = None
|
| 55 |
+
|
| 56 |
+
def forward(self, x):
|
| 57 |
+
if hasattr(self, 'conv'):
|
| 58 |
+
y = self.conv(x)
|
| 59 |
+
else:
|
| 60 |
+
if self.alpha:
|
| 61 |
+
y = self.conv1(x) + self.alpha * self.conv2(x)
|
| 62 |
+
else:
|
| 63 |
+
y = self.conv1(x) + self.conv2(x)
|
| 64 |
+
y = self.act(y)
|
| 65 |
+
return y
|
| 66 |
+
|
| 67 |
+
def convert_to_deploy(self):
|
| 68 |
+
if not hasattr(self, 'conv'):
|
| 69 |
+
self.conv = nn.Conv2d(self.ch_in, self.ch_out, 3, 1, padding=1)
|
| 70 |
+
|
| 71 |
+
kernel, bias = self.get_equivalent_kernel_bias()
|
| 72 |
+
self.conv.weight.data = kernel
|
| 73 |
+
self.conv.bias.data = bias
|
| 74 |
+
|
| 75 |
+
def get_equivalent_kernel_bias(self):
|
| 76 |
+
kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
|
| 77 |
+
kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
|
| 78 |
+
|
| 79 |
+
if self.alpha:
|
| 80 |
+
return kernel3x3 + self.alpha * self._pad_1x1_to_3x3_tensor(
|
| 81 |
+
kernel1x1), bias3x3 + self.alpha * bias1x1
|
| 82 |
+
else:
|
| 83 |
+
return kernel3x3 + self._pad_1x1_to_3x3_tensor(
|
| 84 |
+
kernel1x1), bias3x3 + bias1x1
|
| 85 |
+
|
| 86 |
+
def _pad_1x1_to_3x3_tensor(self, kernel1x1):
|
| 87 |
+
if kernel1x1 is None:
|
| 88 |
+
return 0
|
| 89 |
+
else:
|
| 90 |
+
return F.pad(kernel1x1, [1, 1, 1, 1])
|
| 91 |
+
|
| 92 |
+
def _fuse_bn_tensor(self, branch: ConvBNLayer):
|
| 93 |
+
if branch is None:
|
| 94 |
+
return 0, 0
|
| 95 |
+
kernel = branch.conv.weight
|
| 96 |
+
running_mean = branch.norm.running_mean
|
| 97 |
+
running_var = branch.norm.running_var
|
| 98 |
+
gamma = branch.norm.weight
|
| 99 |
+
beta = branch.norm.bias
|
| 100 |
+
eps = branch.norm.eps
|
| 101 |
+
std = (running_var + eps).sqrt()
|
| 102 |
+
t = (gamma / std).reshape(-1, 1, 1, 1)
|
| 103 |
+
return kernel * t, beta - running_mean * gamma / std
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
class BasicBlock(nn.Module):
|
| 107 |
+
def __init__(self,
|
| 108 |
+
ch_in,
|
| 109 |
+
ch_out,
|
| 110 |
+
act='relu',
|
| 111 |
+
shortcut=True,
|
| 112 |
+
use_alpha=False):
|
| 113 |
+
super().__init__()
|
| 114 |
+
assert ch_in == ch_out
|
| 115 |
+
self.conv1 = ConvBNLayer(ch_in, ch_out, 3, stride=1, padding=1, act=act)
|
| 116 |
+
self.conv2 = RepVggBlock(ch_out, ch_out, act=act, alpha=use_alpha)
|
| 117 |
+
self.shortcut = shortcut
|
| 118 |
+
|
| 119 |
+
def forward(self, x):
|
| 120 |
+
y = self.conv1(x)
|
| 121 |
+
y = self.conv2(y)
|
| 122 |
+
if self.shortcut:
|
| 123 |
+
return x + y
|
| 124 |
+
else:
|
| 125 |
+
return y
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
class EffectiveSELayer(nn.Module):
|
| 129 |
+
""" Effective Squeeze-Excitation
|
| 130 |
+
From `CenterMask : Real-Time Anchor-Free Instance Segmentation` - https://arxiv.org/abs/1911.06667
|
| 131 |
+
"""
|
| 132 |
+
|
| 133 |
+
def __init__(self, channels, act='hardsigmoid'):
|
| 134 |
+
super(EffectiveSELayer, self).__init__()
|
| 135 |
+
self.fc = nn.Conv2d(channels, channels, kernel_size=1, padding=0)
|
| 136 |
+
self.act = get_activation(act)
|
| 137 |
+
|
| 138 |
+
def forward(self, x: torch.Tensor):
|
| 139 |
+
x_se = x.mean((2, 3), keepdim=True)
|
| 140 |
+
x_se = self.fc(x_se)
|
| 141 |
+
x_se = self.act(x_se)
|
| 142 |
+
return x * x_se
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
class CSPResStage(nn.Module):
|
| 146 |
+
def __init__(self,
|
| 147 |
+
block_fn,
|
| 148 |
+
ch_in,
|
| 149 |
+
ch_out,
|
| 150 |
+
n,
|
| 151 |
+
stride,
|
| 152 |
+
act='relu',
|
| 153 |
+
attn='eca',
|
| 154 |
+
use_alpha=False):
|
| 155 |
+
super().__init__()
|
| 156 |
+
ch_mid = (ch_in + ch_out) // 2
|
| 157 |
+
if stride == 2:
|
| 158 |
+
self.conv_down = ConvBNLayer(
|
| 159 |
+
ch_in, ch_mid, 3, stride=2, padding=1, act=act)
|
| 160 |
+
else:
|
| 161 |
+
self.conv_down = None
|
| 162 |
+
self.conv1 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
|
| 163 |
+
self.conv2 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
|
| 164 |
+
self.blocks = nn.Sequential(*[
|
| 165 |
+
block_fn(
|
| 166 |
+
ch_mid // 2,
|
| 167 |
+
ch_mid // 2,
|
| 168 |
+
act=act,
|
| 169 |
+
shortcut=True,
|
| 170 |
+
use_alpha=use_alpha) for i in range(n)
|
| 171 |
+
])
|
| 172 |
+
if attn:
|
| 173 |
+
self.attn = EffectiveSELayer(ch_mid, act='hardsigmoid')
|
| 174 |
+
else:
|
| 175 |
+
self.attn = None
|
| 176 |
+
|
| 177 |
+
self.conv3 = ConvBNLayer(ch_mid, ch_out, 1, act=act)
|
| 178 |
+
|
| 179 |
+
def forward(self, x):
|
| 180 |
+
if self.conv_down is not None:
|
| 181 |
+
x = self.conv_down(x)
|
| 182 |
+
y1 = self.conv1(x)
|
| 183 |
+
y2 = self.blocks(self.conv2(x))
|
| 184 |
+
y = torch.concat([y1, y2], dim=1)
|
| 185 |
+
if self.attn is not None:
|
| 186 |
+
y = self.attn(y)
|
| 187 |
+
y = self.conv3(y)
|
| 188 |
+
return y
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
@register()
|
| 192 |
+
class CSPResNet(nn.Module):
|
| 193 |
+
layers = [3, 6, 6, 3]
|
| 194 |
+
channels = [64, 128, 256, 512, 1024]
|
| 195 |
+
model_cfg = {
|
| 196 |
+
's': {'depth_mult': 0.33, 'width_mult': 0.50, },
|
| 197 |
+
'm': {'depth_mult': 0.67, 'width_mult': 0.75, },
|
| 198 |
+
'l': {'depth_mult': 1.00, 'width_mult': 1.00, },
|
| 199 |
+
'x': {'depth_mult': 1.33, 'width_mult': 1.25, },
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
def __init__(self,
|
| 203 |
+
name: str,
|
| 204 |
+
act='silu',
|
| 205 |
+
return_idx=[1, 2, 3],
|
| 206 |
+
use_large_stem=True,
|
| 207 |
+
use_alpha=False,
|
| 208 |
+
pretrained=False):
|
| 209 |
+
|
| 210 |
+
super().__init__()
|
| 211 |
+
depth_mult = self.model_cfg[name]['depth_mult']
|
| 212 |
+
width_mult = self.model_cfg[name]['width_mult']
|
| 213 |
+
|
| 214 |
+
channels = [max(round(c * width_mult), 1) for c in self.channels]
|
| 215 |
+
layers = [max(round(l * depth_mult), 1) for l in self.layers]
|
| 216 |
+
act = get_activation(act)
|
| 217 |
+
|
| 218 |
+
if use_large_stem:
|
| 219 |
+
self.stem = nn.Sequential(OrderedDict([
|
| 220 |
+
('conv1', ConvBNLayer(
|
| 221 |
+
3, channels[0] // 2, 3, stride=2, padding=1, act=act)),
|
| 222 |
+
('conv2', ConvBNLayer(
|
| 223 |
+
channels[0] // 2,
|
| 224 |
+
channels[0] // 2,
|
| 225 |
+
3,
|
| 226 |
+
stride=1,
|
| 227 |
+
padding=1,
|
| 228 |
+
act=act)), ('conv3', ConvBNLayer(
|
| 229 |
+
channels[0] // 2,
|
| 230 |
+
channels[0],
|
| 231 |
+
3,
|
| 232 |
+
stride=1,
|
| 233 |
+
padding=1,
|
| 234 |
+
act=act))]))
|
| 235 |
+
else:
|
| 236 |
+
self.stem = nn.Sequential(OrderedDict([
|
| 237 |
+
('conv1', ConvBNLayer(
|
| 238 |
+
3, channels[0] // 2, 3, stride=2, padding=1, act=act)),
|
| 239 |
+
('conv2', ConvBNLayer(
|
| 240 |
+
channels[0] // 2,
|
| 241 |
+
channels[0],
|
| 242 |
+
3,
|
| 243 |
+
stride=1,
|
| 244 |
+
padding=1,
|
| 245 |
+
act=act))]))
|
| 246 |
+
|
| 247 |
+
n = len(channels) - 1
|
| 248 |
+
self.stages = nn.Sequential(OrderedDict([(str(i), CSPResStage(
|
| 249 |
+
BasicBlock,
|
| 250 |
+
channels[i],
|
| 251 |
+
channels[i + 1],
|
| 252 |
+
layers[i],
|
| 253 |
+
2,
|
| 254 |
+
act=act,
|
| 255 |
+
use_alpha=use_alpha)) for i in range(n)]))
|
| 256 |
+
|
| 257 |
+
self._out_channels = channels[1:]
|
| 258 |
+
self._out_strides = [4 * 2**i for i in range(n)]
|
| 259 |
+
self.return_idx = return_idx
|
| 260 |
+
|
| 261 |
+
if pretrained:
|
| 262 |
+
if isinstance(pretrained, bool) or 'http' in pretrained:
|
| 263 |
+
state = torch.hub.load_state_dict_from_url(donwload_url[name], map_location='cpu')
|
| 264 |
+
else:
|
| 265 |
+
state = torch.load(pretrained, map_location='cpu')
|
| 266 |
+
self.load_state_dict(state)
|
| 267 |
+
print(f'Load CSPResNet_{name} state_dict')
|
| 268 |
+
|
| 269 |
+
def forward(self, x):
|
| 270 |
+
x = self.stem(x)
|
| 271 |
+
outs = []
|
| 272 |
+
for idx, stage in enumerate(self.stages):
|
| 273 |
+
x = stage(x)
|
| 274 |
+
if idx in self.return_idx:
|
| 275 |
+
outs.append(x)
|
| 276 |
+
|
| 277 |
+
return outs
|
code/engine/backbone/hgnetv2.py
ADDED
|
@@ -0,0 +1,543 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
reference
|
| 3 |
+
- https://github.com/PaddlePaddle/PaddleDetection/blob/develop/ppdet/modeling/backbones/hgnet_v2.py
|
| 4 |
+
|
| 5 |
+
Copyright (c) 2024 The D-FINE Authors. All Rights Reserved.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
import torch.nn.functional as F
|
| 11 |
+
import os
|
| 12 |
+
from .common import FrozenBatchNorm2d
|
| 13 |
+
from ..core import register
|
| 14 |
+
import logging
|
| 15 |
+
|
| 16 |
+
# Constants for initialization
|
| 17 |
+
kaiming_normal_ = nn.init.kaiming_normal_
|
| 18 |
+
zeros_ = nn.init.zeros_
|
| 19 |
+
ones_ = nn.init.ones_
|
| 20 |
+
|
| 21 |
+
__all__ = ['HGNetv2']
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class LearnableAffineBlock(nn.Module):
|
| 25 |
+
def __init__(
|
| 26 |
+
self,
|
| 27 |
+
scale_value=1.0,
|
| 28 |
+
bias_value=0.0
|
| 29 |
+
):
|
| 30 |
+
super().__init__()
|
| 31 |
+
self.scale = nn.Parameter(torch.tensor([scale_value]), requires_grad=True)
|
| 32 |
+
self.bias = nn.Parameter(torch.tensor([bias_value]), requires_grad=True)
|
| 33 |
+
|
| 34 |
+
def forward(self, x):
|
| 35 |
+
return self.scale * x + self.bias
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class ConvBNAct(nn.Module):
|
| 39 |
+
def __init__(
|
| 40 |
+
self,
|
| 41 |
+
in_chs,
|
| 42 |
+
out_chs,
|
| 43 |
+
kernel_size,
|
| 44 |
+
stride=1,
|
| 45 |
+
groups=1,
|
| 46 |
+
padding='',
|
| 47 |
+
use_act=True,
|
| 48 |
+
use_lab=False
|
| 49 |
+
):
|
| 50 |
+
super().__init__()
|
| 51 |
+
self.use_act = use_act
|
| 52 |
+
self.use_lab = use_lab
|
| 53 |
+
if padding == 'same':
|
| 54 |
+
self.conv = nn.Sequential(
|
| 55 |
+
nn.ZeroPad2d([0, 1, 0, 1]),
|
| 56 |
+
nn.Conv2d(
|
| 57 |
+
in_chs,
|
| 58 |
+
out_chs,
|
| 59 |
+
kernel_size,
|
| 60 |
+
stride,
|
| 61 |
+
groups=groups,
|
| 62 |
+
bias=False
|
| 63 |
+
)
|
| 64 |
+
)
|
| 65 |
+
else:
|
| 66 |
+
self.conv = nn.Conv2d(
|
| 67 |
+
in_chs,
|
| 68 |
+
out_chs,
|
| 69 |
+
kernel_size,
|
| 70 |
+
stride,
|
| 71 |
+
padding=(kernel_size - 1) // 2,
|
| 72 |
+
groups=groups,
|
| 73 |
+
bias=False
|
| 74 |
+
)
|
| 75 |
+
self.bn = nn.BatchNorm2d(out_chs)
|
| 76 |
+
if self.use_act:
|
| 77 |
+
self.act = nn.ReLU()
|
| 78 |
+
else:
|
| 79 |
+
self.act = nn.Identity()
|
| 80 |
+
if self.use_act and self.use_lab:
|
| 81 |
+
self.lab = LearnableAffineBlock()
|
| 82 |
+
else:
|
| 83 |
+
self.lab = nn.Identity()
|
| 84 |
+
|
| 85 |
+
def forward(self, x):
|
| 86 |
+
x = self.conv(x)
|
| 87 |
+
x = self.bn(x)
|
| 88 |
+
x = self.act(x)
|
| 89 |
+
x = self.lab(x)
|
| 90 |
+
return x
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class LightConvBNAct(nn.Module):
|
| 94 |
+
def __init__(
|
| 95 |
+
self,
|
| 96 |
+
in_chs,
|
| 97 |
+
out_chs,
|
| 98 |
+
kernel_size,
|
| 99 |
+
groups=1,
|
| 100 |
+
use_lab=False,
|
| 101 |
+
):
|
| 102 |
+
super().__init__()
|
| 103 |
+
self.conv1 = ConvBNAct(
|
| 104 |
+
in_chs,
|
| 105 |
+
out_chs,
|
| 106 |
+
kernel_size=1,
|
| 107 |
+
use_act=False,
|
| 108 |
+
use_lab=use_lab,
|
| 109 |
+
)
|
| 110 |
+
self.conv2 = ConvBNAct(
|
| 111 |
+
out_chs,
|
| 112 |
+
out_chs,
|
| 113 |
+
kernel_size=kernel_size,
|
| 114 |
+
groups=out_chs,
|
| 115 |
+
use_act=True,
|
| 116 |
+
use_lab=use_lab,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
def forward(self, x):
|
| 120 |
+
x = self.conv1(x)
|
| 121 |
+
x = self.conv2(x)
|
| 122 |
+
return x
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
class StemBlock(nn.Module):
|
| 126 |
+
# for HGNetv2
|
| 127 |
+
def __init__(self, in_chs, mid_chs, out_chs, use_lab=False):
|
| 128 |
+
super().__init__()
|
| 129 |
+
self.stem1 = ConvBNAct(
|
| 130 |
+
in_chs,
|
| 131 |
+
mid_chs,
|
| 132 |
+
kernel_size=3,
|
| 133 |
+
stride=2,
|
| 134 |
+
use_lab=use_lab,
|
| 135 |
+
)
|
| 136 |
+
self.stem2a = ConvBNAct(
|
| 137 |
+
mid_chs,
|
| 138 |
+
mid_chs // 2,
|
| 139 |
+
kernel_size=2,
|
| 140 |
+
stride=1,
|
| 141 |
+
use_lab=use_lab,
|
| 142 |
+
)
|
| 143 |
+
self.stem2b = ConvBNAct(
|
| 144 |
+
mid_chs // 2,
|
| 145 |
+
mid_chs,
|
| 146 |
+
kernel_size=2,
|
| 147 |
+
stride=1,
|
| 148 |
+
use_lab=use_lab,
|
| 149 |
+
)
|
| 150 |
+
self.stem3 = ConvBNAct(
|
| 151 |
+
mid_chs * 2,
|
| 152 |
+
mid_chs,
|
| 153 |
+
kernel_size=3,
|
| 154 |
+
stride=2,
|
| 155 |
+
use_lab=use_lab,
|
| 156 |
+
)
|
| 157 |
+
self.stem4 = ConvBNAct(
|
| 158 |
+
mid_chs,
|
| 159 |
+
out_chs,
|
| 160 |
+
kernel_size=1,
|
| 161 |
+
stride=1,
|
| 162 |
+
use_lab=use_lab,
|
| 163 |
+
)
|
| 164 |
+
self.pool = nn.MaxPool2d(kernel_size=2, stride=1, ceil_mode=True)
|
| 165 |
+
|
| 166 |
+
def forward(self, x):
|
| 167 |
+
x = self.stem1(x)
|
| 168 |
+
x = F.pad(x, (0, 1, 0, 1))
|
| 169 |
+
x2 = self.stem2a(x)
|
| 170 |
+
x2 = F.pad(x2, (0, 1, 0, 1))
|
| 171 |
+
x2 = self.stem2b(x2)
|
| 172 |
+
x1 = self.pool(x)
|
| 173 |
+
x = torch.cat([x1, x2], dim=1)
|
| 174 |
+
x = self.stem3(x)
|
| 175 |
+
x = self.stem4(x)
|
| 176 |
+
return x
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
class EseModule(nn.Module):
|
| 180 |
+
def __init__(self, chs):
|
| 181 |
+
super().__init__()
|
| 182 |
+
self.conv = nn.Conv2d(
|
| 183 |
+
chs,
|
| 184 |
+
chs,
|
| 185 |
+
kernel_size=1,
|
| 186 |
+
stride=1,
|
| 187 |
+
padding=0,
|
| 188 |
+
)
|
| 189 |
+
self.sigmoid = nn.Sigmoid()
|
| 190 |
+
|
| 191 |
+
def forward(self, x):
|
| 192 |
+
identity = x
|
| 193 |
+
x = x.mean((2, 3), keepdim=True)
|
| 194 |
+
x = self.conv(x)
|
| 195 |
+
x = self.sigmoid(x)
|
| 196 |
+
return torch.mul(identity, x)
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
class HG_Block(nn.Module):
|
| 200 |
+
def __init__(
|
| 201 |
+
self,
|
| 202 |
+
in_chs,
|
| 203 |
+
mid_chs,
|
| 204 |
+
out_chs,
|
| 205 |
+
layer_num,
|
| 206 |
+
kernel_size=3,
|
| 207 |
+
residual=False,
|
| 208 |
+
light_block=False,
|
| 209 |
+
use_lab=False,
|
| 210 |
+
agg='ese',
|
| 211 |
+
drop_path=0.,
|
| 212 |
+
):
|
| 213 |
+
super().__init__()
|
| 214 |
+
self.residual = residual
|
| 215 |
+
|
| 216 |
+
self.layers = nn.ModuleList()
|
| 217 |
+
for i in range(layer_num):
|
| 218 |
+
if light_block:
|
| 219 |
+
self.layers.append(
|
| 220 |
+
LightConvBNAct(
|
| 221 |
+
in_chs if i == 0 else mid_chs,
|
| 222 |
+
mid_chs,
|
| 223 |
+
kernel_size=kernel_size,
|
| 224 |
+
use_lab=use_lab,
|
| 225 |
+
)
|
| 226 |
+
)
|
| 227 |
+
else:
|
| 228 |
+
self.layers.append(
|
| 229 |
+
ConvBNAct(
|
| 230 |
+
in_chs if i == 0 else mid_chs,
|
| 231 |
+
mid_chs,
|
| 232 |
+
kernel_size=kernel_size,
|
| 233 |
+
stride=1,
|
| 234 |
+
use_lab=use_lab,
|
| 235 |
+
)
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
# feature aggregation
|
| 239 |
+
total_chs = in_chs + layer_num * mid_chs
|
| 240 |
+
if agg == 'se':
|
| 241 |
+
aggregation_squeeze_conv = ConvBNAct(
|
| 242 |
+
total_chs,
|
| 243 |
+
out_chs // 2,
|
| 244 |
+
kernel_size=1,
|
| 245 |
+
stride=1,
|
| 246 |
+
use_lab=use_lab,
|
| 247 |
+
)
|
| 248 |
+
aggregation_excitation_conv = ConvBNAct(
|
| 249 |
+
out_chs // 2,
|
| 250 |
+
out_chs,
|
| 251 |
+
kernel_size=1,
|
| 252 |
+
stride=1,
|
| 253 |
+
use_lab=use_lab,
|
| 254 |
+
)
|
| 255 |
+
self.aggregation = nn.Sequential(
|
| 256 |
+
aggregation_squeeze_conv,
|
| 257 |
+
aggregation_excitation_conv,
|
| 258 |
+
)
|
| 259 |
+
else:
|
| 260 |
+
aggregation_conv = ConvBNAct(
|
| 261 |
+
total_chs,
|
| 262 |
+
out_chs,
|
| 263 |
+
kernel_size=1,
|
| 264 |
+
stride=1,
|
| 265 |
+
use_lab=use_lab,
|
| 266 |
+
)
|
| 267 |
+
att = EseModule(out_chs)
|
| 268 |
+
self.aggregation = nn.Sequential(
|
| 269 |
+
aggregation_conv,
|
| 270 |
+
att,
|
| 271 |
+
)
|
| 272 |
+
|
| 273 |
+
self.drop_path = nn.Dropout(drop_path) if drop_path else nn.Identity()
|
| 274 |
+
|
| 275 |
+
def forward(self, x):
|
| 276 |
+
identity = x
|
| 277 |
+
output = [x]
|
| 278 |
+
for layer in self.layers:
|
| 279 |
+
x = layer(x)
|
| 280 |
+
output.append(x)
|
| 281 |
+
x = torch.cat(output, dim=1)
|
| 282 |
+
x = self.aggregation(x)
|
| 283 |
+
if self.residual:
|
| 284 |
+
x = self.drop_path(x) + identity
|
| 285 |
+
return x
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
class HG_Stage(nn.Module):
|
| 289 |
+
def __init__(
|
| 290 |
+
self,
|
| 291 |
+
in_chs,
|
| 292 |
+
mid_chs,
|
| 293 |
+
out_chs,
|
| 294 |
+
block_num,
|
| 295 |
+
layer_num,
|
| 296 |
+
downsample=True,
|
| 297 |
+
light_block=False,
|
| 298 |
+
kernel_size=3,
|
| 299 |
+
use_lab=False,
|
| 300 |
+
agg='se',
|
| 301 |
+
drop_path=0.,
|
| 302 |
+
):
|
| 303 |
+
super().__init__()
|
| 304 |
+
self.downsample = downsample
|
| 305 |
+
if downsample:
|
| 306 |
+
self.downsample = ConvBNAct(
|
| 307 |
+
in_chs,
|
| 308 |
+
in_chs,
|
| 309 |
+
kernel_size=3,
|
| 310 |
+
stride=2,
|
| 311 |
+
groups=in_chs,
|
| 312 |
+
use_act=False,
|
| 313 |
+
use_lab=use_lab,
|
| 314 |
+
)
|
| 315 |
+
else:
|
| 316 |
+
self.downsample = nn.Identity()
|
| 317 |
+
|
| 318 |
+
blocks_list = []
|
| 319 |
+
for i in range(block_num):
|
| 320 |
+
blocks_list.append(
|
| 321 |
+
HG_Block(
|
| 322 |
+
in_chs if i == 0 else out_chs,
|
| 323 |
+
mid_chs,
|
| 324 |
+
out_chs,
|
| 325 |
+
layer_num,
|
| 326 |
+
residual=False if i == 0 else True,
|
| 327 |
+
kernel_size=kernel_size,
|
| 328 |
+
light_block=light_block,
|
| 329 |
+
use_lab=use_lab,
|
| 330 |
+
agg=agg,
|
| 331 |
+
drop_path=drop_path[i] if isinstance(drop_path, (list, tuple)) else drop_path,
|
| 332 |
+
)
|
| 333 |
+
)
|
| 334 |
+
self.blocks = nn.Sequential(*blocks_list)
|
| 335 |
+
|
| 336 |
+
def forward(self, x):
|
| 337 |
+
x = self.downsample(x)
|
| 338 |
+
x = self.blocks(x)
|
| 339 |
+
return x
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
@register()
|
| 344 |
+
class HGNetv2(nn.Module):
|
| 345 |
+
"""
|
| 346 |
+
HGNetV2
|
| 347 |
+
Args:
|
| 348 |
+
stem_channels: list. Number of channels for the stem block.
|
| 349 |
+
stage_type: str. The stage configuration of HGNet. such as the number of channels, stride, etc.
|
| 350 |
+
use_lab: boolean. Whether to use LearnableAffineBlock in network.
|
| 351 |
+
lr_mult_list: list. Control the learning rate of different stages.
|
| 352 |
+
Returns:
|
| 353 |
+
model: nn.Layer. Specific HGNetV2 model depends on args.
|
| 354 |
+
"""
|
| 355 |
+
|
| 356 |
+
arch_configs = {
|
| 357 |
+
'B0': {
|
| 358 |
+
'stem_channels': [3, 16, 16],
|
| 359 |
+
'stage_config': {
|
| 360 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 361 |
+
"stage1": [16, 16, 64, 1, False, False, 3, 3],
|
| 362 |
+
"stage2": [64, 32, 256, 1, True, False, 3, 3],
|
| 363 |
+
"stage3": [256, 64, 512, 2, True, True, 5, 3],
|
| 364 |
+
"stage4": [512, 128, 1024, 1, True, True, 5, 3],
|
| 365 |
+
},
|
| 366 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B0_stage1.pth'
|
| 367 |
+
},
|
| 368 |
+
'B1': {
|
| 369 |
+
'stem_channels': [3, 24, 32],
|
| 370 |
+
'stage_config': {
|
| 371 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 372 |
+
"stage1": [32, 32, 64, 1, False, False, 3, 3],
|
| 373 |
+
"stage2": [64, 48, 256, 1, True, False, 3, 3],
|
| 374 |
+
"stage3": [256, 96, 512, 2, True, True, 5, 3],
|
| 375 |
+
"stage4": [512, 192, 1024, 1, True, True, 5, 3],
|
| 376 |
+
},
|
| 377 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B1_stage1.pth'
|
| 378 |
+
},
|
| 379 |
+
'B2': {
|
| 380 |
+
'stem_channels': [3, 24, 32],
|
| 381 |
+
'stage_config': {
|
| 382 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 383 |
+
"stage1": [32, 32, 96, 1, False, False, 3, 4],
|
| 384 |
+
"stage2": [96, 64, 384, 1, True, False, 3, 4],
|
| 385 |
+
"stage3": [384, 128, 768, 3, True, True, 5, 4],
|
| 386 |
+
"stage4": [768, 256, 1536, 1, True, True, 5, 4],
|
| 387 |
+
},
|
| 388 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B2_stage1.pth'
|
| 389 |
+
},
|
| 390 |
+
'B3': {
|
| 391 |
+
'stem_channels': [3, 24, 32],
|
| 392 |
+
'stage_config': {
|
| 393 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 394 |
+
"stage1": [32, 32, 128, 1, False, False, 3, 5],
|
| 395 |
+
"stage2": [128, 64, 512, 1, True, False, 3, 5],
|
| 396 |
+
"stage3": [512, 128, 1024, 3, True, True, 5, 5],
|
| 397 |
+
"stage4": [1024, 256, 2048, 1, True, True, 5, 5],
|
| 398 |
+
},
|
| 399 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B3_stage1.pth'
|
| 400 |
+
},
|
| 401 |
+
'B4': {
|
| 402 |
+
'stem_channels': [3, 32, 48],
|
| 403 |
+
'stage_config': {
|
| 404 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 405 |
+
"stage1": [48, 48, 128, 1, False, False, 3, 6],
|
| 406 |
+
"stage2": [128, 96, 512, 1, True, False, 3, 6],
|
| 407 |
+
"stage3": [512, 192, 1024, 3, True, True, 5, 6],
|
| 408 |
+
"stage4": [1024, 384, 2048, 1, True, True, 5, 6],
|
| 409 |
+
},
|
| 410 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B4_stage1.pth'
|
| 411 |
+
},
|
| 412 |
+
'B5': {
|
| 413 |
+
'stem_channels': [3, 32, 64],
|
| 414 |
+
'stage_config': {
|
| 415 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 416 |
+
"stage1": [64, 64, 128, 1, False, False, 3, 6],
|
| 417 |
+
"stage2": [128, 128, 512, 2, True, False, 3, 6],
|
| 418 |
+
"stage3": [512, 256, 1024, 5, True, True, 5, 6],
|
| 419 |
+
"stage4": [1024, 512, 2048, 2, True, True, 5, 6],
|
| 420 |
+
},
|
| 421 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B5_stage1.pth'
|
| 422 |
+
},
|
| 423 |
+
'B6': {
|
| 424 |
+
'stem_channels': [3, 48, 96],
|
| 425 |
+
'stage_config': {
|
| 426 |
+
# in_channels, mid_channels, out_channels, num_blocks, downsample, light_block, kernel_size, layer_num
|
| 427 |
+
"stage1": [96, 96, 192, 2, False, False, 3, 6],
|
| 428 |
+
"stage2": [192, 192, 512, 3, True, False, 3, 6],
|
| 429 |
+
"stage3": [512, 384, 1024, 6, True, True, 5, 6],
|
| 430 |
+
"stage4": [1024, 768, 2048, 3, True, True, 5, 6],
|
| 431 |
+
},
|
| 432 |
+
'url': 'https://github.com/Peterande/storage/releases/download/dfinev1.0/PPHGNetV2_B6_stage1.pth'
|
| 433 |
+
},
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
def __init__(self,
|
| 437 |
+
name,
|
| 438 |
+
use_lab=False,
|
| 439 |
+
return_idx=[1, 2, 3],
|
| 440 |
+
freeze_stem_only=True,
|
| 441 |
+
freeze_at=0,
|
| 442 |
+
freeze_norm=True,
|
| 443 |
+
pretrained=True,
|
| 444 |
+
local_model_dir='weight/hgnetv2/'):
|
| 445 |
+
super().__init__()
|
| 446 |
+
self.use_lab = use_lab
|
| 447 |
+
self.return_idx = return_idx
|
| 448 |
+
|
| 449 |
+
stem_channels = self.arch_configs[name]['stem_channels']
|
| 450 |
+
stage_config = self.arch_configs[name]['stage_config']
|
| 451 |
+
download_url = self.arch_configs[name]['url']
|
| 452 |
+
|
| 453 |
+
self._out_strides = [4, 8, 16, 32]
|
| 454 |
+
self._out_channels = [stage_config[k][2] for k in stage_config]
|
| 455 |
+
|
| 456 |
+
# stem
|
| 457 |
+
self.stem = StemBlock(
|
| 458 |
+
in_chs=stem_channels[0],
|
| 459 |
+
mid_chs=stem_channels[1],
|
| 460 |
+
out_chs=stem_channels[2],
|
| 461 |
+
use_lab=use_lab)
|
| 462 |
+
|
| 463 |
+
# stages
|
| 464 |
+
self.stages = nn.ModuleList()
|
| 465 |
+
for i, k in enumerate(stage_config):
|
| 466 |
+
in_channels, mid_channels, out_channels, block_num, downsample, light_block, kernel_size, layer_num = stage_config[
|
| 467 |
+
k]
|
| 468 |
+
self.stages.append(
|
| 469 |
+
HG_Stage(
|
| 470 |
+
in_channels,
|
| 471 |
+
mid_channels,
|
| 472 |
+
out_channels,
|
| 473 |
+
block_num,
|
| 474 |
+
layer_num,
|
| 475 |
+
downsample,
|
| 476 |
+
light_block,
|
| 477 |
+
kernel_size,
|
| 478 |
+
use_lab))
|
| 479 |
+
|
| 480 |
+
if freeze_at >= 0:
|
| 481 |
+
self._freeze_parameters(self.stem)
|
| 482 |
+
if not freeze_stem_only:
|
| 483 |
+
for i in range(min(freeze_at + 1, len(self.stages))):
|
| 484 |
+
self._freeze_parameters(self.stages[i])
|
| 485 |
+
|
| 486 |
+
if freeze_norm:
|
| 487 |
+
self._freeze_norm(self)
|
| 488 |
+
|
| 489 |
+
if pretrained:
|
| 490 |
+
RED, GREEN, RESET = "\033[91m", "\033[92m", "\033[0m"
|
| 491 |
+
try:
|
| 492 |
+
model_path = local_model_dir + 'PPHGNetV2_' + name + '_stage1.pth'
|
| 493 |
+
if os.path.exists(model_path):
|
| 494 |
+
state = torch.load(model_path, map_location='cpu')
|
| 495 |
+
print(f"Loaded stage1 {name} HGNetV2 from local file.")
|
| 496 |
+
else:
|
| 497 |
+
# If the file doesn't exist locally, download from the URL
|
| 498 |
+
if torch.distributed.get_rank() == 0:
|
| 499 |
+
print(GREEN + "If the pretrained HGNetV2 can't be downloaded automatically. Please check your network connection." + RESET)
|
| 500 |
+
print(GREEN + "Please check your network connection. Or download the model manually from " + RESET + f"{download_url}" + GREEN + " to " + RESET + f"{local_model_dir}." + RESET)
|
| 501 |
+
state = torch.hub.load_state_dict_from_url(download_url, map_location='cpu', model_dir=local_model_dir)
|
| 502 |
+
torch.distributed.barrier()
|
| 503 |
+
else:
|
| 504 |
+
torch.distributed.barrier()
|
| 505 |
+
state = torch.load(local_model_dir)
|
| 506 |
+
|
| 507 |
+
print(f"Loaded stage1 {name} HGNetV2 from URL.")
|
| 508 |
+
|
| 509 |
+
self.load_state_dict(state)
|
| 510 |
+
|
| 511 |
+
except (Exception, KeyboardInterrupt) as e:
|
| 512 |
+
if torch.distributed.get_rank() == 0:
|
| 513 |
+
print(f"{str(e)}")
|
| 514 |
+
logging.error(RED + "CRITICAL WARNING: Failed to load pretrained HGNetV2 model" + RESET)
|
| 515 |
+
logging.error(GREEN + "Please check your network connection. Or download the model manually from " \
|
| 516 |
+
+ RESET + f"{download_url}" + GREEN + " to " + RESET + f"{local_model_dir}." + RESET)
|
| 517 |
+
exit()
|
| 518 |
+
|
| 519 |
+
|
| 520 |
+
|
| 521 |
+
|
| 522 |
+
def _freeze_norm(self, m: nn.Module):
|
| 523 |
+
if isinstance(m, nn.BatchNorm2d):
|
| 524 |
+
m = FrozenBatchNorm2d(m.num_features)
|
| 525 |
+
else:
|
| 526 |
+
for name, child in m.named_children():
|
| 527 |
+
_child = self._freeze_norm(child)
|
| 528 |
+
if _child is not child:
|
| 529 |
+
setattr(m, name, _child)
|
| 530 |
+
return m
|
| 531 |
+
|
| 532 |
+
def _freeze_parameters(self, m: nn.Module):
|
| 533 |
+
for p in m.parameters():
|
| 534 |
+
p.requires_grad = False
|
| 535 |
+
|
| 536 |
+
def forward(self, x):
|
| 537 |
+
x = self.stem(x)
|
| 538 |
+
outs = []
|
| 539 |
+
for idx, stage in enumerate(self.stages):
|
| 540 |
+
x = stage(x)
|
| 541 |
+
if idx in self.return_idx:
|
| 542 |
+
outs.append(x)
|
| 543 |
+
return outs
|
code/engine/backbone/presnet.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
import torch
|
| 6 |
+
import torch.nn as nn
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
|
| 9 |
+
from collections import OrderedDict
|
| 10 |
+
|
| 11 |
+
from .common import get_activation, FrozenBatchNorm2d
|
| 12 |
+
|
| 13 |
+
from ..core import register
|
| 14 |
+
import os
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
__all__ = ['PResNet']
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
ResNet_cfg = {
|
| 21 |
+
18: [2, 2, 2, 2],
|
| 22 |
+
34: [3, 4, 6, 3],
|
| 23 |
+
50: [3, 4, 6, 3],
|
| 24 |
+
101: [3, 4, 23, 3],
|
| 25 |
+
# 152: [3, 8, 36, 3],
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
donwload_url = {
|
| 30 |
+
18: 'https://github.com/lyuwenyu/storage/releases/download/v0.1/ResNet18_vd_pretrained_from_paddle.pth',
|
| 31 |
+
34: 'https://github.com/lyuwenyu/storage/releases/download/v0.1/ResNet34_vd_pretrained_from_paddle.pth',
|
| 32 |
+
50: 'https://github.com/lyuwenyu/storage/releases/download/v0.1/ResNet50_vd_ssld_v2_pretrained_from_paddle.pth',
|
| 33 |
+
101: 'https://github.com/lyuwenyu/storage/releases/download/v0.1/ResNet101_vd_ssld_pretrained_from_paddle.pth',
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
local_weights = {
|
| 37 |
+
18: "ResNet18_vd_pretrained_from_paddle.pth",
|
| 38 |
+
34: "ResNet34_vd_pretrained_from_paddle.pth",
|
| 39 |
+
50: "ResNet50_vd_ssld_v2_pretrained_from_paddle.pth",
|
| 40 |
+
101: "ResNet101_vd_ssld_pretrained_from_paddle.pth"
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
class ConvNormLayer(nn.Module):
|
| 44 |
+
def __init__(self, ch_in, ch_out, kernel_size, stride, padding=None, bias=False, act=None):
|
| 45 |
+
super().__init__()
|
| 46 |
+
self.conv = nn.Conv2d(
|
| 47 |
+
ch_in,
|
| 48 |
+
ch_out,
|
| 49 |
+
kernel_size,
|
| 50 |
+
stride,
|
| 51 |
+
padding=(kernel_size-1)//2 if padding is None else padding,
|
| 52 |
+
bias=bias)
|
| 53 |
+
self.norm = nn.BatchNorm2d(ch_out)
|
| 54 |
+
self.act = get_activation(act)
|
| 55 |
+
|
| 56 |
+
def forward(self, x):
|
| 57 |
+
return self.act(self.norm(self.conv(x)))
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class BasicBlock(nn.Module):
|
| 61 |
+
expansion = 1
|
| 62 |
+
|
| 63 |
+
def __init__(self, ch_in, ch_out, stride, shortcut, act='relu', variant='b'):
|
| 64 |
+
super().__init__()
|
| 65 |
+
|
| 66 |
+
self.shortcut = shortcut
|
| 67 |
+
|
| 68 |
+
if not shortcut:
|
| 69 |
+
if variant == 'd' and stride == 2:
|
| 70 |
+
self.short = nn.Sequential(OrderedDict([
|
| 71 |
+
('pool', nn.AvgPool2d(2, 2, 0, ceil_mode=True)),
|
| 72 |
+
('conv', ConvNormLayer(ch_in, ch_out, 1, 1))
|
| 73 |
+
]))
|
| 74 |
+
else:
|
| 75 |
+
self.short = ConvNormLayer(ch_in, ch_out, 1, stride)
|
| 76 |
+
|
| 77 |
+
self.branch2a = ConvNormLayer(ch_in, ch_out, 3, stride, act=act)
|
| 78 |
+
self.branch2b = ConvNormLayer(ch_out, ch_out, 3, 1, act=None)
|
| 79 |
+
self.act = nn.Identity() if act is None else get_activation(act)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def forward(self, x):
|
| 83 |
+
out = self.branch2a(x)
|
| 84 |
+
out = self.branch2b(out)
|
| 85 |
+
if self.shortcut:
|
| 86 |
+
short = x
|
| 87 |
+
else:
|
| 88 |
+
short = self.short(x)
|
| 89 |
+
|
| 90 |
+
out = out + short
|
| 91 |
+
out = self.act(out)
|
| 92 |
+
|
| 93 |
+
return out
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class BottleNeck(nn.Module):
|
| 97 |
+
expansion = 4
|
| 98 |
+
|
| 99 |
+
def __init__(self, ch_in, ch_out, stride, shortcut, act='relu', variant='b'):
|
| 100 |
+
super().__init__()
|
| 101 |
+
|
| 102 |
+
if variant == 'a':
|
| 103 |
+
stride1, stride2 = stride, 1
|
| 104 |
+
else:
|
| 105 |
+
stride1, stride2 = 1, stride
|
| 106 |
+
|
| 107 |
+
width = ch_out
|
| 108 |
+
|
| 109 |
+
self.branch2a = ConvNormLayer(ch_in, width, 1, stride1, act=act)
|
| 110 |
+
self.branch2b = ConvNormLayer(width, width, 3, stride2, act=act)
|
| 111 |
+
self.branch2c = ConvNormLayer(width, ch_out * self.expansion, 1, 1)
|
| 112 |
+
|
| 113 |
+
self.shortcut = shortcut
|
| 114 |
+
if not shortcut:
|
| 115 |
+
if variant == 'd' and stride == 2:
|
| 116 |
+
self.short = nn.Sequential(OrderedDict([
|
| 117 |
+
('pool', nn.AvgPool2d(2, 2, 0, ceil_mode=True)),
|
| 118 |
+
('conv', ConvNormLayer(ch_in, ch_out * self.expansion, 1, 1))
|
| 119 |
+
]))
|
| 120 |
+
else:
|
| 121 |
+
self.short = ConvNormLayer(ch_in, ch_out * self.expansion, 1, stride)
|
| 122 |
+
|
| 123 |
+
self.act = nn.Identity() if act is None else get_activation(act)
|
| 124 |
+
|
| 125 |
+
def forward(self, x):
|
| 126 |
+
out = self.branch2a(x)
|
| 127 |
+
out = self.branch2b(out)
|
| 128 |
+
out = self.branch2c(out)
|
| 129 |
+
|
| 130 |
+
if self.shortcut:
|
| 131 |
+
short = x
|
| 132 |
+
else:
|
| 133 |
+
short = self.short(x)
|
| 134 |
+
|
| 135 |
+
out = out + short
|
| 136 |
+
out = self.act(out)
|
| 137 |
+
|
| 138 |
+
return out
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
class Blocks(nn.Module):
|
| 142 |
+
def __init__(self, block, ch_in, ch_out, count, stage_num, act='relu', variant='b'):
|
| 143 |
+
super().__init__()
|
| 144 |
+
|
| 145 |
+
self.blocks = nn.ModuleList()
|
| 146 |
+
for i in range(count):
|
| 147 |
+
self.blocks.append(
|
| 148 |
+
block(
|
| 149 |
+
ch_in,
|
| 150 |
+
ch_out,
|
| 151 |
+
stride=2 if i == 0 and stage_num != 2 else 1,
|
| 152 |
+
shortcut=False if i == 0 else True,
|
| 153 |
+
variant=variant,
|
| 154 |
+
act=act)
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
if i == 0:
|
| 158 |
+
ch_in = ch_out * block.expansion
|
| 159 |
+
|
| 160 |
+
def forward(self, x):
|
| 161 |
+
out = x
|
| 162 |
+
for block in self.blocks:
|
| 163 |
+
out = block(out)
|
| 164 |
+
return out
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
@register()
|
| 168 |
+
class PResNet(nn.Module):
|
| 169 |
+
def __init__(
|
| 170 |
+
self,
|
| 171 |
+
depth,
|
| 172 |
+
variant='d',
|
| 173 |
+
num_stages=4,
|
| 174 |
+
return_idx=[0, 1, 2, 3],
|
| 175 |
+
act='relu',
|
| 176 |
+
freeze_at=-1,
|
| 177 |
+
freeze_norm=True,
|
| 178 |
+
pretrained=False,
|
| 179 |
+
local_model_dir='weights/resnets',
|
| 180 |
+
):
|
| 181 |
+
super().__init__()
|
| 182 |
+
|
| 183 |
+
block_nums = ResNet_cfg[depth]
|
| 184 |
+
ch_in = 64
|
| 185 |
+
if variant in ['c', 'd']:
|
| 186 |
+
conv_def = [
|
| 187 |
+
[3, ch_in // 2, 3, 2, "conv1_1"],
|
| 188 |
+
[ch_in // 2, ch_in // 2, 3, 1, "conv1_2"],
|
| 189 |
+
[ch_in // 2, ch_in, 3, 1, "conv1_3"],
|
| 190 |
+
]
|
| 191 |
+
else:
|
| 192 |
+
conv_def = [[3, ch_in, 7, 2, "conv1_1"]]
|
| 193 |
+
|
| 194 |
+
self.conv1 = nn.Sequential(OrderedDict([
|
| 195 |
+
(name, ConvNormLayer(cin, cout, k, s, act=act)) for cin, cout, k, s, name in conv_def
|
| 196 |
+
]))
|
| 197 |
+
|
| 198 |
+
ch_out_list = [64, 128, 256, 512]
|
| 199 |
+
block = BottleNeck if depth >= 50 else BasicBlock
|
| 200 |
+
|
| 201 |
+
_out_channels = [block.expansion * v for v in ch_out_list]
|
| 202 |
+
_out_strides = [4, 8, 16, 32]
|
| 203 |
+
|
| 204 |
+
self.res_layers = nn.ModuleList()
|
| 205 |
+
for i in range(num_stages):
|
| 206 |
+
stage_num = i + 2
|
| 207 |
+
self.res_layers.append(
|
| 208 |
+
Blocks(block, ch_in, ch_out_list[i], block_nums[i], stage_num, act=act, variant=variant)
|
| 209 |
+
)
|
| 210 |
+
ch_in = _out_channels[i]
|
| 211 |
+
|
| 212 |
+
self.return_idx = return_idx
|
| 213 |
+
self.out_channels = [_out_channels[_i] for _i in return_idx]
|
| 214 |
+
self.out_strides = [_out_strides[_i] for _i in return_idx]
|
| 215 |
+
|
| 216 |
+
if freeze_at >= 0:
|
| 217 |
+
self._freeze_parameters(self.conv1)
|
| 218 |
+
for i in range(min(freeze_at, num_stages)):
|
| 219 |
+
self._freeze_parameters(self.res_layers[i])
|
| 220 |
+
|
| 221 |
+
if freeze_norm:
|
| 222 |
+
self._freeze_norm(self)
|
| 223 |
+
|
| 224 |
+
if pretrained:
|
| 225 |
+
model_path = local_model_dir + local_weights[depth]
|
| 226 |
+
if os.path.exists(model_path):
|
| 227 |
+
state = torch.load(model_path, map_location='cpu')
|
| 228 |
+
print(f"Loaded PResNet{depth} from local file@{model_path}.")
|
| 229 |
+
else:
|
| 230 |
+
if isinstance(pretrained, bool) or 'http' in pretrained:
|
| 231 |
+
state = torch.hub.load_state_dict_from_url(donwload_url[depth], map_location='cpu', model_dir=local_model_dir)
|
| 232 |
+
else:
|
| 233 |
+
state = torch.load(pretrained, map_location='cpu')
|
| 234 |
+
self.load_state_dict(state)
|
| 235 |
+
print(f'Load PResNet{depth} state_dict')
|
| 236 |
+
|
| 237 |
+
def _freeze_parameters(self, m: nn.Module):
|
| 238 |
+
for p in m.parameters():
|
| 239 |
+
p.requires_grad = False
|
| 240 |
+
|
| 241 |
+
def _freeze_norm(self, m: nn.Module):
|
| 242 |
+
if isinstance(m, nn.BatchNorm2d):
|
| 243 |
+
m = FrozenBatchNorm2d(m.num_features)
|
| 244 |
+
else:
|
| 245 |
+
for name, child in m.named_children():
|
| 246 |
+
_child = self._freeze_norm(child)
|
| 247 |
+
if _child is not child:
|
| 248 |
+
setattr(m, name, _child)
|
| 249 |
+
return m
|
| 250 |
+
|
| 251 |
+
def forward(self, x):
|
| 252 |
+
conv1 = self.conv1(x)
|
| 253 |
+
x = F.max_pool2d(conv1, kernel_size=3, stride=2, padding=1)
|
| 254 |
+
outs = []
|
| 255 |
+
for idx, stage in enumerate(self.res_layers):
|
| 256 |
+
x = stage(x)
|
| 257 |
+
if idx in self.return_idx:
|
| 258 |
+
outs.append(x)
|
| 259 |
+
return outs
|
code/engine/backbone/test_resnet.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
|
| 5 |
+
from collections import OrderedDict
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
from ..core import register
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class BasicBlock(nn.Module):
|
| 12 |
+
expansion = 1
|
| 13 |
+
|
| 14 |
+
def __init__(self, in_planes, planes, stride=1):
|
| 15 |
+
super(BasicBlock, self).__init__()
|
| 16 |
+
|
| 17 |
+
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
|
| 18 |
+
self.bn1 = nn.BatchNorm2d(planes)
|
| 19 |
+
|
| 20 |
+
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,stride=1, padding=1, bias=False)
|
| 21 |
+
self.bn2 = nn.BatchNorm2d(planes)
|
| 22 |
+
|
| 23 |
+
self.shortcut = nn.Sequential()
|
| 24 |
+
if stride != 1 or in_planes != self.expansion*planes:
|
| 25 |
+
self.shortcut = nn.Sequential(
|
| 26 |
+
nn.Conv2d(in_planes, self.expansion*planes,kernel_size=1, stride=stride, bias=False),
|
| 27 |
+
nn.BatchNorm2d(self.expansion*planes)
|
| 28 |
+
)
|
| 29 |
+
def forward(self, x):
|
| 30 |
+
out = F.relu(self.bn1(self.conv1(x)))
|
| 31 |
+
out = self.bn2(self.conv2(out))
|
| 32 |
+
out += self.shortcut(x)
|
| 33 |
+
out = F.relu(out)
|
| 34 |
+
return out
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class _ResNet(nn.Module):
|
| 39 |
+
def __init__(self, block, num_blocks, num_classes=10):
|
| 40 |
+
super().__init__()
|
| 41 |
+
self.in_planes = 64
|
| 42 |
+
|
| 43 |
+
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
|
| 44 |
+
self.bn1 = nn.BatchNorm2d(64)
|
| 45 |
+
|
| 46 |
+
self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
|
| 47 |
+
self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
|
| 48 |
+
self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
|
| 49 |
+
self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
|
| 50 |
+
|
| 51 |
+
self.linear = nn.Linear(512 * block.expansion, num_classes)
|
| 52 |
+
|
| 53 |
+
def _make_layer(self, block, planes, num_blocks, stride):
|
| 54 |
+
strides = [stride] + [1]*(num_blocks-1)
|
| 55 |
+
layers = []
|
| 56 |
+
for stride in strides:
|
| 57 |
+
layers.append(block(self.in_planes, planes, stride))
|
| 58 |
+
self.in_planes = planes * block.expansion
|
| 59 |
+
return nn.Sequential(*layers)
|
| 60 |
+
|
| 61 |
+
def forward(self, x):
|
| 62 |
+
out = F.relu(self.bn1(self.conv1(x)))
|
| 63 |
+
out = self.layer1(out)
|
| 64 |
+
out = self.layer2(out)
|
| 65 |
+
out = self.layer3(out)
|
| 66 |
+
out = self.layer4(out)
|
| 67 |
+
out = F.avg_pool2d(out, 4)
|
| 68 |
+
out = out.view(out.size(0), -1)
|
| 69 |
+
out = self.linear(out)
|
| 70 |
+
return out
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
@register()
|
| 74 |
+
class MResNet(nn.Module):
|
| 75 |
+
def __init__(self, num_classes=10, num_blocks=[2, 2, 2, 2]) -> None:
|
| 76 |
+
super().__init__()
|
| 77 |
+
self.model = _ResNet(BasicBlock, num_blocks, num_classes)
|
| 78 |
+
|
| 79 |
+
def forward(self, x):
|
| 80 |
+
return self.model(x)
|
code/engine/backbone/timm_model.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 2 |
+
|
| 3 |
+
https://towardsdatascience.com/getting-started-with-pytorch-image-models-timm-a-practitioners-guide-4e77b4bf9055#0583
|
| 4 |
+
"""
|
| 5 |
+
import torch
|
| 6 |
+
from torchvision.models.feature_extraction import get_graph_node_names, create_feature_extractor
|
| 7 |
+
|
| 8 |
+
from .utils import IntermediateLayerGetter
|
| 9 |
+
from ..core import register
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@register()
|
| 13 |
+
class TimmModel(torch.nn.Module):
|
| 14 |
+
def __init__(self, \
|
| 15 |
+
name,
|
| 16 |
+
return_layers,
|
| 17 |
+
pretrained=False,
|
| 18 |
+
exportable=True,
|
| 19 |
+
features_only=True,
|
| 20 |
+
**kwargs) -> None:
|
| 21 |
+
|
| 22 |
+
super().__init__()
|
| 23 |
+
|
| 24 |
+
import timm
|
| 25 |
+
model = timm.create_model(
|
| 26 |
+
name,
|
| 27 |
+
pretrained=pretrained,
|
| 28 |
+
exportable=exportable,
|
| 29 |
+
features_only=features_only,
|
| 30 |
+
**kwargs
|
| 31 |
+
)
|
| 32 |
+
# nodes, _ = get_graph_node_names(model)
|
| 33 |
+
# print(nodes)
|
| 34 |
+
# features = {'': ''}
|
| 35 |
+
# model = create_feature_extractor(model, return_nodes=features)
|
| 36 |
+
|
| 37 |
+
assert set(return_layers).issubset(model.feature_info.module_name()), \
|
| 38 |
+
f'return_layers should be a subset of {model.feature_info.module_name()}'
|
| 39 |
+
|
| 40 |
+
# self.model = model
|
| 41 |
+
self.model = IntermediateLayerGetter(model, return_layers)
|
| 42 |
+
|
| 43 |
+
return_idx = [model.feature_info.module_name().index(name) for name in return_layers]
|
| 44 |
+
self.strides = [model.feature_info.reduction()[i] for i in return_idx]
|
| 45 |
+
self.channels = [model.feature_info.channels()[i] for i in return_idx]
|
| 46 |
+
self.return_idx = return_idx
|
| 47 |
+
self.return_layers = return_layers
|
| 48 |
+
|
| 49 |
+
def forward(self, x: torch.Tensor):
|
| 50 |
+
outputs = self.model(x)
|
| 51 |
+
# outputs = [outputs[i] for i in self.return_idx]
|
| 52 |
+
return outputs
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
if __name__ == '__main__':
|
| 56 |
+
|
| 57 |
+
model = TimmModel(name='resnet34', return_layers=['layer2', 'layer3'])
|
| 58 |
+
data = torch.rand(1, 3, 640, 640)
|
| 59 |
+
outputs = model(data)
|
| 60 |
+
|
| 61 |
+
for output in outputs:
|
| 62 |
+
print(output.shape)
|
| 63 |
+
|
| 64 |
+
"""
|
| 65 |
+
model:
|
| 66 |
+
type: TimmModel
|
| 67 |
+
name: resnet34
|
| 68 |
+
return_layers: ['layer2', 'layer4']
|
| 69 |
+
"""
|
code/engine/backbone/torchvision_model.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torchvision
|
| 8 |
+
|
| 9 |
+
from ..core import register
|
| 10 |
+
from .utils import IntermediateLayerGetter
|
| 11 |
+
|
| 12 |
+
__all__ = ['TorchVisionModel']
|
| 13 |
+
|
| 14 |
+
@register()
|
| 15 |
+
class TorchVisionModel(torch.nn.Module):
|
| 16 |
+
def __init__(self, name, return_layers, weights=None, **kwargs) -> None:
|
| 17 |
+
super().__init__()
|
| 18 |
+
|
| 19 |
+
if weights is not None:
|
| 20 |
+
weights = getattr(torchvision.models.get_model_weights(name), weights)
|
| 21 |
+
|
| 22 |
+
model = torchvision.models.get_model(name, weights=weights, **kwargs)
|
| 23 |
+
|
| 24 |
+
# TODO hard code.
|
| 25 |
+
if hasattr(model, 'features'):
|
| 26 |
+
model = IntermediateLayerGetter(model.features, return_layers)
|
| 27 |
+
else:
|
| 28 |
+
model = IntermediateLayerGetter(model, return_layers)
|
| 29 |
+
|
| 30 |
+
self.model = model
|
| 31 |
+
|
| 32 |
+
def forward(self, x):
|
| 33 |
+
return self.model(x)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
# TorchVisionModel('swin_t', return_layers=['5', '7'])
|
| 37 |
+
# TorchVisionModel('resnet34', return_layers=['layer2','layer3', 'layer4'])
|
| 38 |
+
|
| 39 |
+
# TorchVisionModel:
|
| 40 |
+
# name: swin_t
|
| 41 |
+
# return_layers: ['5', '7']
|
| 42 |
+
# weights: DEFAULT
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
# model:
|
| 46 |
+
# type: TorchVisionModel
|
| 47 |
+
# name: resnet34
|
| 48 |
+
# return_layers: ['layer2','layer3', 'layer4']
|
| 49 |
+
# weights: DEFAULT
|
code/engine/backbone/utils.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
https://github.com/pytorch/vision/blob/main/torchvision/models/_utils.py
|
| 3 |
+
|
| 4 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from collections import OrderedDict
|
| 8 |
+
from typing import Dict, List
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
import torch.nn as nn
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class IntermediateLayerGetter(nn.ModuleDict):
|
| 15 |
+
"""
|
| 16 |
+
Module wrapper that returns intermediate layers from a model
|
| 17 |
+
|
| 18 |
+
It has a strong assumption that the modules have been registered
|
| 19 |
+
into the model in the same order as they are used.
|
| 20 |
+
This means that one should **not** reuse the same nn.Module
|
| 21 |
+
twice in the forward if you want this to work.
|
| 22 |
+
|
| 23 |
+
Additionally, it is only able to query submodules that are directly
|
| 24 |
+
assigned to the model. So if `model` is passed, `model.feature1` can
|
| 25 |
+
be returned, but not `model.feature1.layer2`.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
_version = 3
|
| 29 |
+
|
| 30 |
+
def __init__(self, model: nn.Module, return_layers: List[str]) -> None:
|
| 31 |
+
if not set(return_layers).issubset([name for name, _ in model.named_children()]):
|
| 32 |
+
raise ValueError("return_layers are not present in model. {}"\
|
| 33 |
+
.format([name for name, _ in model.named_children()]))
|
| 34 |
+
orig_return_layers = return_layers
|
| 35 |
+
return_layers = {str(k): str(k) for k in return_layers}
|
| 36 |
+
layers = OrderedDict()
|
| 37 |
+
for name, module in model.named_children():
|
| 38 |
+
layers[name] = module
|
| 39 |
+
if name in return_layers:
|
| 40 |
+
del return_layers[name]
|
| 41 |
+
if not return_layers:
|
| 42 |
+
break
|
| 43 |
+
|
| 44 |
+
super().__init__(layers)
|
| 45 |
+
self.return_layers = orig_return_layers
|
| 46 |
+
|
| 47 |
+
def forward(self, x):
|
| 48 |
+
outputs = []
|
| 49 |
+
for name, module in self.items():
|
| 50 |
+
x = module(x)
|
| 51 |
+
if name in self.return_layers:
|
| 52 |
+
outputs.append(x)
|
| 53 |
+
|
| 54 |
+
return outputs
|
code/engine/core/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .workspace import GLOBAL_CONFIG, register, create
|
| 7 |
+
from .yaml_utils import *
|
| 8 |
+
from ._config import BaseConfig
|
| 9 |
+
from .yaml_config import YAMLConfig
|
code/engine/core/_config.py
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
from torch.utils.data import Dataset, DataLoader
|
| 9 |
+
from torch.optim import Optimizer
|
| 10 |
+
from torch.optim.lr_scheduler import LRScheduler
|
| 11 |
+
from torch.cuda.amp.grad_scaler import GradScaler
|
| 12 |
+
from torch.utils.tensorboard import SummaryWriter
|
| 13 |
+
|
| 14 |
+
from pathlib import Path
|
| 15 |
+
from typing import Callable, List, Dict
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
__all__ = ['BaseConfig', ]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class BaseConfig(object):
|
| 22 |
+
# TODO property
|
| 23 |
+
|
| 24 |
+
def __init__(self) -> None:
|
| 25 |
+
super().__init__()
|
| 26 |
+
|
| 27 |
+
self.task :str = None
|
| 28 |
+
|
| 29 |
+
# instance / function
|
| 30 |
+
self._model :nn.Module = None
|
| 31 |
+
self._postprocessor :nn.Module = None
|
| 32 |
+
self._criterion :nn.Module = None
|
| 33 |
+
self._optimizer :Optimizer = None
|
| 34 |
+
self._lr_scheduler :LRScheduler = None
|
| 35 |
+
self._lr_warmup_scheduler: LRScheduler = None
|
| 36 |
+
self._train_dataloader :DataLoader = None
|
| 37 |
+
self._val_dataloader :DataLoader = None
|
| 38 |
+
self._ema :nn.Module = None
|
| 39 |
+
self._scaler :GradScaler = None
|
| 40 |
+
self._train_dataset :Dataset = None
|
| 41 |
+
self._val_dataset :Dataset = None
|
| 42 |
+
self._collate_fn :Callable = None
|
| 43 |
+
self._evaluator :Callable[[nn.Module, DataLoader, str], ] = None
|
| 44 |
+
self._writer: SummaryWriter = None
|
| 45 |
+
|
| 46 |
+
# dataset
|
| 47 |
+
self.num_workers :int = 0
|
| 48 |
+
self.batch_size :int = None
|
| 49 |
+
self._train_batch_size :int = None
|
| 50 |
+
self._val_batch_size :int = None
|
| 51 |
+
self._train_shuffle: bool = None
|
| 52 |
+
self._val_shuffle: bool = None
|
| 53 |
+
|
| 54 |
+
# runtime
|
| 55 |
+
self.resume :str = None
|
| 56 |
+
self.tuning :str = None
|
| 57 |
+
|
| 58 |
+
self.epoches :int = None
|
| 59 |
+
self.last_epoch :int = -1
|
| 60 |
+
|
| 61 |
+
# new_add for support self-defined cosine FIXME
|
| 62 |
+
self.lrsheduler: str = None
|
| 63 |
+
self.lr_gamma: float = None
|
| 64 |
+
self.no_aug_epoch: int = None
|
| 65 |
+
self.warmup_iter: int = None
|
| 66 |
+
self.flat_epoch: int = None
|
| 67 |
+
|
| 68 |
+
self.use_amp :bool = False
|
| 69 |
+
self.use_ema :bool = False
|
| 70 |
+
self.ema_decay :float = 0.9999
|
| 71 |
+
self.ema_warmups: int = 2000
|
| 72 |
+
self.sync_bn :bool = False
|
| 73 |
+
self.clip_max_norm : float = 0.
|
| 74 |
+
self.find_unused_parameters :bool = None
|
| 75 |
+
|
| 76 |
+
self.seed :int = None
|
| 77 |
+
self.print_freq :int = None
|
| 78 |
+
self.checkpoint_freq :int = 1
|
| 79 |
+
self.output_dir :str = None
|
| 80 |
+
self.summary_dir :str = None
|
| 81 |
+
self.device : str = ''
|
| 82 |
+
|
| 83 |
+
@property
|
| 84 |
+
def model(self, ) -> nn.Module:
|
| 85 |
+
return self._model
|
| 86 |
+
|
| 87 |
+
@model.setter
|
| 88 |
+
def model(self, m):
|
| 89 |
+
assert isinstance(m, nn.Module), f'{type(m)} != nn.Module, please check your model class'
|
| 90 |
+
self._model = m
|
| 91 |
+
|
| 92 |
+
@property
|
| 93 |
+
def postprocessor(self, ) -> nn.Module:
|
| 94 |
+
return self._postprocessor
|
| 95 |
+
|
| 96 |
+
@postprocessor.setter
|
| 97 |
+
def postprocessor(self, m):
|
| 98 |
+
assert isinstance(m, nn.Module), f'{type(m)} != nn.Module, please check your model class'
|
| 99 |
+
self._postprocessor = m
|
| 100 |
+
|
| 101 |
+
@property
|
| 102 |
+
def criterion(self, ) -> nn.Module:
|
| 103 |
+
return self._criterion
|
| 104 |
+
|
| 105 |
+
@criterion.setter
|
| 106 |
+
def criterion(self, m):
|
| 107 |
+
assert isinstance(m, nn.Module), f'{type(m)} != nn.Module, please check your model class'
|
| 108 |
+
self._criterion = m
|
| 109 |
+
|
| 110 |
+
@property
|
| 111 |
+
def optimizer(self, ) -> Optimizer:
|
| 112 |
+
return self._optimizer
|
| 113 |
+
|
| 114 |
+
@optimizer.setter
|
| 115 |
+
def optimizer(self, m):
|
| 116 |
+
assert isinstance(m, Optimizer), f'{type(m)} != optim.Optimizer, please check your model class'
|
| 117 |
+
self._optimizer = m
|
| 118 |
+
|
| 119 |
+
@property
|
| 120 |
+
def lr_scheduler(self, ) -> LRScheduler:
|
| 121 |
+
return self._lr_scheduler
|
| 122 |
+
|
| 123 |
+
@lr_scheduler.setter
|
| 124 |
+
def lr_scheduler(self, m):
|
| 125 |
+
assert isinstance(m, LRScheduler), f'{type(m)} != LRScheduler, please check your model class'
|
| 126 |
+
self._lr_scheduler = m
|
| 127 |
+
|
| 128 |
+
@property
|
| 129 |
+
def lr_warmup_scheduler(self, ) -> LRScheduler:
|
| 130 |
+
return self._lr_warmup_scheduler
|
| 131 |
+
|
| 132 |
+
@lr_warmup_scheduler.setter
|
| 133 |
+
def lr_warmup_scheduler(self, m):
|
| 134 |
+
self._lr_warmup_scheduler = m
|
| 135 |
+
|
| 136 |
+
@property
|
| 137 |
+
def train_dataloader(self) -> DataLoader:
|
| 138 |
+
if self._train_dataloader is None and self.train_dataset is not None:
|
| 139 |
+
loader = DataLoader(self.train_dataset,
|
| 140 |
+
batch_size=self.train_batch_size,
|
| 141 |
+
num_workers=self.num_workers,
|
| 142 |
+
collate_fn=self.collate_fn,
|
| 143 |
+
shuffle=self.train_shuffle, )
|
| 144 |
+
loader.shuffle = self.train_shuffle
|
| 145 |
+
self._train_dataloader = loader
|
| 146 |
+
|
| 147 |
+
return self._train_dataloader
|
| 148 |
+
|
| 149 |
+
@train_dataloader.setter
|
| 150 |
+
def train_dataloader(self, loader):
|
| 151 |
+
self._train_dataloader = loader
|
| 152 |
+
|
| 153 |
+
@property
|
| 154 |
+
def val_dataloader(self) -> DataLoader:
|
| 155 |
+
if self._val_dataloader is None and self.val_dataset is not None:
|
| 156 |
+
loader = DataLoader(self.val_dataset,
|
| 157 |
+
batch_size=self.val_batch_size,
|
| 158 |
+
num_workers=self.num_workers,
|
| 159 |
+
drop_last=False,
|
| 160 |
+
collate_fn=self.collate_fn,
|
| 161 |
+
shuffle=self.val_shuffle,
|
| 162 |
+
persistent_workers=True)
|
| 163 |
+
loader.shuffle = self.val_shuffle
|
| 164 |
+
self._val_dataloader = loader
|
| 165 |
+
|
| 166 |
+
return self._val_dataloader
|
| 167 |
+
|
| 168 |
+
@val_dataloader.setter
|
| 169 |
+
def val_dataloader(self, loader):
|
| 170 |
+
self._val_dataloader = loader
|
| 171 |
+
|
| 172 |
+
@property
|
| 173 |
+
def ema(self, ) -> nn.Module:
|
| 174 |
+
if self._ema is None and self.use_ema and self.model is not None:
|
| 175 |
+
from ..optim import ModelEMA
|
| 176 |
+
self._ema = ModelEMA(self.model, self.ema_decay, self.ema_warmups)
|
| 177 |
+
return self._ema
|
| 178 |
+
|
| 179 |
+
@ema.setter
|
| 180 |
+
def ema(self, obj):
|
| 181 |
+
self._ema = obj
|
| 182 |
+
|
| 183 |
+
@property
|
| 184 |
+
def scaler(self) -> GradScaler:
|
| 185 |
+
if self._scaler is None and self.use_amp and torch.cuda.is_available():
|
| 186 |
+
self._scaler = GradScaler()
|
| 187 |
+
return self._scaler
|
| 188 |
+
|
| 189 |
+
@scaler.setter
|
| 190 |
+
def scaler(self, obj: GradScaler):
|
| 191 |
+
self._scaler = obj
|
| 192 |
+
|
| 193 |
+
@property
|
| 194 |
+
def val_shuffle(self) -> bool:
|
| 195 |
+
if self._val_shuffle is None:
|
| 196 |
+
print('warning: set default val_shuffle=False')
|
| 197 |
+
return False
|
| 198 |
+
return self._val_shuffle
|
| 199 |
+
|
| 200 |
+
@val_shuffle.setter
|
| 201 |
+
def val_shuffle(self, shuffle):
|
| 202 |
+
assert isinstance(shuffle, bool), 'shuffle must be bool'
|
| 203 |
+
self._val_shuffle = shuffle
|
| 204 |
+
|
| 205 |
+
@property
|
| 206 |
+
def train_shuffle(self) -> bool:
|
| 207 |
+
if self._train_shuffle is None:
|
| 208 |
+
print('warning: set default train_shuffle=True')
|
| 209 |
+
return True
|
| 210 |
+
return self._train_shuffle
|
| 211 |
+
|
| 212 |
+
@train_shuffle.setter
|
| 213 |
+
def train_shuffle(self, shuffle):
|
| 214 |
+
assert isinstance(shuffle, bool), 'shuffle must be bool'
|
| 215 |
+
self._train_shuffle = shuffle
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
@property
|
| 219 |
+
def train_batch_size(self) -> int:
|
| 220 |
+
if self._train_batch_size is None and isinstance(self.batch_size, int):
|
| 221 |
+
print(f'warning: set train_batch_size=batch_size={self.batch_size}')
|
| 222 |
+
return self.batch_size
|
| 223 |
+
return self._train_batch_size
|
| 224 |
+
|
| 225 |
+
@train_batch_size.setter
|
| 226 |
+
def train_batch_size(self, batch_size):
|
| 227 |
+
assert isinstance(batch_size, int), 'batch_size must be int'
|
| 228 |
+
self._train_batch_size = batch_size
|
| 229 |
+
|
| 230 |
+
@property
|
| 231 |
+
def val_batch_size(self) -> int:
|
| 232 |
+
if self._val_batch_size is None:
|
| 233 |
+
print(f'warning: set val_batch_size=batch_size={self.batch_size}')
|
| 234 |
+
return self.batch_size
|
| 235 |
+
return self._val_batch_size
|
| 236 |
+
|
| 237 |
+
@val_batch_size.setter
|
| 238 |
+
def val_batch_size(self, batch_size):
|
| 239 |
+
assert isinstance(batch_size, int), 'batch_size must be int'
|
| 240 |
+
self._val_batch_size = batch_size
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
@property
|
| 244 |
+
def train_dataset(self) -> Dataset:
|
| 245 |
+
return self._train_dataset
|
| 246 |
+
|
| 247 |
+
@train_dataset.setter
|
| 248 |
+
def train_dataset(self, dataset):
|
| 249 |
+
assert isinstance(dataset, Dataset), f'{type(dataset)} must be Dataset'
|
| 250 |
+
self._train_dataset = dataset
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
@property
|
| 254 |
+
def val_dataset(self) -> Dataset:
|
| 255 |
+
return self._val_dataset
|
| 256 |
+
|
| 257 |
+
@val_dataset.setter
|
| 258 |
+
def val_dataset(self, dataset):
|
| 259 |
+
assert isinstance(dataset, Dataset), f'{type(dataset)} must be Dataset'
|
| 260 |
+
self._val_dataset = dataset
|
| 261 |
+
|
| 262 |
+
@property
|
| 263 |
+
def collate_fn(self) -> Callable:
|
| 264 |
+
return self._collate_fn
|
| 265 |
+
|
| 266 |
+
@collate_fn.setter
|
| 267 |
+
def collate_fn(self, fn):
|
| 268 |
+
assert isinstance(fn, Callable), f'{type(fn)} must be Callable'
|
| 269 |
+
self._collate_fn = fn
|
| 270 |
+
|
| 271 |
+
@property
|
| 272 |
+
def evaluator(self) -> Callable:
|
| 273 |
+
return self._evaluator
|
| 274 |
+
|
| 275 |
+
@evaluator.setter
|
| 276 |
+
def evaluator(self, fn):
|
| 277 |
+
assert isinstance(fn, Callable), f'{type(fn)} must be Callable'
|
| 278 |
+
self._evaluator = fn
|
| 279 |
+
|
| 280 |
+
@property
|
| 281 |
+
def writer(self) -> SummaryWriter:
|
| 282 |
+
if self._writer is None:
|
| 283 |
+
if self.summary_dir:
|
| 284 |
+
self._writer = SummaryWriter(self.summary_dir)
|
| 285 |
+
elif self.output_dir:
|
| 286 |
+
self._writer = SummaryWriter(Path(self.output_dir) / 'summary')
|
| 287 |
+
return self._writer
|
| 288 |
+
|
| 289 |
+
@writer.setter
|
| 290 |
+
def writer(self, m):
|
| 291 |
+
assert isinstance(m, SummaryWriter), f'{type(m)} must be SummaryWriter'
|
| 292 |
+
self._writer = m
|
| 293 |
+
|
| 294 |
+
def __repr__(self, ):
|
| 295 |
+
s = ''
|
| 296 |
+
for k, v in self.__dict__.items():
|
| 297 |
+
if not k.startswith('_'):
|
| 298 |
+
s += f'{k}: {v}\n'
|
| 299 |
+
return s
|
code/engine/core/workspace.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Copied from RT-DETR (https://github.com/lyuwenyu/RT-DETR)
|
| 3 |
+
Copyright(c) 2023 lyuwenyu. All Rights Reserved.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import inspect
|
| 7 |
+
import importlib
|
| 8 |
+
import functools
|
| 9 |
+
from collections import defaultdict
|
| 10 |
+
from typing import Any, Dict, Optional, List
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
GLOBAL_CONFIG = defaultdict(dict)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def register(dct :Any=GLOBAL_CONFIG, name=None, force=False):
|
| 17 |
+
"""
|
| 18 |
+
dct:
|
| 19 |
+
if dct is Dict, register foo into dct as key-value pair
|
| 20 |
+
if dct is Clas, register as modules attibute
|
| 21 |
+
force
|
| 22 |
+
whether force register.
|
| 23 |
+
"""
|
| 24 |
+
def decorator(foo):
|
| 25 |
+
register_name = foo.__name__ if name is None else name
|
| 26 |
+
if not force:
|
| 27 |
+
if inspect.isclass(dct):
|
| 28 |
+
assert not hasattr(dct, foo.__name__), \
|
| 29 |
+
f'module {dct.__name__} has {foo.__name__}'
|
| 30 |
+
else:
|
| 31 |
+
assert foo.__name__ not in dct, \
|
| 32 |
+
f'{foo.__name__} has been already registered'
|
| 33 |
+
|
| 34 |
+
if inspect.isfunction(foo):
|
| 35 |
+
@functools.wraps(foo)
|
| 36 |
+
def wrap_func(*args, **kwargs):
|
| 37 |
+
return foo(*args, **kwargs)
|
| 38 |
+
if isinstance(dct, dict):
|
| 39 |
+
dct[foo.__name__] = wrap_func
|
| 40 |
+
elif inspect.isclass(dct):
|
| 41 |
+
setattr(dct, foo.__name__, wrap_func)
|
| 42 |
+
else:
|
| 43 |
+
raise AttributeError('')
|
| 44 |
+
return wrap_func
|
| 45 |
+
|
| 46 |
+
elif inspect.isclass(foo):
|
| 47 |
+
dct[register_name] = extract_schema(foo)
|
| 48 |
+
|
| 49 |
+
else:
|
| 50 |
+
raise ValueError(f'Do not support {type(foo)} register')
|
| 51 |
+
|
| 52 |
+
return foo
|
| 53 |
+
|
| 54 |
+
return decorator
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def extract_schema(module: type):
|
| 59 |
+
"""
|
| 60 |
+
Args:
|
| 61 |
+
module (type),
|
| 62 |
+
Return:
|
| 63 |
+
Dict,
|
| 64 |
+
"""
|
| 65 |
+
argspec = inspect.getfullargspec(module.__init__)
|
| 66 |
+
arg_names = [arg for arg in argspec.args if arg != 'self']
|
| 67 |
+
num_defualts = len(argspec.defaults) if argspec.defaults is not None else 0
|
| 68 |
+
num_requires = len(arg_names) - num_defualts
|
| 69 |
+
|
| 70 |
+
schame = dict()
|
| 71 |
+
schame['_name'] = module.__name__
|
| 72 |
+
schame['_pymodule'] = importlib.import_module(module.__module__)
|
| 73 |
+
schame['_inject'] = getattr(module, '__inject__', [])
|
| 74 |
+
schame['_share'] = getattr(module, '__share__', [])
|
| 75 |
+
schame['_kwargs'] = {}
|
| 76 |
+
for i, name in enumerate(arg_names):
|
| 77 |
+
if name in schame['_share']:
|
| 78 |
+
assert i >= num_requires, 'share config must have default value.'
|
| 79 |
+
value = argspec.defaults[i - num_requires]
|
| 80 |
+
|
| 81 |
+
elif i >= num_requires:
|
| 82 |
+
value = argspec.defaults[i - num_requires]
|
| 83 |
+
|
| 84 |
+
else:
|
| 85 |
+
value = None
|
| 86 |
+
|
| 87 |
+
schame[name] = value
|
| 88 |
+
schame['_kwargs'][name] = value
|
| 89 |
+
|
| 90 |
+
return schame
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def create(type_or_name, global_cfg=GLOBAL_CONFIG, **kwargs):
|
| 94 |
+
"""
|
| 95 |
+
"""
|
| 96 |
+
assert type(type_or_name) in (type, str), 'create should be modules or name.'
|
| 97 |
+
|
| 98 |
+
name = type_or_name if isinstance(type_or_name, str) else type_or_name.__name__
|
| 99 |
+
|
| 100 |
+
if name in global_cfg:
|
| 101 |
+
if hasattr(global_cfg[name], '__dict__'):
|
| 102 |
+
return global_cfg[name]
|
| 103 |
+
else:
|
| 104 |
+
raise ValueError('The module {} is not registered'.format(name))
|
| 105 |
+
|
| 106 |
+
cfg = global_cfg[name]
|
| 107 |
+
|
| 108 |
+
if isinstance(cfg, dict) and 'type' in cfg:
|
| 109 |
+
_cfg: dict = global_cfg[cfg['type']]
|
| 110 |
+
# clean args
|
| 111 |
+
_keys = [k for k in _cfg.keys() if not k.startswith('_')]
|
| 112 |
+
for _arg in _keys:
|
| 113 |
+
del _cfg[_arg]
|
| 114 |
+
_cfg.update(_cfg['_kwargs']) # restore default args
|
| 115 |
+
_cfg.update(cfg) # load config args
|
| 116 |
+
_cfg.update(kwargs) # TODO recive extra kwargs
|
| 117 |
+
name = _cfg.pop('type') # pop extra key `type` (from cfg)
|
| 118 |
+
|
| 119 |
+
return create(name, global_cfg)
|
| 120 |
+
|
| 121 |
+
module = getattr(cfg['_pymodule'], name)
|
| 122 |
+
module_kwargs = {}
|
| 123 |
+
module_kwargs.update(cfg)
|
| 124 |
+
|
| 125 |
+
# shared var
|
| 126 |
+
for k in cfg['_share']:
|
| 127 |
+
if k in global_cfg:
|
| 128 |
+
module_kwargs[k] = global_cfg[k]
|
| 129 |
+
else:
|
| 130 |
+
module_kwargs[k] = cfg[k]
|
| 131 |
+
|
| 132 |
+
# inject
|
| 133 |
+
for k in cfg['_inject']:
|
| 134 |
+
_k = cfg[k]
|
| 135 |
+
|
| 136 |
+
if _k is None:
|
| 137 |
+
continue
|
| 138 |
+
|
| 139 |
+
if isinstance(_k, str):
|
| 140 |
+
if _k not in global_cfg:
|
| 141 |
+
raise ValueError(f'Missing inject config of {_k}.')
|
| 142 |
+
|
| 143 |
+
_cfg = global_cfg[_k]
|
| 144 |
+
|
| 145 |
+
if isinstance(_cfg, dict):
|
| 146 |
+
module_kwargs[k] = create(_cfg['_name'], global_cfg)
|
| 147 |
+
else:
|
| 148 |
+
module_kwargs[k] = _cfg
|
| 149 |
+
|
| 150 |
+
elif isinstance(_k, dict):
|
| 151 |
+
if 'type' not in _k.keys():
|
| 152 |
+
raise ValueError('Missing inject for `type` style.')
|
| 153 |
+
|
| 154 |
+
_type = str(_k['type'])
|
| 155 |
+
if _type not in global_cfg:
|
| 156 |
+
raise ValueError(f'Missing {_type} in inspect stage.')
|
| 157 |
+
|
| 158 |
+
# TODO
|
| 159 |
+
_cfg: dict = global_cfg[_type]
|
| 160 |
+
# clean args
|
| 161 |
+
_keys = [k for k in _cfg.keys() if not k.startswith('_')]
|
| 162 |
+
for _arg in _keys:
|
| 163 |
+
del _cfg[_arg]
|
| 164 |
+
_cfg.update(_cfg['_kwargs']) # restore default values
|
| 165 |
+
_cfg.update(_k) # load config args
|
| 166 |
+
name = _cfg.pop('type') # pop extra key (`type` from _k)
|
| 167 |
+
module_kwargs[k] = create(name, global_cfg)
|
| 168 |
+
|
| 169 |
+
else:
|
| 170 |
+
raise ValueError(f'Inject does not support {_k}')
|
| 171 |
+
|
| 172 |
+
# TODO hard code
|
| 173 |
+
module_kwargs = {k: v for k, v in module_kwargs.items() if not k.startswith('_')}
|
| 174 |
+
|
| 175 |
+
# TODO for **kwargs
|
| 176 |
+
# extra_args = set(module_kwargs.keys()) - set(arg_names)
|
| 177 |
+
# if len(extra_args) > 0:
|
| 178 |
+
# raise RuntimeError(f'Error: unknown args {extra_args} for {module}')
|
| 179 |
+
|
| 180 |
+
return module(**module_kwargs)
|