vtrace-behavior 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- configs/__init__.py +0 -0
- configs/_dataset.py +93 -0
- configs/_model.py +29 -0
- configs/calms21_demo.py +169 -0
- configs/calms21_distill_vmaeB.py +189 -0
- configs/calms21_vjepa2.py +108 -0
- configs/maev2.py +179 -0
- configs/vjepa2.py +164 -0
- tools/__init__.py +0 -0
- tools/bake_distill_adapters.py +83 -0
- tools/distill_jepa_to_vmae.py +450 -0
- tools/infer.py +625 -0
- tools/prep_dataset.py +82 -0
- tools/select_backbone.py +171 -0
- tools/select_head.py +232 -0
- tools/test.py +168 -0
- tools/train.py +285 -0
- tools/tune_train.py +42 -0
- vtrace/__init__.py +17 -0
- vtrace/cli.py +1021 -0
- vtrace/config.py +233 -0
- vtrace/cores/__init__.py +6 -0
- vtrace/cores/eval_engine.py +456 -0
- vtrace/cores/layer_decay_optimizer.py +93 -0
- vtrace/cores/optimizer.py +145 -0
- vtrace/cores/scheduler.py +212 -0
- vtrace/cores/train_engine.py +161 -0
- vtrace/data_prep.py +1059 -0
- vtrace/datasets/__init__.py +10 -0
- vtrace/datasets/builder.py +65 -0
- vtrace/datasets/sliding.py +1009 -0
- vtrace/datasets/transforms.py +1519 -0
- vtrace/demo.py +493 -0
- vtrace/demo_data/calms21/classmap.txt +3 -0
- vtrace/demo_data/calms21/test/mouse071_task1_annotator1.csv +106 -0
- vtrace/demo_data/calms21/test/mouse072_task1_annotator1.csv +61 -0
- vtrace/demo_data/calms21/test/mouse073_task1_annotator1.csv +77 -0
- vtrace/demo_data/calms21/test/mouse074_task1_annotator1.csv +141 -0
- vtrace/demo_data/calms21/test/mouse075_task1_annotator1.csv +66 -0
- vtrace/demo_data/calms21/test/mouse076_task1_annotator1.csv +187 -0
- vtrace/demo_data/calms21/test/mouse077_task1_annotator1.csv +115 -0
- vtrace/demo_data/calms21/test/mouse078_task1_annotator1.csv +277 -0
- vtrace/demo_data/calms21/test/mouse079_task1_annotator1.csv +79 -0
- vtrace/demo_data/calms21/test/mouse080_task1_annotator1.csv +52 -0
- vtrace/demo_data/calms21/test/mouse081_task1_annotator1.csv +12 -0
- vtrace/demo_data/calms21/test/mouse082_task1_annotator1.csv +42 -0
- vtrace/demo_data/calms21/test/mouse083_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/test/mouse084_task1_annotator1.csv +31 -0
- vtrace/demo_data/calms21/test/mouse085_task1_annotator1.csv +75 -0
- vtrace/demo_data/calms21/test/mouse086_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/test/mouse087_task1_annotator1.csv +44 -0
- vtrace/demo_data/calms21/test/mouse088_task1_annotator1.csv +46 -0
- vtrace/demo_data/calms21/test/mouse089_task1_annotator1.csv +63 -0
- vtrace/demo_data/calms21/train/mouse001_task1_annotator1.csv +87 -0
- vtrace/demo_data/calms21/train/mouse002_task1_annotator1.csv +170 -0
- vtrace/demo_data/calms21/train/mouse003_task1_annotator1.csv +51 -0
- vtrace/demo_data/calms21/train/mouse004_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/train/mouse005_task1_annotator1.csv +23 -0
- vtrace/demo_data/calms21/train/mouse006_task1_annotator1.csv +24 -0
- vtrace/demo_data/calms21/train/mouse007_task1_annotator1.csv +45 -0
- vtrace/demo_data/calms21/train/mouse008_task1_annotator1.csv +62 -0
- vtrace/demo_data/calms21/train/mouse009_task1_annotator1.csv +24 -0
- vtrace/demo_data/calms21/train/mouse010_task1_annotator1.csv +32 -0
- vtrace/demo_data/calms21/train/mouse011_task1_annotator1.csv +22 -0
- vtrace/demo_data/calms21/train/mouse012_task1_annotator1.csv +32 -0
- vtrace/demo_data/calms21/train/mouse013_task1_annotator1.csv +6 -0
- vtrace/demo_data/calms21/train/mouse014_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/train/mouse015_task1_annotator1.csv +24 -0
- vtrace/demo_data/calms21/train/mouse016_task1_annotator1.csv +11 -0
- vtrace/demo_data/calms21/train/mouse017_task1_annotator1.csv +12 -0
- vtrace/demo_data/calms21/train/mouse018_task1_annotator1.csv +32 -0
- vtrace/demo_data/calms21/train/mouse019_task1_annotator1.csv +9 -0
- vtrace/demo_data/calms21/train/mouse020_task1_annotator1.csv +6 -0
- vtrace/demo_data/calms21/train/mouse021_task1_annotator1.csv +23 -0
- vtrace/demo_data/calms21/train/mouse022_task1_annotator1.csv +16 -0
- vtrace/demo_data/calms21/train/mouse023_task1_annotator1.csv +5 -0
- vtrace/demo_data/calms21/train/mouse024_task1_annotator1.csv +15 -0
- vtrace/demo_data/calms21/train/mouse025_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/train/mouse026_task1_annotator1.csv +29 -0
- vtrace/demo_data/calms21/train/mouse027_task1_annotator1.csv +12 -0
- vtrace/demo_data/calms21/train/mouse028_task1_annotator1.csv +16 -0
- vtrace/demo_data/calms21/train/mouse029_task1_annotator1.csv +14 -0
- vtrace/demo_data/calms21/train/mouse030_task1_annotator1.csv +15 -0
- vtrace/demo_data/calms21/train/mouse031_task1_annotator1.csv +23 -0
- vtrace/demo_data/calms21/train/mouse032_task1_annotator1.csv +30 -0
- vtrace/demo_data/calms21/train/mouse033_task1_annotator1.csv +13 -0
- vtrace/demo_data/calms21/train/mouse034_task1_annotator1.csv +10 -0
- vtrace/demo_data/calms21/train/mouse035_task1_annotator1.csv +18 -0
- vtrace/demo_data/calms21/train/mouse036_task1_annotator1.csv +2 -0
- vtrace/demo_data/calms21/train/mouse037_task1_annotator1.csv +8 -0
- vtrace/demo_data/calms21/train/mouse038_task1_annotator1.csv +19 -0
- vtrace/demo_data/calms21/train/mouse039_task1_annotator1.csv +24 -0
- vtrace/demo_data/calms21/train/mouse040_task1_annotator1.csv +15 -0
- vtrace/demo_data/calms21/train/mouse041_task1_annotator1.csv +8 -0
- vtrace/demo_data/calms21/train/mouse042_task1_annotator1.csv +11 -0
- vtrace/demo_data/calms21/train/mouse043_task1_annotator1.csv +9 -0
- vtrace/demo_data/calms21/train/mouse044_task1_annotator1.csv +25 -0
- vtrace/demo_data/calms21/train/mouse045_task1_annotator1.csv +44 -0
- vtrace/demo_data/calms21/train/mouse046_task1_annotator1.csv +29 -0
- vtrace/demo_data/calms21/train/mouse047_task1_annotator1.csv +21 -0
- vtrace/demo_data/calms21/train/mouse048_task1_annotator1.csv +11 -0
- vtrace/demo_data/calms21/train/mouse049_task1_annotator1.csv +10 -0
- vtrace/demo_data/calms21/train/mouse050_task1_annotator1.csv +11 -0
- vtrace/demo_data/calms21/train/mouse051_task1_annotator1.csv +72 -0
- vtrace/demo_data/calms21/train/mouse052_task1_annotator1.csv +68 -0
- vtrace/demo_data/calms21/train/mouse053_task1_annotator1.csv +91 -0
- vtrace/demo_data/calms21/train/mouse054_task1_annotator1.csv +59 -0
- vtrace/demo_data/calms21/train/mouse055_task1_annotator1.csv +87 -0
- vtrace/demo_data/calms21/train/mouse056_task1_annotator1.csv +46 -0
- vtrace/demo_data/calms21/train/mouse057_task1_annotator1.csv +66 -0
- vtrace/demo_data/calms21/train/mouse058_task1_annotator1.csv +79 -0
- vtrace/demo_data/calms21/train/mouse059_task1_annotator1.csv +30 -0
- vtrace/demo_data/calms21/train/mouse060_task1_annotator1.csv +22 -0
- vtrace/demo_data/calms21/train/mouse061_task1_annotator1.csv +25 -0
- vtrace/demo_data/calms21/train/mouse062_task1_annotator1.csv +48 -0
- vtrace/demo_data/calms21/train/mouse063_task1_annotator1.csv +53 -0
- vtrace/demo_data/calms21/train/mouse064_task1_annotator1.csv +41 -0
- vtrace/demo_data/calms21/train/mouse065_task1_annotator1.csv +27 -0
- vtrace/demo_data/calms21/train/mouse066_task1_annotator1.csv +31 -0
- vtrace/demo_data/calms21/train/mouse067_task1_annotator1.csv +34 -0
- vtrace/demo_data/calms21/train/mouse068_task1_annotator1.csv +33 -0
- vtrace/demo_data/calms21/train/mouse069_task1_annotator1.csv +64 -0
- vtrace/demo_data/calms21/train/mouse070_task1_annotator1.csv +124 -0
- vtrace/demo_data/calms21/videos.json +540 -0
- vtrace/evaluations/__init__.py +5 -0
- vtrace/evaluations/builder.py +29 -0
- vtrace/evaluations/mAP.py +477 -0
- vtrace/evaluations/precision.py +801 -0
- vtrace/model_artifacts.py +87 -0
- vtrace/models/__init__.py +22 -0
- vtrace/models/backbones.py +1242 -0
- vtrace/models/bricks.py +911 -0
- vtrace/models/builder.py +42 -0
- vtrace/models/detectors.py +1225 -0
- vtrace/models/heads.py +450 -0
- vtrace/models/necks.py +397 -0
- vtrace/models/postprocess.py +534 -0
- vtrace/models/projections.py +173 -0
- vtrace/pipeline_plan.py +281 -0
- vtrace/proxy_geometry.py +243 -0
- vtrace/registry.py +27 -0
- vtrace/remote_zip.py +96 -0
- vtrace/selection/__init__.py +34 -0
- vtrace/selection/extract.py +174 -0
- vtrace/selection/head_proxy.py +272 -0
- vtrace/selection/lc_extrap.py +310 -0
- vtrace/selection/lead.py +267 -0
- vtrace/selection/rankme.py +116 -0
- vtrace/selection/transferability.py +363 -0
- vtrace/shell.py +236 -0
- vtrace/splash.py +216 -0
- vtrace/static/gui/index.html +3203 -0
- vtrace/steps.py +404 -0
- vtrace/utils/__init__.py +21 -0
- vtrace/utils/auto_tune.py +248 -0
- vtrace/utils/checkpoint.py +37 -0
- vtrace/utils/ema.py +27 -0
- vtrace/utils/logger.py +24 -0
- vtrace/utils/misc.py +67 -0
- vtrace/utils/train_tune.py +233 -0
- vtrace/version.py +1 -0
- vtrace/weights.py +210 -0
- vtrace_behavior-1.0.0.dist-info/METADATA +218 -0
- vtrace_behavior-1.0.0.dist-info/RECORD +168 -0
- vtrace_behavior-1.0.0.dist-info/WHEEL +5 -0
- vtrace_behavior-1.0.0.dist-info/entry_points.txt +2 -0
- vtrace_behavior-1.0.0.dist-info/licenses/LICENSE +176 -0
- vtrace_behavior-1.0.0.dist-info/top_level.txt +3 -0
configs/__init__.py
ADDED
|
File without changes
|
configs/_dataset.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
annotation_path = "dataset.json"
|
|
2
|
+
class_map = "classmap.txt"
|
|
3
|
+
data_path = "."
|
|
4
|
+
block_list = None
|
|
5
|
+
|
|
6
|
+
window_size = 256
|
|
7
|
+
|
|
8
|
+
dataset = dict(
|
|
9
|
+
train=dict(
|
|
10
|
+
type="PlainSlidingDataset",
|
|
11
|
+
ann_file=annotation_path,
|
|
12
|
+
subset_name="training",
|
|
13
|
+
block_list=block_list,
|
|
14
|
+
class_map=class_map,
|
|
15
|
+
data_path=data_path,
|
|
16
|
+
filter_gt=False,
|
|
17
|
+
feature_stride=1,
|
|
18
|
+
sample_stride=1,
|
|
19
|
+
window_size=window_size,
|
|
20
|
+
window_overlap_ratio=0.5,
|
|
21
|
+
pipeline=[
|
|
22
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
23
|
+
dict(type="VideoInit", num_threads=4),
|
|
24
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
25
|
+
dict(type="VideoDecode"),
|
|
26
|
+
dict(type="VideoResize", scale=(-1, 256)),
|
|
27
|
+
dict(type="VideoRandomResizedCrop"),
|
|
28
|
+
dict(type="VideoResize", scale=(224, 224)),
|
|
29
|
+
dict(type="VideoFlip", flip_ratio=0.5),
|
|
30
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
31
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
32
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
33
|
+
],
|
|
34
|
+
),
|
|
35
|
+
val=dict(
|
|
36
|
+
type="PlainSlidingDataset",
|
|
37
|
+
ann_file=annotation_path,
|
|
38
|
+
subset_name="validation",
|
|
39
|
+
block_list=block_list,
|
|
40
|
+
class_map=class_map,
|
|
41
|
+
data_path=data_path,
|
|
42
|
+
filter_gt=False,
|
|
43
|
+
feature_stride=1,
|
|
44
|
+
sample_stride=1,
|
|
45
|
+
window_size=window_size,
|
|
46
|
+
window_overlap_ratio=0.25,
|
|
47
|
+
pipeline=[
|
|
48
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
49
|
+
dict(type="VideoInit", num_threads=4),
|
|
50
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
51
|
+
dict(type="VideoDecode"),
|
|
52
|
+
dict(type="VideoResize", scale=(-1, 224)),
|
|
53
|
+
dict(type="VideoCenterCrop", crop_size=224),
|
|
54
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
55
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
56
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
57
|
+
],
|
|
58
|
+
),
|
|
59
|
+
test=dict(
|
|
60
|
+
type="PlainSlidingDataset",
|
|
61
|
+
ann_file=annotation_path,
|
|
62
|
+
subset_name="validation",
|
|
63
|
+
block_list=block_list,
|
|
64
|
+
class_map=class_map,
|
|
65
|
+
data_path=data_path,
|
|
66
|
+
filter_gt=False,
|
|
67
|
+
test_mode=True,
|
|
68
|
+
feature_stride=1,
|
|
69
|
+
sample_stride=1,
|
|
70
|
+
window_size=window_size,
|
|
71
|
+
window_overlap_ratio=0.5,
|
|
72
|
+
pipeline=[
|
|
73
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
74
|
+
dict(type="VideoInit", num_threads=4),
|
|
75
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
76
|
+
dict(type="VideoDecode"),
|
|
77
|
+
dict(type="VideoResize", scale=(-1, 224)),
|
|
78
|
+
dict(type="VideoCenterCrop", crop_size=224),
|
|
79
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
80
|
+
dict(type="ConvertToTensor", keys=["imgs"]),
|
|
81
|
+
dict(type="Collect", inputs="imgs", keys=["masks"]),
|
|
82
|
+
],
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
evaluation = dict(
|
|
87
|
+
type="Precision",
|
|
88
|
+
subset="validation",
|
|
89
|
+
tiou_thresholds=[0.3, 0.4, 0.5, 0.6, 0.7],
|
|
90
|
+
ground_truth_filename=annotation_path,
|
|
91
|
+
gt_fps=30.0,
|
|
92
|
+
eval_fps=30.0,
|
|
93
|
+
)
|
configs/_model.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
model = dict(
|
|
2
|
+
type="DenseLocalizer",
|
|
3
|
+
# DFC-only per-frame classifier; num_classes is auto-detected from the dataset
|
|
4
|
+
# class_map by tools/train.py (overrides this placeholder).
|
|
5
|
+
num_classes=3,
|
|
6
|
+
projection=dict(
|
|
7
|
+
type="SGPPyramidProj",
|
|
8
|
+
in_channels=2048,
|
|
9
|
+
out_channels=512,
|
|
10
|
+
sgp_mlp_dim=768,
|
|
11
|
+
arch=(2, 2, 5), # layers in embed / stem / branch
|
|
12
|
+
downsample_type="max",
|
|
13
|
+
sgp_win_size=[1, 1, 1, 1, 1, 1],
|
|
14
|
+
k=5,
|
|
15
|
+
init_conv_vars=0,
|
|
16
|
+
conv_cfg=dict(kernel_size=3),
|
|
17
|
+
norm_cfg=dict(type="LN"),
|
|
18
|
+
path_pdrop=0.1,
|
|
19
|
+
use_abs_pe=True,
|
|
20
|
+
max_seq_len=768,
|
|
21
|
+
input_noise=0.0,
|
|
22
|
+
),
|
|
23
|
+
neck=dict(
|
|
24
|
+
type="FPNIdentity",
|
|
25
|
+
in_channels=512,
|
|
26
|
+
out_channels=512,
|
|
27
|
+
num_levels=6,
|
|
28
|
+
),
|
|
29
|
+
)
|
configs/calms21_demo.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Architecture for the released CalMS21 demo checkpoint (`calms21_vitB_distilled_best.pth`).
|
|
2
|
+
|
|
3
|
+
This is the config `vtrace demo` writes into the demo model directory's `config.txt`,
|
|
4
|
+
so `vtrace demo predict` / `vtrace eval --model-dir` / `vtrace predict --model-dir` all
|
|
5
|
+
resolve to it. It is the model half of `configs/calms21_distill_vmaeB.py` — a
|
|
6
|
+
VideoMAE V2 ViT-B with per-block adapters and the routed dense head the checkpoint
|
|
7
|
+
was trained with — minus every absolute path from that research config.
|
|
8
|
+
|
|
9
|
+
Dataset paths stay as the placeholders from `_dataset.py`; the CLI rewrites them per
|
|
10
|
+
run (`data_path=` / `annotation_path=` / `class_map=`), and `num_classes` is
|
|
11
|
+
auto-detected from the class map. So the same file serves prediction on a demo video
|
|
12
|
+
and training on new ones.
|
|
13
|
+
|
|
14
|
+
The frozen ViT-B base (`pretrained/vitB_videomaev2_k400.pth`) auto-downloads through
|
|
15
|
+
`vtrace/weights.py`; when the full checkpoint is loaded for prediction its weights
|
|
16
|
+
are overwritten by that checkpoint anyway.
|
|
17
|
+
"""
|
|
18
|
+
_base_ = [
|
|
19
|
+
"_dataset.py",
|
|
20
|
+
"_model.py",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
window_size = 768
|
|
24
|
+
scale_factor = 1
|
|
25
|
+
chunk_num = window_size * scale_factor // 16
|
|
26
|
+
crop = 224 # VideoMAE-B native input
|
|
27
|
+
|
|
28
|
+
_train_pipe = [
|
|
29
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
30
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
31
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
32
|
+
dict(type="VideoTemporalAugment", speed_range=(0.7, 1.3), p=0.8),
|
|
33
|
+
dict(type="VideoDecode"),
|
|
34
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
35
|
+
dict(type="VideoFlip", flip_ratio=0.5),
|
|
36
|
+
dict(type="VideoRotate", max_angle=180.0, p=0.8),
|
|
37
|
+
dict(type="VideoTrivialAugment"),
|
|
38
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
39
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
40
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
41
|
+
]
|
|
42
|
+
_val_pipe = [
|
|
43
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
44
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
45
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
46
|
+
dict(type="VideoDecode"),
|
|
47
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
48
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
49
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
50
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
51
|
+
]
|
|
52
|
+
_test_pipe = [
|
|
53
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
54
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
55
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
56
|
+
dict(type="VideoDecode"),
|
|
57
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
58
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
59
|
+
dict(type="ConvertToTensor", keys=["imgs"]),
|
|
60
|
+
dict(type="Collect", inputs="imgs", keys=["masks"]),
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
dataset = dict(
|
|
64
|
+
train=dict(
|
|
65
|
+
type="BehaviorTargetedSlidingDataset",
|
|
66
|
+
window_size=window_size,
|
|
67
|
+
window_overlap_ratio=0.0,
|
|
68
|
+
rare_phases=2,
|
|
69
|
+
base_jitter=0.125,
|
|
70
|
+
pipeline=_train_pipe,
|
|
71
|
+
),
|
|
72
|
+
val=dict(window_size=window_size, window_overlap_ratio=0.5, pipeline=_val_pipe),
|
|
73
|
+
test=dict(window_size=window_size, window_overlap_ratio=0.5, pipeline=_test_pipe),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Must match `calms21_vitB_distilled_best.pth` key for key — do not retune here.
|
|
77
|
+
model = dict(
|
|
78
|
+
type="DenseLocalizer",
|
|
79
|
+
crop_stream_reduce="max",
|
|
80
|
+
backbone=dict(
|
|
81
|
+
type="VisionTransformerAdapter",
|
|
82
|
+
img_size=224,
|
|
83
|
+
patch_size=16,
|
|
84
|
+
embed_dims=768,
|
|
85
|
+
depth=12,
|
|
86
|
+
num_heads=12,
|
|
87
|
+
mlp_ratio=4,
|
|
88
|
+
qkv_bias=True,
|
|
89
|
+
drop_path_rate=0.3,
|
|
90
|
+
norm_cfg=dict(type="LN", eps=1e-6),
|
|
91
|
+
return_feat_map=True,
|
|
92
|
+
with_cp=True,
|
|
93
|
+
total_frames=window_size * scale_factor,
|
|
94
|
+
adapter_index=list(range(12)),
|
|
95
|
+
custom=dict(
|
|
96
|
+
pretrain="pretrained/vitB_videomaev2_k400.pth",
|
|
97
|
+
mean=[123.675, 116.28, 103.53],
|
|
98
|
+
std=[58.395, 57.12, 57.375],
|
|
99
|
+
pre_processing_pipeline=[
|
|
100
|
+
dict(type="Rearrange", keys=["frames"], ops="b n c (t1 t) h w -> (b t1) n c t h w", t1=chunk_num),
|
|
101
|
+
],
|
|
102
|
+
post_processing_pipeline=[
|
|
103
|
+
dict(type="Reduce", keys=["feats"], ops="b n c t h w -> b c t", reduction="mean"),
|
|
104
|
+
dict(type="Rearrange", keys=["feats"], ops="(b t1) c t -> b c (t1 t)", t1=chunk_num),
|
|
105
|
+
dict(type="Interpolate", keys=["feats"], size=window_size),
|
|
106
|
+
],
|
|
107
|
+
norm_eval=False,
|
|
108
|
+
freeze_backbone=False, # the ViT is frozen through the optimizer
|
|
109
|
+
),
|
|
110
|
+
),
|
|
111
|
+
projection=dict(in_channels=768, input_noise=0.0005),
|
|
112
|
+
aux_frame_cls=dict(
|
|
113
|
+
enabled=True, in_channels=512, feat_channels=512, num_layers=2,
|
|
114
|
+
use_background=True, multilabel=False, target_mode="all",
|
|
115
|
+
label_smoothing=0.1, class_weight_mode="inv_freq_sqrt", loss_weight=2.0,
|
|
116
|
+
dropout=0.5,
|
|
117
|
+
inference_enabled=True, score_fusion_enabled=False, proposal_enabled=True,
|
|
118
|
+
proposal_mode="dense", proposal_prior="softmax", proposal_min_score=1e-8,
|
|
119
|
+
proposal_topk=0, proposal_smoothing=9, multiscale=True, mixup_alpha=0.8,
|
|
120
|
+
head_type="routed", routing=dict(default="dyfadet", conv=[0]),
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
solver = dict(
|
|
125
|
+
train=dict(batch_size=4, num_workers=6, persistent_workers=False, prefetch_factor=2),
|
|
126
|
+
val=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
127
|
+
test=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
128
|
+
clip_grad_norm=1, ema=True, amp=True, amp_dtype="bfloat16",
|
|
129
|
+
accumulation_steps=1, compile=False,
|
|
130
|
+
)
|
|
131
|
+
optimizer = dict(
|
|
132
|
+
type="AdamW", lr=7e-5, weight_decay=0.025, paramwise=True,
|
|
133
|
+
backbone=dict(lr=0, weight_decay=0,
|
|
134
|
+
custom=[dict(name="adapter", lr=1e-4, weight_decay=0.05)],
|
|
135
|
+
exclude=["backbone"]),
|
|
136
|
+
)
|
|
137
|
+
scheduler = dict(type="LinearWarmupCosineAnnealingLR", warmup_epoch=2, max_epoch=10)
|
|
138
|
+
|
|
139
|
+
inference = dict(load_from_raw_predictions=False, save_raw_prediction=False)
|
|
140
|
+
post_processing = dict(
|
|
141
|
+
# Soft-NMS merges the dense per-frame scores into behaviour bouts. The research
|
|
142
|
+
# configs turn this off (iou_threshold=1.0, max_seg_num=500000) because frame-level
|
|
143
|
+
# mAP is scored on the raw dense output; a reviewer opening the prediction file
|
|
144
|
+
# wants bouts, not one entry per frame.
|
|
145
|
+
nms=dict(
|
|
146
|
+
use_soft_nms=True,
|
|
147
|
+
sigma=0.5,
|
|
148
|
+
max_seg_num=2000,
|
|
149
|
+
min_score=0.05,
|
|
150
|
+
multiclass=True,
|
|
151
|
+
voting_thresh=0.7,
|
|
152
|
+
),
|
|
153
|
+
save_dict=True,
|
|
154
|
+
)
|
|
155
|
+
# `vtrace demo train` runs this over all 70 official CalMS21 training videos
|
|
156
|
+
# (~125 iterations per epoch at batch 4). Ten epochs with a 2-epoch warmup is the
|
|
157
|
+
# same schedule the research recipe in `calms21_distill_vmaeB.py` uses, so the demo
|
|
158
|
+
# reproduces the released checkpoint's training rather than gesturing at it.
|
|
159
|
+
# `logging_interval` stays finer than the research config's 50: a walkthrough wants
|
|
160
|
+
# to see progress.
|
|
161
|
+
workflow = dict(logging_interval=10, checkpoint_interval=1, val_eval_interval=1,
|
|
162
|
+
val_start_epoch=2, end_epoch=10)
|
|
163
|
+
evaluation = dict(
|
|
164
|
+
type="Precision", subset="validation", tiou_thresholds=[0.3, 0.4, 0.5, 0.6, 0.7],
|
|
165
|
+
gt_fps=30.0, eval_fps=30.0, prediction_min_score=0.0,
|
|
166
|
+
map_frame_filter="all", ap_mode="sklearn",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
work_dir = "runs/calms21_demo"
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""CalMS21 downstream — VideoMAE-B/16 student whose adapters were FD-distilled
|
|
2
|
+
from V-JEPA 2 (see tools/distill_jepa_to_vmae.py).
|
|
3
|
+
|
|
4
|
+
Clones the no-val CalMS21 recipe from `calms21_HPSWEEP_v2_BASE.py` (train on all 70
|
|
5
|
+
train videos, eval on the 19 official-test videos; routed default=dyfadet head +
|
|
6
|
+
multiscale DFC; frame mAP_all_frames, sklearn AP; NMS off / pre_nms_topk=0) but
|
|
7
|
+
swaps the V-JEPA2 ViT-L backbone for the VideoMAE-B/16 `VisionTransformerAdapter`
|
|
8
|
+
— the EXACT student backbone block from configs/singlemouse_routed_mae_multiscale.py
|
|
9
|
+
and tools/distill_jepa_to_vmae.py (img 224, embed 768, depth 12, adapters on all 12
|
|
10
|
+
blocks). The ViT blocks stay frozen (VisionTransformerAdapter._freeze_layers, run
|
|
11
|
+
every forward); ONLY the in-backbone temporal adapters are trained downstream
|
|
12
|
+
(optimizer.backbone lr=0 + custom adapter group lr=1e-4, exactly as singlemouse).
|
|
13
|
+
|
|
14
|
+
────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
INITIALIZING THE DISTILLED ADAPTERS
|
|
16
|
+
────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
The distill run writes its trainable state to
|
|
18
|
+
{out}/distill_adapter.pth
|
|
19
|
+
as a flat state_dict whose keys are exactly:
|
|
20
|
+
backbone.model.backbone.blocks.<i>.adapter.* (108 tensors, one set/block)
|
|
21
|
+
proj.0.* / proj.2.* (4 tensors — the 768->1024 head)
|
|
22
|
+
|
|
23
|
+
In THIS downstream model the backbone lives at `backbone.model.backbone.*`, so the
|
|
24
|
+
adapter keys above map ONE-TO-ONE onto this model's state_dict (no remap needed).
|
|
25
|
+
The `proj.*` keys have NO home here (downstream uses TriDetProj on the raw 768-d
|
|
26
|
+
features, not the distillation projection) and are simply dropped.
|
|
27
|
+
|
|
28
|
+
train.py / eval_engine are NOT modified. Pick ONE of these to load the adapters:
|
|
29
|
+
|
|
30
|
+
(A) --cfg-options field + a tiny one-time pre-load step (recommended). This config
|
|
31
|
+
carries `distill_adapter_ckpt` (default below). Because train.py builds the
|
|
32
|
+
model and only loads weights via --resume, the simplest no-train.py-edit path
|
|
33
|
+
is to bake the distilled adapters into a full TriDet checkpoint ONCE, then
|
|
34
|
+
--resume from it:
|
|
35
|
+
|
|
36
|
+
python - <<'PY'
|
|
37
|
+
import torch, os, sys
|
|
38
|
+
sys.path.insert(0, ".") # mirror tools/train.py
|
|
39
|
+
from vtrace.config import Config
|
|
40
|
+
from vtrace.models import build_detector
|
|
41
|
+
cfg = Config.fromfile("configs/calms21_distill_vmaeB.py")
|
|
42
|
+
cfg.model.num_classes = 3
|
|
43
|
+
model = build_detector(cfg.model)
|
|
44
|
+
ad = torch.load(cfg.distill_adapter_ckpt, map_location="cpu")
|
|
45
|
+
ad = {k: v for k, v in ad.items() if "adapter" in k} # drop proj.*
|
|
46
|
+
missing, unexpected = model.load_state_dict(ad, strict=False)
|
|
47
|
+
print("loaded adapters:", len(ad), "unexpected:", unexpected[:3])
|
|
48
|
+
out = os.path.join(cfg.work_dir, "init_with_distilled_adapters.pth")
|
|
49
|
+
os.makedirs(cfg.work_dir, exist_ok=True)
|
|
50
|
+
torch.save({"epoch": -1, "state_dict": model.state_dict()}, out)
|
|
51
|
+
print("wrote", out)
|
|
52
|
+
PY
|
|
53
|
+
|
|
54
|
+
then:
|
|
55
|
+
torchrun --nproc_per_node=1 tools/train.py configs/calms21_distill_vmaeB.py \
|
|
56
|
+
--resume <work_dir>/init_with_distilled_adapters.pth
|
|
57
|
+
(train.py's --resume sets resume_epoch from epoch=-1 -> starts at epoch 0, and
|
|
58
|
+
load_state_dict(strict=False) tolerates the adapter-only init.)
|
|
59
|
+
|
|
60
|
+
(B) Add a `load_from` hook to train.py (NOT done here, since we must not edit
|
|
61
|
+
train.py): a 3-line block right after `model = build_detector(cfg.model)` that,
|
|
62
|
+
when `cfg.get("distill_adapter_ckpt")` is set, loads the adapter-only keys with
|
|
63
|
+
strict=False. Documented here for whoever later wants it in-engine.
|
|
64
|
+
|
|
65
|
+
If `distill_adapter_ckpt` is left unused, the adapters start from random init and
|
|
66
|
+
this config is just a plain frozen-ViT-B + trained-adapter CalMS21 baseline.
|
|
67
|
+
"""
|
|
68
|
+
_base_ = ["_model.py"]
|
|
69
|
+
|
|
70
|
+
window_size = 768
|
|
71
|
+
scale_factor = 1
|
|
72
|
+
chunk_num = window_size * scale_factor // 16
|
|
73
|
+
crop = 224 # VideoMAE-B native input
|
|
74
|
+
|
|
75
|
+
# NO-VAL protocol (per calms21_HPSWEEP_v2_BASE): train on all 70 train videos, eval
|
|
76
|
+
# on the 19 official-test videos so mAP is comparable to the V-JEPA2 anchors.
|
|
77
|
+
# ── Fill these in for your CalMS21 copy ──────────────────────────────────────
|
|
78
|
+
# The official Task-1 release; `vtrace demo download` fetches the same videos from
|
|
79
|
+
# CaltechDATA into `~/.trace/demo` (or `data/calms21_demo` in a checkout), and
|
|
80
|
+
# `full_seq/dataset.json` is the official 70/19 split in TRACE's annotation format.
|
|
81
|
+
# Either edit these four, or override them at launch:
|
|
82
|
+
# --cfg-options ann=... vid_train=... vid_test=... class_map=...
|
|
83
|
+
ann = "data/calms21/full_seq/dataset.json"
|
|
84
|
+
vid_train = "data/calms21/videos/train"
|
|
85
|
+
vid_test = "data/calms21/videos/test"
|
|
86
|
+
class_map = "data/calms21/full_seq/classmap.txt"
|
|
87
|
+
|
|
88
|
+
# Path to the distilled trainable state written by tools/distill_jepa_to_vmae.py.
|
|
89
|
+
# Consumed by the one-time bake-in step (A) above; train.py itself ignores unknown
|
|
90
|
+
# top-level keys.
|
|
91
|
+
distill_adapter_ckpt = "runs/distill_jepa2vmae/distill_adapter.pth"
|
|
92
|
+
|
|
93
|
+
model = dict(
|
|
94
|
+
type="DenseLocalizer",
|
|
95
|
+
crop_stream_reduce="max",
|
|
96
|
+
backbone=dict(
|
|
97
|
+
type="VisionTransformerAdapter",
|
|
98
|
+
img_size=224, patch_size=16, embed_dims=768, depth=12, num_heads=12, mlp_ratio=4,
|
|
99
|
+
qkv_bias=True, drop_path_rate=0.3, norm_cfg=dict(type="LN", eps=1e-6),
|
|
100
|
+
return_feat_map=True, with_cp=True, total_frames=window_size * scale_factor,
|
|
101
|
+
adapter_index=list(range(12)),
|
|
102
|
+
custom=dict(
|
|
103
|
+
# The distilled adapters are loaded SEPARATELY (see header); this is the
|
|
104
|
+
# base K400 ViT-B the distillation also started from.
|
|
105
|
+
pretrain="pretrained/vitB_videomaev2_k400.pth",
|
|
106
|
+
mean=[123.675, 116.28, 103.53],
|
|
107
|
+
std=[58.395, 57.12, 57.375],
|
|
108
|
+
pre_processing_pipeline=[
|
|
109
|
+
dict(type="Rearrange", keys=["frames"], ops="b n c (t1 t) h w -> (b t1) n c t h w", t1=chunk_num),
|
|
110
|
+
],
|
|
111
|
+
post_processing_pipeline=[
|
|
112
|
+
dict(type="Reduce", keys=["feats"], ops="b n c t h w -> b c t", reduction="mean"),
|
|
113
|
+
dict(type="Rearrange", keys=["feats"], ops="(b t1) c t -> b c (t1 t)", t1=chunk_num),
|
|
114
|
+
dict(type="Interpolate", keys=["feats"], size=window_size),
|
|
115
|
+
],
|
|
116
|
+
norm_eval=False,
|
|
117
|
+
freeze_backbone=False, # ViT frozen via _freeze_layers; adapters trainable
|
|
118
|
+
),
|
|
119
|
+
),
|
|
120
|
+
projection=dict(in_channels=768, input_noise=0.0005),
|
|
121
|
+
aux_frame_cls=dict(
|
|
122
|
+
enabled=True, in_channels=512, feat_channels=512, num_layers=2,
|
|
123
|
+
use_background=True, multilabel=False, target_mode="all",
|
|
124
|
+
label_smoothing=0.1, class_weight_mode="inv_freq_sqrt", loss_weight=2.0,
|
|
125
|
+
dropout=0.5,
|
|
126
|
+
inference_enabled=True, score_fusion_enabled=False, proposal_enabled=True,
|
|
127
|
+
proposal_mode="dense", proposal_prior="softmax", proposal_min_score=1e-8,
|
|
128
|
+
proposal_topk=0, proposal_smoothing=9, multiscale=True, mixup_alpha=0.8,
|
|
129
|
+
head_type="routed", routing=dict(default="dyfadet", conv=[0]),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
_train_pipe = [
|
|
134
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
135
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
136
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
137
|
+
dict(type="VideoTemporalAugment", speed_range=(0.7, 1.3), p=0.8),
|
|
138
|
+
dict(type="VideoDecode"),
|
|
139
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
140
|
+
dict(type="VideoFlip", flip_ratio=0.5),
|
|
141
|
+
dict(type="VideoRotate", max_angle=180.0, p=0.8),
|
|
142
|
+
dict(type="VideoTrivialAugment"),
|
|
143
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
144
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
145
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
146
|
+
]
|
|
147
|
+
_test_pipe = [
|
|
148
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
149
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
150
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
151
|
+
dict(type="VideoDecode"),
|
|
152
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
153
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
154
|
+
dict(type="ConvertToTensor", keys=["imgs"]),
|
|
155
|
+
dict(type="Collect", inputs="imgs", keys=["masks"]),
|
|
156
|
+
]
|
|
157
|
+
dataset = dict(
|
|
158
|
+
train=dict(type="BehaviorTargetedSlidingDataset", ann_file=ann, subset_name="train", block_list=None,
|
|
159
|
+
class_map=class_map, data_path=vid_train, filter_gt=False, feature_stride=1, sample_stride=1,
|
|
160
|
+
window_size=window_size, window_overlap_ratio=0.0, rare_phases=2,
|
|
161
|
+
base_jitter=0.125, pipeline=_train_pipe),
|
|
162
|
+
val=dict(type="PlainSlidingDataset", ann_file=ann, subset_name="validation", block_list=None,
|
|
163
|
+
class_map=class_map, data_path=vid_test, filter_gt=False, feature_stride=1, sample_stride=1,
|
|
164
|
+
window_size=window_size, window_overlap_ratio=0.5, pipeline=_test_pipe),
|
|
165
|
+
test=dict(type="PlainSlidingDataset", ann_file=ann, subset_name="validation", block_list=None,
|
|
166
|
+
class_map=class_map, data_path=vid_test, filter_gt=False, test_mode=True, feature_stride=1, sample_stride=1,
|
|
167
|
+
window_size=window_size, window_overlap_ratio=0.5, pipeline=_test_pipe),
|
|
168
|
+
)
|
|
169
|
+
solver = dict(
|
|
170
|
+
train=dict(batch_size=4, num_workers=6, persistent_workers=False, prefetch_factor=2),
|
|
171
|
+
val=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
172
|
+
test=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
173
|
+
clip_grad_norm=1, ema=True, amp=True, amp_dtype="bfloat16", accumulation_steps=1, compile=False,
|
|
174
|
+
)
|
|
175
|
+
# Frozen ViT + trained adapters: backbone lr=0 except a custom adapter group at 1e-4
|
|
176
|
+
# (identical to configs/singlemouse_routed_mae_multiscale.py).
|
|
177
|
+
optimizer = dict(
|
|
178
|
+
type="AdamW", lr=7e-5, weight_decay=0.025, paramwise=True,
|
|
179
|
+
backbone=dict(lr=0, weight_decay=0, custom=[dict(name="adapter", lr=1e-4, weight_decay=0.05)], exclude=["backbone"]),
|
|
180
|
+
)
|
|
181
|
+
scheduler = dict(type="LinearWarmupCosineAnnealingLR", warmup_epoch=2, max_epoch=10)
|
|
182
|
+
inference = dict(load_from_raw_predictions=False, save_raw_prediction=False)
|
|
183
|
+
post_processing = dict(pre_nms_topk=0, nms=dict(use_soft_nms=False, iou_threshold=1.0, min_score=0.0, max_seg_num=500000, multiclass=True),
|
|
184
|
+
result_time_decimals=None, result_score_decimals=None, save_dict=True)
|
|
185
|
+
workflow = dict(logging_interval=50, checkpoint_interval=1, val_eval_interval=1, val_start_epoch=2, end_epoch=10)
|
|
186
|
+
evaluation = dict(type="Precision", subset="validation", tiou_thresholds=[0.3, 0.4, 0.5, 0.6, 0.7],
|
|
187
|
+
ground_truth_filename=ann, gt_fps=30.0, eval_fps=30.0, prediction_min_score=0.0,
|
|
188
|
+
map_frame_filter="all", ap_mode="sklearn")
|
|
189
|
+
work_dir = "runs/calms21_distill_vmaeB"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""HP-sweep BASE config — V-JEPA 2 (256/32), no-fov, BehaviorTargeted + routed + mixup.
|
|
2
|
+
|
|
3
|
+
Clone of the proven `calms21_vjepa2_NOFOV_TARGETED_attackonly.py` (no-fov ~95.0 on the
|
|
4
|
+
282-test). NO-VAL protocol (per user): train on all 70 train videos, eval on the 19
|
|
5
|
+
official-test videos — so sweep mAP is directly comparable to the 95.0/95.15 anchors. All
|
|
6
|
+
HP-sweep axes are driven via `--cfg-options` off this base (no per-run config files):
|
|
7
|
+
optimizer.backbone.lr / optimizer.lr ............ LR axis
|
|
8
|
+
model.backbone.freeze_first_n_blocks ............ #unfrozen-layers axis (24 - N)
|
|
9
|
+
dataset.train.rare_classes ...................... densify axis ([0]=attack, [0,1]=attack+inv)
|
|
10
|
+
Eval is the full-video sliding protocol (overlap 0.5, NMS off), frame mAP all-frames (sklearn AP).
|
|
11
|
+
"""
|
|
12
|
+
_base_ = ["_model.py"]
|
|
13
|
+
|
|
14
|
+
window_size = 768
|
|
15
|
+
crop = 256 # V-JEPA2 (2.0) native input
|
|
16
|
+
IMAGENET_MEAN_255 = [0.485 * 255, 0.456 * 255, 0.406 * 255]
|
|
17
|
+
IMAGENET_STD_255 = [0.229 * 255, 0.224 * 255, 0.225 * 255]
|
|
18
|
+
|
|
19
|
+
# NO-VAL protocol (per user): train on all 70 train videos, eval on the 19 official-test
|
|
20
|
+
# videos — identical to the proven 95.0 no-fov line, so sweep mAP is directly comparable.
|
|
21
|
+
# ── Fill these in for your CalMS21 copy ──────────────────────────────────────
|
|
22
|
+
# The official Task-1 release; `vtrace demo download` fetches the same videos from
|
|
23
|
+
# CaltechDATA into `~/.trace/demo` (or `data/calms21_demo` in a checkout), and
|
|
24
|
+
# `full_seq/dataset.json` is the official 70/19 split in TRACE's annotation format.
|
|
25
|
+
# Either edit these four, or override them at launch:
|
|
26
|
+
# --cfg-options ann=... vid_train=... vid_test=... class_map=...
|
|
27
|
+
ann = "data/calms21/full_seq/dataset.json"
|
|
28
|
+
vid_train = "data/calms21/videos/train"
|
|
29
|
+
vid_test = "data/calms21/videos/test"
|
|
30
|
+
class_map = "data/calms21/full_seq/classmap.txt"
|
|
31
|
+
|
|
32
|
+
model = dict(
|
|
33
|
+
type="TriDet",
|
|
34
|
+
crop_stream_reduce="max",
|
|
35
|
+
foveation=dict(enabled=False),
|
|
36
|
+
backbone=dict(
|
|
37
|
+
type="VJEPA2Backbone",
|
|
38
|
+
model_id="facebook/vjepa2-vitl-fpc32-256-diving48",
|
|
39
|
+
crop=crop, fpc=32, tubelet=2, patch=16, total_frames=window_size,
|
|
40
|
+
embed_dims=1024, mean=IMAGENET_MEAN_255, std=IMAGENET_STD_255,
|
|
41
|
+
gradient_checkpointing=True, freeze_first_n_blocks=12, freeze_backbone=False,
|
|
42
|
+
norm_eval=False, local_files_only=True,
|
|
43
|
+
),
|
|
44
|
+
projection=dict(in_channels=1024, input_noise=0.0005),
|
|
45
|
+
aux_frame_cls=dict(
|
|
46
|
+
enabled=True, in_channels=512, feat_channels=512, num_layers=2,
|
|
47
|
+
use_background=True, multilabel=False, target_mode="all",
|
|
48
|
+
label_smoothing=0.1, class_weight_mode="inv_freq_sqrt", loss_weight=2.0,
|
|
49
|
+
dropout=0.5,
|
|
50
|
+
inference_enabled=True, score_fusion_enabled=False, proposal_enabled=True,
|
|
51
|
+
proposal_mode="dense", proposal_prior="softmax", proposal_min_score=1e-8,
|
|
52
|
+
proposal_topk=0, proposal_smoothing=9, multiscale=True, mixup_alpha=0.8,
|
|
53
|
+
head_type="routed", routing=dict(default="dyfadet", conv=[0]),
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
_train_pipe = [
|
|
58
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
59
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
60
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
61
|
+
dict(type="VideoTemporalAugment", speed_range=(0.7, 1.3), p=0.8),
|
|
62
|
+
dict(type="VideoDecode"),
|
|
63
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
64
|
+
dict(type="VideoFlip", flip_ratio=0.5),
|
|
65
|
+
dict(type="VideoRotate", max_angle=180.0, p=0.8),
|
|
66
|
+
dict(type="VideoTrivialAugment"),
|
|
67
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
68
|
+
dict(type="ConvertToTensor", keys=["imgs", "gt_segments", "gt_labels"]),
|
|
69
|
+
dict(type="Collect", inputs="imgs", keys=["masks", "gt_segments", "gt_labels"]),
|
|
70
|
+
]
|
|
71
|
+
_test_pipe = [
|
|
72
|
+
dict(type="PrepareVideoInfo", format="mp4"),
|
|
73
|
+
dict(type="VideoInit", num_threads=4, resize=(crop, crop)),
|
|
74
|
+
dict(type="LoadFrames", num_clips=1, method="sliding_window"),
|
|
75
|
+
dict(type="VideoDecode"),
|
|
76
|
+
dict(type="VideoBatchResize", scale=(crop, crop)),
|
|
77
|
+
dict(type="VideoFormatShape", input_format="NCTHW"),
|
|
78
|
+
dict(type="ConvertToTensor", keys=["imgs"]),
|
|
79
|
+
dict(type="Collect", inputs="imgs", keys=["masks"]),
|
|
80
|
+
]
|
|
81
|
+
dataset = dict(
|
|
82
|
+
train=dict(type="BehaviorTargetedSlidingDataset", ann_file=ann, subset_name="train", block_list=None,
|
|
83
|
+
class_map=class_map, data_path=vid_train, filter_gt=False, feature_stride=1, sample_stride=1,
|
|
84
|
+
window_size=window_size, window_overlap_ratio=0.0, rare_classes=[0], rare_overlap=0.75, pipeline=_train_pipe),
|
|
85
|
+
val=dict(type="ThumosSlidingDataset", ann_file=ann, subset_name="validation", block_list=None,
|
|
86
|
+
class_map=class_map, data_path=vid_test, filter_gt=False, feature_stride=1, sample_stride=1,
|
|
87
|
+
window_size=window_size, window_overlap_ratio=0.5, pipeline=_test_pipe),
|
|
88
|
+
test=dict(type="ThumosSlidingDataset", ann_file=ann, subset_name="validation", block_list=None,
|
|
89
|
+
class_map=class_map, data_path=vid_test, filter_gt=False, test_mode=True, feature_stride=1, sample_stride=1,
|
|
90
|
+
window_size=window_size, window_overlap_ratio=0.5, pipeline=_test_pipe),
|
|
91
|
+
)
|
|
92
|
+
solver = dict(
|
|
93
|
+
train=dict(batch_size=4, num_workers=6, persistent_workers=False, prefetch_factor=2),
|
|
94
|
+
val=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
95
|
+
test=dict(batch_size=1, num_workers=4, persistent_workers=False, prefetch_factor=2),
|
|
96
|
+
clip_grad_norm=1, ema=True, amp=True, amp_dtype="bfloat16", accumulation_steps=1, compile=False,
|
|
97
|
+
)
|
|
98
|
+
optimizer = dict(type="AdamW", lr=1e-4, weight_decay=0.025, paramwise=True,
|
|
99
|
+
backbone=dict(lr=4e-5, weight_decay=0.05, exclude=[]))
|
|
100
|
+
scheduler = dict(type="LinearWarmupCosineAnnealingLR", warmup_epoch=2, max_epoch=10)
|
|
101
|
+
inference = dict(load_from_raw_predictions=False, save_raw_prediction=False)
|
|
102
|
+
post_processing = dict(pre_nms_topk=0, nms=dict(use_soft_nms=False, iou_threshold=1.0, min_score=0.0, max_seg_num=500000, multiclass=True),
|
|
103
|
+
result_time_decimals=None, result_score_decimals=None, save_dict=True)
|
|
104
|
+
workflow = dict(logging_interval=50, checkpoint_interval=1, val_eval_interval=1, val_start_epoch=2, end_epoch=10)
|
|
105
|
+
evaluation = dict(type="Precision", subset="validation", tiou_thresholds=[0.3, 0.4, 0.5, 0.6, 0.7],
|
|
106
|
+
ground_truth_filename=ann, gt_fps=30.0, eval_fps=30.0, prediction_min_score=0.0,
|
|
107
|
+
map_frame_filter="all", ap_mode="sklearn")
|
|
108
|
+
work_dir = "runs/calms21_vjepa2"
|