BiliSakura commited on
Commit
2ada71f
·
verified ·
1 Parent(s): f02f494

Upload SkySense Transformers checkpoints

Browse files
README.md ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ tags:
4
+ - remote-sensing
5
+ - earth-observation
6
+ - skysense
7
+ - feature-extraction
8
+ pipeline_tag: feature-extraction
9
+ ---
10
+
11
+ # SkySense Transformers
12
+
13
+ HuggingFace-compatible checkpoints for the SkySense (CVPR 2024) foundation model backbones.
14
+
15
+ ## Checkpoints
16
+
17
+ | Directory | Modality | Architecture | Source |
18
+ |-----------|----------|--------------|--------|
19
+ | `skysense-swinv2-huge-rgb` | High-res optical (RGB) | SwinV2 Huge | `skysense_model_backbone_hr.pth` |
20
+ | `skysense-vit-large-s2` | Sentinel-2 | ViT-Large | `skysense_model_backbone_s2.pth` |
21
+ | `skysense-vit-large-s1` | Sentinel-1 SAR | ViT-Large | `skysense_model_backbone_s1.pth` |
22
+
23
+ Each subdirectory is a self-contained HuggingFace model repo with remote code (`trust_remote_code=True`).
24
+
25
+ ## Usage
26
+
27
+ ```python
28
+ from transformers import pipeline
29
+ import torch
30
+
31
+ # HR RGB backbone — input 224×224
32
+ hr_pipe = pipeline(
33
+ task="image-feature-extraction",
34
+ model="/path/to/SkySense-transformers/skysense-swinv2-huge-rgb",
35
+ trust_remote_code=True,
36
+ device="cpu",
37
+ )
38
+ hr_img = torch.randn(1, 3, 224, 224)
39
+ features = hr_pipe(hr_img)
40
+ print(features["last_hidden_state"].shape) # (1, 2816, 7, 7)
41
+
42
+ # Sentinel-2 — 10 bands, 64×64
43
+ s2_pipe = pipeline(
44
+ task="image-feature-extraction",
45
+ model="/path/to/SkySense-transformers/skysense-vit-large-s2",
46
+ trust_remote_code=True,
47
+ device="cpu",
48
+ )
49
+ s2_img = torch.randn(1, 10, 64, 64)
50
+ features = s2_pipe(s2_img)
51
+ print(features["last_hidden_state"].shape) # (1, 1024, 16, 16)
52
+
53
+ # Sentinel-1 — VV/VH, 64×64
54
+ s1_pipe = pipeline(
55
+ task="image-feature-extraction",
56
+ model="/path/to/SkySense-transformers/skysense-vit-large-s1",
57
+ trust_remote_code=True,
58
+ device="cpu",
59
+ )
60
+ s1_img = torch.randn(1, 2, 64, 64)
61
+ features = s1_pipe(s1_img)
62
+ print(features["last_hidden_state"].shape)
63
+ ```
64
+
65
+ ## Conversion
66
+
67
+ Source project: `/home/czy/local/projects/SkySense-transformers`
68
+
69
+ ```bash
70
+ conda activate rsgen
71
+
72
+ python scripts/convert_checkpoint_to_hf.py \
73
+ --input-path /path/to/skysense_model_backbone_hr.pth \
74
+ --modality hr \
75
+ --output-dir /path/to/skysense-swinv2-huge-rgb \
76
+ --clean-output
77
+
78
+ python scripts/convert_checkpoint_to_hf.py \
79
+ --input-path /path/to/skysense_model_backbone_s2.pth \
80
+ --modality s2 \
81
+ --output-dir /path/to/skysense-vit-large-s2 \
82
+ --clean-output
83
+
84
+ python scripts/convert_checkpoint_to_hf.py \
85
+ --input-path /path/to/skysense_model_backbone_s1.pth \
86
+ --modality s1 \
87
+ --output-dir /path/to/skysense-vit-large-s1 \
88
+ --clean-output
89
+ ```
90
+
91
+ The converter also accepts unified pretraining checkpoints with `backbone_gep.*` / `backbone_s2.*` / `backbone_s1.*` prefixes.
92
+
93
+ ## Notes
94
+
95
+ - HR conversion skips Swin relative-position buffers (`relative_position_index`, `relative_coords_table`) and `mask_token`. Buffers are **deterministically recomputed** at init; learned CPB weights are loaded.
96
+ - ViT checkpoints use per-layer `ln1`/`ln2` keys remapped to `norm1`/`norm2`.
97
+ - Swin FFN keys `ffn.layers.0.0` → `ffn.layers.0`, `ffn.layers.1` → `ffn.layers.3`.
98
+ - HR Swin uses `pad_small_map=True` so 224×224 inputs work with window size 8 at deep stages.
skysense-swinv2-huge-rgb/config.json ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "return_dict": true,
3
+ "output_hidden_states": false,
4
+ "dtype": "float32",
5
+ "chunk_size_feed_forward": 0,
6
+ "is_encoder_decoder": false,
7
+ "architectures": [
8
+ "SkySenseSwinV2Model"
9
+ ],
10
+ "id2label": {
11
+ "0": "LABEL_0",
12
+ "1": "LABEL_1"
13
+ },
14
+ "label2id": {
15
+ "LABEL_0": 0,
16
+ "LABEL_1": 1
17
+ },
18
+ "problem_type": null,
19
+ "_name_or_path": "",
20
+ "transformers_version": "5.0.0",
21
+ "arch": "huge",
22
+ "embed_dims": 352,
23
+ "depths": [
24
+ 2,
25
+ 2,
26
+ 18,
27
+ 2
28
+ ],
29
+ "num_heads": [
30
+ 8,
31
+ 16,
32
+ 32,
33
+ 64
34
+ ],
35
+ "extra_norm_every_n_blocks": 6,
36
+ "img_size": 224,
37
+ "patch_size": 4,
38
+ "in_channels": 3,
39
+ "window_size": 8,
40
+ "drop_rate": 0.0,
41
+ "drop_path_rate": 0.1,
42
+ "out_indices": [
43
+ 3
44
+ ],
45
+ "use_abs_pos_embed": false,
46
+ "with_cp": false,
47
+ "pad_small_map": true,
48
+ "pretrained_window_sizes": [
49
+ 0,
50
+ 0,
51
+ 0,
52
+ 0
53
+ ],
54
+ "is_post_norm_downsample": true,
55
+ "model_type": "skysense_swinv2",
56
+ "output_attentions": false,
57
+ "auto_map": {
58
+ "AutoConfig": "configuration_skysense.SkySenseSwinV2Config",
59
+ "AutoModel": "modeling_skysense_swinv2.SkySenseSwinV2Model"
60
+ },
61
+ "custom_pipelines": {
62
+ "skysense-feature-extraction": {
63
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
64
+ "pt": [
65
+ "AutoModel"
66
+ ]
67
+ },
68
+ "image-feature-extraction": {
69
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
70
+ "pt": [
71
+ "AutoModel"
72
+ ]
73
+ }
74
+ }
75
+ }
skysense-swinv2-huge-rgb/configuration_skysense.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration classes for SkySense models."""
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class SkySenseSwinV2Config(PretrainedConfig):
7
+ """Configuration class for SkySense Swin Transformer V2 backbone.
8
+
9
+ This model handles high-resolution optical imagery (RGB/RGBNIR).
10
+
11
+ Args:
12
+ arch (str): Architecture variant. One of 'tiny', 'small', 'base',
13
+ 'large', 'huge', 'giant'. Default: 'huge'.
14
+ img_size (int): Input image size. Default: 224.
15
+ patch_size (int): Patch size. Default: 4.
16
+ in_channels (int): Number of input channels. Default: 3.
17
+ window_size (int or list): Window size for each stage. Default: 8.
18
+ drop_rate (float): Dropout rate after embedding. Default: 0.0.
19
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1.
20
+ out_indices (list): Output indices from stages. Default: [3].
21
+ use_abs_pos_embed (bool): Use absolute position embedding. Default: False.
22
+ with_cp (bool): Use gradient checkpointing. Default: False.
23
+ pad_small_map (bool): Pad small maps to window size. Default: False.
24
+ pretrained_window_sizes (list): Pretrained window sizes. Default: [0, 0, 0, 0].
25
+ is_post_norm_downsample (bool): Use post-norm in downsample. Default: True.
26
+ """
27
+
28
+ model_type = "skysense_swinv2"
29
+
30
+ arch_zoo = {
31
+ 'tiny': {'embed_dims': 96, 'depths': [2, 2, 6, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
32
+ 'small': {'embed_dims': 96, 'depths': [2, 2, 18, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
33
+ 'base': {'embed_dims': 128, 'depths': [2, 2, 18, 2], 'num_heads': [4, 8, 16, 32], 'extra_norm_every_n_blocks': 0},
34
+ 'large': {'embed_dims': 192, 'depths': [2, 2, 18, 2], 'num_heads': [6, 12, 24, 48], 'extra_norm_every_n_blocks': 0},
35
+ 'huge': {'embed_dims': 352, 'depths': [2, 2, 18, 2], 'num_heads': [8, 16, 32, 64], 'extra_norm_every_n_blocks': 6},
36
+ 'giant': {'embed_dims': 512, 'depths': [2, 2, 42, 4], 'num_heads': [16, 32, 64, 128], 'extra_norm_every_n_blocks': 6},
37
+ }
38
+
39
+ def __init__(
40
+ self,
41
+ arch="huge",
42
+ img_size=224,
43
+ patch_size=4,
44
+ in_channels=3,
45
+ window_size=8,
46
+ drop_rate=0.0,
47
+ drop_path_rate=0.1,
48
+ out_indices=(3,),
49
+ use_abs_pos_embed=False,
50
+ with_cp=False,
51
+ pad_small_map=False,
52
+ pretrained_window_sizes=(0, 0, 0, 0),
53
+ is_post_norm_downsample=True,
54
+ **kwargs,
55
+ ):
56
+ super().__init__(**kwargs)
57
+
58
+ if isinstance(arch, str):
59
+ arch = arch.lower()
60
+ if arch not in self.arch_zoo:
61
+ raise ValueError(f"Unknown arch '{arch}'. Choose from {list(self.arch_zoo.keys())}")
62
+ arch_settings = self.arch_zoo[arch]
63
+ else:
64
+ arch_settings = arch
65
+
66
+ self.arch = arch
67
+ self.embed_dims = arch_settings['embed_dims']
68
+ self.depths = arch_settings['depths']
69
+ self.num_heads = arch_settings['num_heads']
70
+ self.extra_norm_every_n_blocks = arch_settings['extra_norm_every_n_blocks']
71
+
72
+ self.img_size = img_size
73
+ self.patch_size = patch_size
74
+ self.in_channels = in_channels
75
+ self.window_size = window_size
76
+ self.drop_rate = drop_rate
77
+ self.drop_path_rate = drop_path_rate
78
+ self.out_indices = list(out_indices)
79
+ self.use_abs_pos_embed = use_abs_pos_embed
80
+ self.with_cp = with_cp
81
+ self.pad_small_map = pad_small_map
82
+ self.pretrained_window_sizes = list(pretrained_window_sizes)
83
+ self.is_post_norm_downsample = is_post_norm_downsample
84
+
85
+
86
+ class SkySenseViTConfig(PretrainedConfig):
87
+ """Configuration class for SkySense Vision Transformer backbone.
88
+
89
+ This model handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
90
+
91
+ Args:
92
+ img_size (int): Input image size. Default: 64.
93
+ patch_size (int): Patch size. Default: 4.
94
+ in_channels (int): Number of input channels.
95
+ 10 for Sentinel-2, 2 for Sentinel-1. Default: 10.
96
+ embed_dims (int): Embedding dimension. Default: 1024.
97
+ num_layers (int): Number of transformer layers. Default: 24.
98
+ num_heads (int): Number of attention heads. Default: 16.
99
+ mlp_ratio (int): MLP hidden dim ratio. Default: 4.
100
+ out_indices (list): Output indices. Default: [-1].
101
+ qkv_bias (bool): QKV bias. Default: True.
102
+ drop_rate (float): Dropout rate. Default: 0.0.
103
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
104
+ drop_path_rate (float): Stochastic depth rate. Default: 0.3.
105
+ with_cls_token (bool): Use CLS token. Default: True.
106
+ output_cls_token (bool): Output CLS token. Default: False.
107
+ patch_norm (bool): Norm in patch embed. Default: False.
108
+ final_norm (bool): Final layer norm. Default: False.
109
+ with_cp (bool): Use gradient checkpointing. Default: False.
110
+ """
111
+
112
+ model_type = "skysense_vit"
113
+
114
+ def __init__(
115
+ self,
116
+ img_size=64,
117
+ patch_size=4,
118
+ in_channels=10,
119
+ embed_dims=1024,
120
+ num_layers=24,
121
+ num_heads=16,
122
+ mlp_ratio=4,
123
+ out_indices=(-1,),
124
+ qkv_bias=True,
125
+ drop_rate=0.0,
126
+ attn_drop_rate=0.0,
127
+ drop_path_rate=0.3,
128
+ with_cls_token=True,
129
+ output_cls_token=False,
130
+ patch_norm=False,
131
+ final_norm=False,
132
+ with_cp=False,
133
+ **kwargs,
134
+ ):
135
+ super().__init__(**kwargs)
136
+ self.img_size = img_size
137
+ self.patch_size = patch_size
138
+ self.in_channels = in_channels
139
+ self.embed_dims = embed_dims
140
+ self.num_layers = num_layers
141
+ self.num_heads = num_heads
142
+ self.mlp_ratio = mlp_ratio
143
+ self.out_indices = list(out_indices)
144
+ self.qkv_bias = qkv_bias
145
+ self.drop_rate = drop_rate
146
+ self.attn_drop_rate = attn_drop_rate
147
+ self.drop_path_rate = drop_path_rate
148
+ self.with_cls_token = with_cls_token
149
+ self.output_cls_token = output_cls_token
150
+ self.patch_norm = patch_norm
151
+ self.final_norm = final_norm
152
+ self.with_cp = with_cp
skysense-swinv2-huge-rgb/conversion_manifest.json ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_checkpoint": "/exstorage/czy/models/raw/skysense_model_backbone_hr.pth",
3
+ "modality": "hr",
4
+ "model_class": "SkySenseSwinV2Model",
5
+ "num_tensors": 429,
6
+ "missing_keys": [
7
+ "stages.0.blocks.0.attn.w_msa.relative_coords_table",
8
+ "stages.0.blocks.0.attn.w_msa.relative_position_index",
9
+ "stages.0.blocks.1.attn.w_msa.relative_coords_table",
10
+ "stages.0.blocks.1.attn.w_msa.relative_position_index",
11
+ "stages.1.blocks.0.attn.w_msa.relative_coords_table",
12
+ "stages.1.blocks.0.attn.w_msa.relative_position_index",
13
+ "stages.1.blocks.1.attn.w_msa.relative_coords_table",
14
+ "stages.1.blocks.1.attn.w_msa.relative_position_index",
15
+ "stages.2.blocks.0.attn.w_msa.relative_coords_table",
16
+ "stages.2.blocks.0.attn.w_msa.relative_position_index",
17
+ "stages.2.blocks.1.attn.w_msa.relative_coords_table",
18
+ "stages.2.blocks.1.attn.w_msa.relative_position_index",
19
+ "stages.2.blocks.2.attn.w_msa.relative_coords_table",
20
+ "stages.2.blocks.2.attn.w_msa.relative_position_index",
21
+ "stages.2.blocks.3.attn.w_msa.relative_coords_table",
22
+ "stages.2.blocks.3.attn.w_msa.relative_position_index",
23
+ "stages.2.blocks.4.attn.w_msa.relative_coords_table",
24
+ "stages.2.blocks.4.attn.w_msa.relative_position_index",
25
+ "stages.2.blocks.5.attn.w_msa.relative_coords_table",
26
+ "stages.2.blocks.5.attn.w_msa.relative_position_index",
27
+ "stages.2.blocks.6.attn.w_msa.relative_coords_table",
28
+ "stages.2.blocks.6.attn.w_msa.relative_position_index",
29
+ "stages.2.blocks.7.attn.w_msa.relative_coords_table",
30
+ "stages.2.blocks.7.attn.w_msa.relative_position_index",
31
+ "stages.2.blocks.8.attn.w_msa.relative_coords_table",
32
+ "stages.2.blocks.8.attn.w_msa.relative_position_index",
33
+ "stages.2.blocks.9.attn.w_msa.relative_coords_table",
34
+ "stages.2.blocks.9.attn.w_msa.relative_position_index",
35
+ "stages.2.blocks.10.attn.w_msa.relative_coords_table",
36
+ "stages.2.blocks.10.attn.w_msa.relative_position_index",
37
+ "stages.2.blocks.11.attn.w_msa.relative_coords_table",
38
+ "stages.2.blocks.11.attn.w_msa.relative_position_index",
39
+ "stages.2.blocks.12.attn.w_msa.relative_coords_table",
40
+ "stages.2.blocks.12.attn.w_msa.relative_position_index",
41
+ "stages.2.blocks.13.attn.w_msa.relative_coords_table",
42
+ "stages.2.blocks.13.attn.w_msa.relative_position_index",
43
+ "stages.2.blocks.14.attn.w_msa.relative_coords_table",
44
+ "stages.2.blocks.14.attn.w_msa.relative_position_index",
45
+ "stages.2.blocks.15.attn.w_msa.relative_coords_table",
46
+ "stages.2.blocks.15.attn.w_msa.relative_position_index",
47
+ "stages.2.blocks.16.attn.w_msa.relative_coords_table",
48
+ "stages.2.blocks.16.attn.w_msa.relative_position_index",
49
+ "stages.2.blocks.17.attn.w_msa.relative_coords_table",
50
+ "stages.2.blocks.17.attn.w_msa.relative_position_index",
51
+ "stages.3.blocks.0.attn.w_msa.relative_coords_table",
52
+ "stages.3.blocks.0.attn.w_msa.relative_position_index",
53
+ "stages.3.blocks.1.attn.w_msa.relative_coords_table",
54
+ "stages.3.blocks.1.attn.w_msa.relative_position_index"
55
+ ],
56
+ "unexpected_keys": [],
57
+ "tensor_names": [
58
+ "norm3.bias",
59
+ "norm3.weight",
60
+ "patch_embed.norm.bias",
61
+ "patch_embed.norm.weight",
62
+ "patch_embed.projection.bias",
63
+ "patch_embed.projection.weight",
64
+ "stages.0.blocks.0.attn.w_msa.cpb_mlp.0.bias",
65
+ "stages.0.blocks.0.attn.w_msa.cpb_mlp.0.weight",
66
+ "stages.0.blocks.0.attn.w_msa.cpb_mlp.2.weight",
67
+ "stages.0.blocks.0.attn.w_msa.logit_scale",
68
+ "stages.0.blocks.0.attn.w_msa.proj.bias",
69
+ "stages.0.blocks.0.attn.w_msa.proj.weight",
70
+ "stages.0.blocks.0.attn.w_msa.q_bias",
71
+ "stages.0.blocks.0.attn.w_msa.qkv.weight",
72
+ "stages.0.blocks.0.attn.w_msa.v_bias",
73
+ "stages.0.blocks.0.ffn.layers.0.bias",
74
+ "stages.0.blocks.0.ffn.layers.0.weight",
75
+ "stages.0.blocks.0.ffn.layers.3.bias",
76
+ "stages.0.blocks.0.ffn.layers.3.weight",
77
+ "stages.0.blocks.0.norm1.bias",
78
+ "stages.0.blocks.0.norm1.weight",
79
+ "stages.0.blocks.0.norm2.bias",
80
+ "stages.0.blocks.0.norm2.weight",
81
+ "stages.0.blocks.1.attn.w_msa.cpb_mlp.0.bias",
82
+ "stages.0.blocks.1.attn.w_msa.cpb_mlp.0.weight",
83
+ "stages.0.blocks.1.attn.w_msa.cpb_mlp.2.weight",
84
+ "stages.0.blocks.1.attn.w_msa.logit_scale",
85
+ "stages.0.blocks.1.attn.w_msa.proj.bias",
86
+ "stages.0.blocks.1.attn.w_msa.proj.weight",
87
+ "stages.0.blocks.1.attn.w_msa.q_bias",
88
+ "stages.0.blocks.1.attn.w_msa.qkv.weight",
89
+ "stages.0.blocks.1.attn.w_msa.v_bias",
90
+ "stages.0.blocks.1.ffn.layers.0.bias",
91
+ "stages.0.blocks.1.ffn.layers.0.weight",
92
+ "stages.0.blocks.1.ffn.layers.3.bias",
93
+ "stages.0.blocks.1.ffn.layers.3.weight",
94
+ "stages.0.blocks.1.norm1.bias",
95
+ "stages.0.blocks.1.norm1.weight",
96
+ "stages.0.blocks.1.norm2.bias",
97
+ "stages.0.blocks.1.norm2.weight",
98
+ "stages.1.blocks.0.attn.w_msa.cpb_mlp.0.bias",
99
+ "stages.1.blocks.0.attn.w_msa.cpb_mlp.0.weight",
100
+ "stages.1.blocks.0.attn.w_msa.cpb_mlp.2.weight",
101
+ "stages.1.blocks.0.attn.w_msa.logit_scale",
102
+ "stages.1.blocks.0.attn.w_msa.proj.bias",
103
+ "stages.1.blocks.0.attn.w_msa.proj.weight",
104
+ "stages.1.blocks.0.attn.w_msa.q_bias",
105
+ "stages.1.blocks.0.attn.w_msa.qkv.weight",
106
+ "stages.1.blocks.0.attn.w_msa.v_bias",
107
+ "stages.1.blocks.0.ffn.layers.0.bias",
108
+ "stages.1.blocks.0.ffn.layers.0.weight",
109
+ "stages.1.blocks.0.ffn.layers.3.bias",
110
+ "stages.1.blocks.0.ffn.layers.3.weight",
111
+ "stages.1.blocks.0.norm1.bias",
112
+ "stages.1.blocks.0.norm1.weight",
113
+ "stages.1.blocks.0.norm2.bias",
114
+ "stages.1.blocks.0.norm2.weight",
115
+ "stages.1.blocks.1.attn.w_msa.cpb_mlp.0.bias",
116
+ "stages.1.blocks.1.attn.w_msa.cpb_mlp.0.weight",
117
+ "stages.1.blocks.1.attn.w_msa.cpb_mlp.2.weight",
118
+ "stages.1.blocks.1.attn.w_msa.logit_scale",
119
+ "stages.1.blocks.1.attn.w_msa.proj.bias",
120
+ "stages.1.blocks.1.attn.w_msa.proj.weight",
121
+ "stages.1.blocks.1.attn.w_msa.q_bias",
122
+ "stages.1.blocks.1.attn.w_msa.qkv.weight",
123
+ "stages.1.blocks.1.attn.w_msa.v_bias",
124
+ "stages.1.blocks.1.ffn.layers.0.bias",
125
+ "stages.1.blocks.1.ffn.layers.0.weight",
126
+ "stages.1.blocks.1.ffn.layers.3.bias",
127
+ "stages.1.blocks.1.ffn.layers.3.weight",
128
+ "stages.1.blocks.1.norm1.bias",
129
+ "stages.1.blocks.1.norm1.weight",
130
+ "stages.1.blocks.1.norm2.bias",
131
+ "stages.1.blocks.1.norm2.weight",
132
+ "stages.1.downsample.norm.bias",
133
+ "stages.1.downsample.norm.weight",
134
+ "stages.1.downsample.reduction.weight",
135
+ "stages.2.blocks.0.attn.w_msa.cpb_mlp.0.bias",
136
+ "stages.2.blocks.0.attn.w_msa.cpb_mlp.0.weight",
137
+ "stages.2.blocks.0.attn.w_msa.cpb_mlp.2.weight",
138
+ "stages.2.blocks.0.attn.w_msa.logit_scale",
139
+ "stages.2.blocks.0.attn.w_msa.proj.bias",
140
+ "stages.2.blocks.0.attn.w_msa.proj.weight",
141
+ "stages.2.blocks.0.attn.w_msa.q_bias",
142
+ "stages.2.blocks.0.attn.w_msa.qkv.weight",
143
+ "stages.2.blocks.0.attn.w_msa.v_bias",
144
+ "stages.2.blocks.0.ffn.layers.0.bias",
145
+ "stages.2.blocks.0.ffn.layers.0.weight",
146
+ "stages.2.blocks.0.ffn.layers.3.bias",
147
+ "stages.2.blocks.0.ffn.layers.3.weight",
148
+ "stages.2.blocks.0.norm1.bias",
149
+ "stages.2.blocks.0.norm1.weight",
150
+ "stages.2.blocks.0.norm2.bias",
151
+ "stages.2.blocks.0.norm2.weight",
152
+ "stages.2.blocks.1.attn.w_msa.cpb_mlp.0.bias",
153
+ "stages.2.blocks.1.attn.w_msa.cpb_mlp.0.weight",
154
+ "stages.2.blocks.1.attn.w_msa.cpb_mlp.2.weight",
155
+ "stages.2.blocks.1.attn.w_msa.logit_scale",
156
+ "stages.2.blocks.1.attn.w_msa.proj.bias",
157
+ "stages.2.blocks.1.attn.w_msa.proj.weight",
158
+ "stages.2.blocks.1.attn.w_msa.q_bias",
159
+ "stages.2.blocks.1.attn.w_msa.qkv.weight",
160
+ "stages.2.blocks.1.attn.w_msa.v_bias",
161
+ "stages.2.blocks.1.ffn.layers.0.bias",
162
+ "stages.2.blocks.1.ffn.layers.0.weight",
163
+ "stages.2.blocks.1.ffn.layers.3.bias",
164
+ "stages.2.blocks.1.ffn.layers.3.weight",
165
+ "stages.2.blocks.1.norm1.bias",
166
+ "stages.2.blocks.1.norm1.weight",
167
+ "stages.2.blocks.1.norm2.bias",
168
+ "stages.2.blocks.1.norm2.weight",
169
+ "stages.2.blocks.10.attn.w_msa.cpb_mlp.0.bias",
170
+ "stages.2.blocks.10.attn.w_msa.cpb_mlp.0.weight",
171
+ "stages.2.blocks.10.attn.w_msa.cpb_mlp.2.weight",
172
+ "stages.2.blocks.10.attn.w_msa.logit_scale",
173
+ "stages.2.blocks.10.attn.w_msa.proj.bias",
174
+ "stages.2.blocks.10.attn.w_msa.proj.weight",
175
+ "stages.2.blocks.10.attn.w_msa.q_bias",
176
+ "stages.2.blocks.10.attn.w_msa.qkv.weight",
177
+ "stages.2.blocks.10.attn.w_msa.v_bias",
178
+ "stages.2.blocks.10.ffn.layers.0.bias",
179
+ "stages.2.blocks.10.ffn.layers.0.weight",
180
+ "stages.2.blocks.10.ffn.layers.3.bias",
181
+ "stages.2.blocks.10.ffn.layers.3.weight",
182
+ "stages.2.blocks.10.norm1.bias",
183
+ "stages.2.blocks.10.norm1.weight",
184
+ "stages.2.blocks.10.norm2.bias",
185
+ "stages.2.blocks.10.norm2.weight",
186
+ "stages.2.blocks.11.attn.w_msa.cpb_mlp.0.bias",
187
+ "stages.2.blocks.11.attn.w_msa.cpb_mlp.0.weight",
188
+ "stages.2.blocks.11.attn.w_msa.cpb_mlp.2.weight",
189
+ "stages.2.blocks.11.attn.w_msa.logit_scale",
190
+ "stages.2.blocks.11.attn.w_msa.proj.bias",
191
+ "stages.2.blocks.11.attn.w_msa.proj.weight",
192
+ "stages.2.blocks.11.attn.w_msa.q_bias",
193
+ "stages.2.blocks.11.attn.w_msa.qkv.weight",
194
+ "stages.2.blocks.11.attn.w_msa.v_bias",
195
+ "stages.2.blocks.11.ffn.layers.0.bias",
196
+ "stages.2.blocks.11.ffn.layers.0.weight",
197
+ "stages.2.blocks.11.ffn.layers.3.bias",
198
+ "stages.2.blocks.11.ffn.layers.3.weight",
199
+ "stages.2.blocks.11.norm1.bias",
200
+ "stages.2.blocks.11.norm1.weight",
201
+ "stages.2.blocks.11.norm2.bias",
202
+ "stages.2.blocks.11.norm2.weight",
203
+ "stages.2.blocks.11.norm3.bias",
204
+ "stages.2.blocks.11.norm3.weight",
205
+ "stages.2.blocks.12.attn.w_msa.cpb_mlp.0.bias",
206
+ "stages.2.blocks.12.attn.w_msa.cpb_mlp.0.weight",
207
+ "stages.2.blocks.12.attn.w_msa.cpb_mlp.2.weight",
208
+ "stages.2.blocks.12.attn.w_msa.logit_scale",
209
+ "stages.2.blocks.12.attn.w_msa.proj.bias",
210
+ "stages.2.blocks.12.attn.w_msa.proj.weight",
211
+ "stages.2.blocks.12.attn.w_msa.q_bias",
212
+ "stages.2.blocks.12.attn.w_msa.qkv.weight",
213
+ "stages.2.blocks.12.attn.w_msa.v_bias",
214
+ "stages.2.blocks.12.ffn.layers.0.bias",
215
+ "stages.2.blocks.12.ffn.layers.0.weight",
216
+ "stages.2.blocks.12.ffn.layers.3.bias",
217
+ "stages.2.blocks.12.ffn.layers.3.weight",
218
+ "stages.2.blocks.12.norm1.bias",
219
+ "stages.2.blocks.12.norm1.weight",
220
+ "stages.2.blocks.12.norm2.bias",
221
+ "stages.2.blocks.12.norm2.weight",
222
+ "stages.2.blocks.13.attn.w_msa.cpb_mlp.0.bias",
223
+ "stages.2.blocks.13.attn.w_msa.cpb_mlp.0.weight",
224
+ "stages.2.blocks.13.attn.w_msa.cpb_mlp.2.weight",
225
+ "stages.2.blocks.13.attn.w_msa.logit_scale",
226
+ "stages.2.blocks.13.attn.w_msa.proj.bias",
227
+ "stages.2.blocks.13.attn.w_msa.proj.weight",
228
+ "stages.2.blocks.13.attn.w_msa.q_bias",
229
+ "stages.2.blocks.13.attn.w_msa.qkv.weight",
230
+ "stages.2.blocks.13.attn.w_msa.v_bias",
231
+ "stages.2.blocks.13.ffn.layers.0.bias",
232
+ "stages.2.blocks.13.ffn.layers.0.weight",
233
+ "stages.2.blocks.13.ffn.layers.3.bias",
234
+ "stages.2.blocks.13.ffn.layers.3.weight",
235
+ "stages.2.blocks.13.norm1.bias",
236
+ "stages.2.blocks.13.norm1.weight",
237
+ "stages.2.blocks.13.norm2.bias",
238
+ "stages.2.blocks.13.norm2.weight",
239
+ "stages.2.blocks.14.attn.w_msa.cpb_mlp.0.bias",
240
+ "stages.2.blocks.14.attn.w_msa.cpb_mlp.0.weight",
241
+ "stages.2.blocks.14.attn.w_msa.cpb_mlp.2.weight",
242
+ "stages.2.blocks.14.attn.w_msa.logit_scale",
243
+ "stages.2.blocks.14.attn.w_msa.proj.bias",
244
+ "stages.2.blocks.14.attn.w_msa.proj.weight",
245
+ "stages.2.blocks.14.attn.w_msa.q_bias",
246
+ "stages.2.blocks.14.attn.w_msa.qkv.weight",
247
+ "stages.2.blocks.14.attn.w_msa.v_bias",
248
+ "stages.2.blocks.14.ffn.layers.0.bias",
249
+ "stages.2.blocks.14.ffn.layers.0.weight",
250
+ "stages.2.blocks.14.ffn.layers.3.bias",
251
+ "stages.2.blocks.14.ffn.layers.3.weight",
252
+ "stages.2.blocks.14.norm1.bias",
253
+ "stages.2.blocks.14.norm1.weight",
254
+ "stages.2.blocks.14.norm2.bias",
255
+ "stages.2.blocks.14.norm2.weight",
256
+ "stages.2.blocks.15.attn.w_msa.cpb_mlp.0.bias",
257
+ "stages.2.blocks.15.attn.w_msa.cpb_mlp.0.weight",
258
+ "stages.2.blocks.15.attn.w_msa.cpb_mlp.2.weight",
259
+ "stages.2.blocks.15.attn.w_msa.logit_scale",
260
+ "stages.2.blocks.15.attn.w_msa.proj.bias",
261
+ "stages.2.blocks.15.attn.w_msa.proj.weight",
262
+ "stages.2.blocks.15.attn.w_msa.q_bias",
263
+ "stages.2.blocks.15.attn.w_msa.qkv.weight",
264
+ "stages.2.blocks.15.attn.w_msa.v_bias",
265
+ "stages.2.blocks.15.ffn.layers.0.bias",
266
+ "stages.2.blocks.15.ffn.layers.0.weight",
267
+ "stages.2.blocks.15.ffn.layers.3.bias",
268
+ "stages.2.blocks.15.ffn.layers.3.weight",
269
+ "stages.2.blocks.15.norm1.bias",
270
+ "stages.2.blocks.15.norm1.weight",
271
+ "stages.2.blocks.15.norm2.bias",
272
+ "stages.2.blocks.15.norm2.weight",
273
+ "stages.2.blocks.16.attn.w_msa.cpb_mlp.0.bias",
274
+ "stages.2.blocks.16.attn.w_msa.cpb_mlp.0.weight",
275
+ "stages.2.blocks.16.attn.w_msa.cpb_mlp.2.weight",
276
+ "stages.2.blocks.16.attn.w_msa.logit_scale",
277
+ "stages.2.blocks.16.attn.w_msa.proj.bias",
278
+ "stages.2.blocks.16.attn.w_msa.proj.weight",
279
+ "stages.2.blocks.16.attn.w_msa.q_bias",
280
+ "stages.2.blocks.16.attn.w_msa.qkv.weight",
281
+ "stages.2.blocks.16.attn.w_msa.v_bias",
282
+ "stages.2.blocks.16.ffn.layers.0.bias",
283
+ "stages.2.blocks.16.ffn.layers.0.weight",
284
+ "stages.2.blocks.16.ffn.layers.3.bias",
285
+ "stages.2.blocks.16.ffn.layers.3.weight",
286
+ "stages.2.blocks.16.norm1.bias",
287
+ "stages.2.blocks.16.norm1.weight",
288
+ "stages.2.blocks.16.norm2.bias",
289
+ "stages.2.blocks.16.norm2.weight",
290
+ "stages.2.blocks.17.attn.w_msa.cpb_mlp.0.bias",
291
+ "stages.2.blocks.17.attn.w_msa.cpb_mlp.0.weight",
292
+ "stages.2.blocks.17.attn.w_msa.cpb_mlp.2.weight",
293
+ "stages.2.blocks.17.attn.w_msa.logit_scale",
294
+ "stages.2.blocks.17.attn.w_msa.proj.bias",
295
+ "stages.2.blocks.17.attn.w_msa.proj.weight",
296
+ "stages.2.blocks.17.attn.w_msa.q_bias",
297
+ "stages.2.blocks.17.attn.w_msa.qkv.weight",
298
+ "stages.2.blocks.17.attn.w_msa.v_bias",
299
+ "stages.2.blocks.17.ffn.layers.0.bias",
300
+ "stages.2.blocks.17.ffn.layers.0.weight",
301
+ "stages.2.blocks.17.ffn.layers.3.bias",
302
+ "stages.2.blocks.17.ffn.layers.3.weight",
303
+ "stages.2.blocks.17.norm1.bias",
304
+ "stages.2.blocks.17.norm1.weight",
305
+ "stages.2.blocks.17.norm2.bias",
306
+ "stages.2.blocks.17.norm2.weight",
307
+ "stages.2.blocks.17.norm3.bias",
308
+ "stages.2.blocks.17.norm3.weight",
309
+ "stages.2.blocks.2.attn.w_msa.cpb_mlp.0.bias",
310
+ "stages.2.blocks.2.attn.w_msa.cpb_mlp.0.weight",
311
+ "stages.2.blocks.2.attn.w_msa.cpb_mlp.2.weight",
312
+ "stages.2.blocks.2.attn.w_msa.logit_scale",
313
+ "stages.2.blocks.2.attn.w_msa.proj.bias",
314
+ "stages.2.blocks.2.attn.w_msa.proj.weight",
315
+ "stages.2.blocks.2.attn.w_msa.q_bias",
316
+ "stages.2.blocks.2.attn.w_msa.qkv.weight",
317
+ "stages.2.blocks.2.attn.w_msa.v_bias",
318
+ "stages.2.blocks.2.ffn.layers.0.bias",
319
+ "stages.2.blocks.2.ffn.layers.0.weight",
320
+ "stages.2.blocks.2.ffn.layers.3.bias",
321
+ "stages.2.blocks.2.ffn.layers.3.weight",
322
+ "stages.2.blocks.2.norm1.bias",
323
+ "stages.2.blocks.2.norm1.weight",
324
+ "stages.2.blocks.2.norm2.bias",
325
+ "stages.2.blocks.2.norm2.weight",
326
+ "stages.2.blocks.3.attn.w_msa.cpb_mlp.0.bias",
327
+ "stages.2.blocks.3.attn.w_msa.cpb_mlp.0.weight",
328
+ "stages.2.blocks.3.attn.w_msa.cpb_mlp.2.weight",
329
+ "stages.2.blocks.3.attn.w_msa.logit_scale",
330
+ "stages.2.blocks.3.attn.w_msa.proj.bias",
331
+ "stages.2.blocks.3.attn.w_msa.proj.weight",
332
+ "stages.2.blocks.3.attn.w_msa.q_bias",
333
+ "stages.2.blocks.3.attn.w_msa.qkv.weight",
334
+ "stages.2.blocks.3.attn.w_msa.v_bias",
335
+ "stages.2.blocks.3.ffn.layers.0.bias",
336
+ "stages.2.blocks.3.ffn.layers.0.weight",
337
+ "stages.2.blocks.3.ffn.layers.3.bias",
338
+ "stages.2.blocks.3.ffn.layers.3.weight",
339
+ "stages.2.blocks.3.norm1.bias",
340
+ "stages.2.blocks.3.norm1.weight",
341
+ "stages.2.blocks.3.norm2.bias",
342
+ "stages.2.blocks.3.norm2.weight",
343
+ "stages.2.blocks.4.attn.w_msa.cpb_mlp.0.bias",
344
+ "stages.2.blocks.4.attn.w_msa.cpb_mlp.0.weight",
345
+ "stages.2.blocks.4.attn.w_msa.cpb_mlp.2.weight",
346
+ "stages.2.blocks.4.attn.w_msa.logit_scale",
347
+ "stages.2.blocks.4.attn.w_msa.proj.bias",
348
+ "stages.2.blocks.4.attn.w_msa.proj.weight",
349
+ "stages.2.blocks.4.attn.w_msa.q_bias",
350
+ "stages.2.blocks.4.attn.w_msa.qkv.weight",
351
+ "stages.2.blocks.4.attn.w_msa.v_bias",
352
+ "stages.2.blocks.4.ffn.layers.0.bias",
353
+ "stages.2.blocks.4.ffn.layers.0.weight",
354
+ "stages.2.blocks.4.ffn.layers.3.bias",
355
+ "stages.2.blocks.4.ffn.layers.3.weight",
356
+ "stages.2.blocks.4.norm1.bias",
357
+ "stages.2.blocks.4.norm1.weight",
358
+ "stages.2.blocks.4.norm2.bias",
359
+ "stages.2.blocks.4.norm2.weight",
360
+ "stages.2.blocks.5.attn.w_msa.cpb_mlp.0.bias",
361
+ "stages.2.blocks.5.attn.w_msa.cpb_mlp.0.weight",
362
+ "stages.2.blocks.5.attn.w_msa.cpb_mlp.2.weight",
363
+ "stages.2.blocks.5.attn.w_msa.logit_scale",
364
+ "stages.2.blocks.5.attn.w_msa.proj.bias",
365
+ "stages.2.blocks.5.attn.w_msa.proj.weight",
366
+ "stages.2.blocks.5.attn.w_msa.q_bias",
367
+ "stages.2.blocks.5.attn.w_msa.qkv.weight",
368
+ "stages.2.blocks.5.attn.w_msa.v_bias",
369
+ "stages.2.blocks.5.ffn.layers.0.bias",
370
+ "stages.2.blocks.5.ffn.layers.0.weight",
371
+ "stages.2.blocks.5.ffn.layers.3.bias",
372
+ "stages.2.blocks.5.ffn.layers.3.weight",
373
+ "stages.2.blocks.5.norm1.bias",
374
+ "stages.2.blocks.5.norm1.weight",
375
+ "stages.2.blocks.5.norm2.bias",
376
+ "stages.2.blocks.5.norm2.weight",
377
+ "stages.2.blocks.5.norm3.bias",
378
+ "stages.2.blocks.5.norm3.weight",
379
+ "stages.2.blocks.6.attn.w_msa.cpb_mlp.0.bias",
380
+ "stages.2.blocks.6.attn.w_msa.cpb_mlp.0.weight",
381
+ "stages.2.blocks.6.attn.w_msa.cpb_mlp.2.weight",
382
+ "stages.2.blocks.6.attn.w_msa.logit_scale",
383
+ "stages.2.blocks.6.attn.w_msa.proj.bias",
384
+ "stages.2.blocks.6.attn.w_msa.proj.weight",
385
+ "stages.2.blocks.6.attn.w_msa.q_bias",
386
+ "stages.2.blocks.6.attn.w_msa.qkv.weight",
387
+ "stages.2.blocks.6.attn.w_msa.v_bias",
388
+ "stages.2.blocks.6.ffn.layers.0.bias",
389
+ "stages.2.blocks.6.ffn.layers.0.weight",
390
+ "stages.2.blocks.6.ffn.layers.3.bias",
391
+ "stages.2.blocks.6.ffn.layers.3.weight",
392
+ "stages.2.blocks.6.norm1.bias",
393
+ "stages.2.blocks.6.norm1.weight",
394
+ "stages.2.blocks.6.norm2.bias",
395
+ "stages.2.blocks.6.norm2.weight",
396
+ "stages.2.blocks.7.attn.w_msa.cpb_mlp.0.bias",
397
+ "stages.2.blocks.7.attn.w_msa.cpb_mlp.0.weight",
398
+ "stages.2.blocks.7.attn.w_msa.cpb_mlp.2.weight",
399
+ "stages.2.blocks.7.attn.w_msa.logit_scale",
400
+ "stages.2.blocks.7.attn.w_msa.proj.bias",
401
+ "stages.2.blocks.7.attn.w_msa.proj.weight",
402
+ "stages.2.blocks.7.attn.w_msa.q_bias",
403
+ "stages.2.blocks.7.attn.w_msa.qkv.weight",
404
+ "stages.2.blocks.7.attn.w_msa.v_bias",
405
+ "stages.2.blocks.7.ffn.layers.0.bias",
406
+ "stages.2.blocks.7.ffn.layers.0.weight",
407
+ "stages.2.blocks.7.ffn.layers.3.bias",
408
+ "stages.2.blocks.7.ffn.layers.3.weight",
409
+ "stages.2.blocks.7.norm1.bias",
410
+ "stages.2.blocks.7.norm1.weight",
411
+ "stages.2.blocks.7.norm2.bias",
412
+ "stages.2.blocks.7.norm2.weight",
413
+ "stages.2.blocks.8.attn.w_msa.cpb_mlp.0.bias",
414
+ "stages.2.blocks.8.attn.w_msa.cpb_mlp.0.weight",
415
+ "stages.2.blocks.8.attn.w_msa.cpb_mlp.2.weight",
416
+ "stages.2.blocks.8.attn.w_msa.logit_scale",
417
+ "stages.2.blocks.8.attn.w_msa.proj.bias",
418
+ "stages.2.blocks.8.attn.w_msa.proj.weight",
419
+ "stages.2.blocks.8.attn.w_msa.q_bias",
420
+ "stages.2.blocks.8.attn.w_msa.qkv.weight",
421
+ "stages.2.blocks.8.attn.w_msa.v_bias",
422
+ "stages.2.blocks.8.ffn.layers.0.bias",
423
+ "stages.2.blocks.8.ffn.layers.0.weight",
424
+ "stages.2.blocks.8.ffn.layers.3.bias",
425
+ "stages.2.blocks.8.ffn.layers.3.weight",
426
+ "stages.2.blocks.8.norm1.bias",
427
+ "stages.2.blocks.8.norm1.weight",
428
+ "stages.2.blocks.8.norm2.bias",
429
+ "stages.2.blocks.8.norm2.weight",
430
+ "stages.2.blocks.9.attn.w_msa.cpb_mlp.0.bias",
431
+ "stages.2.blocks.9.attn.w_msa.cpb_mlp.0.weight",
432
+ "stages.2.blocks.9.attn.w_msa.cpb_mlp.2.weight",
433
+ "stages.2.blocks.9.attn.w_msa.logit_scale",
434
+ "stages.2.blocks.9.attn.w_msa.proj.bias",
435
+ "stages.2.blocks.9.attn.w_msa.proj.weight",
436
+ "stages.2.blocks.9.attn.w_msa.q_bias",
437
+ "stages.2.blocks.9.attn.w_msa.qkv.weight",
438
+ "stages.2.blocks.9.attn.w_msa.v_bias",
439
+ "stages.2.blocks.9.ffn.layers.0.bias",
440
+ "stages.2.blocks.9.ffn.layers.0.weight",
441
+ "stages.2.blocks.9.ffn.layers.3.bias",
442
+ "stages.2.blocks.9.ffn.layers.3.weight",
443
+ "stages.2.blocks.9.norm1.bias",
444
+ "stages.2.blocks.9.norm1.weight",
445
+ "stages.2.blocks.9.norm2.bias",
446
+ "stages.2.blocks.9.norm2.weight",
447
+ "stages.2.downsample.norm.bias",
448
+ "stages.2.downsample.norm.weight",
449
+ "stages.2.downsample.reduction.weight",
450
+ "stages.3.blocks.0.attn.w_msa.cpb_mlp.0.bias",
451
+ "stages.3.blocks.0.attn.w_msa.cpb_mlp.0.weight",
452
+ "stages.3.blocks.0.attn.w_msa.cpb_mlp.2.weight",
453
+ "stages.3.blocks.0.attn.w_msa.logit_scale",
454
+ "stages.3.blocks.0.attn.w_msa.proj.bias",
455
+ "stages.3.blocks.0.attn.w_msa.proj.weight",
456
+ "stages.3.blocks.0.attn.w_msa.q_bias",
457
+ "stages.3.blocks.0.attn.w_msa.qkv.weight",
458
+ "stages.3.blocks.0.attn.w_msa.v_bias",
459
+ "stages.3.blocks.0.ffn.layers.0.bias",
460
+ "stages.3.blocks.0.ffn.layers.0.weight",
461
+ "stages.3.blocks.0.ffn.layers.3.bias",
462
+ "stages.3.blocks.0.ffn.layers.3.weight",
463
+ "stages.3.blocks.0.norm1.bias",
464
+ "stages.3.blocks.0.norm1.weight",
465
+ "stages.3.blocks.0.norm2.bias",
466
+ "stages.3.blocks.0.norm2.weight",
467
+ "stages.3.blocks.1.attn.w_msa.cpb_mlp.0.bias",
468
+ "stages.3.blocks.1.attn.w_msa.cpb_mlp.0.weight",
469
+ "stages.3.blocks.1.attn.w_msa.cpb_mlp.2.weight",
470
+ "stages.3.blocks.1.attn.w_msa.logit_scale",
471
+ "stages.3.blocks.1.attn.w_msa.proj.bias",
472
+ "stages.3.blocks.1.attn.w_msa.proj.weight",
473
+ "stages.3.blocks.1.attn.w_msa.q_bias",
474
+ "stages.3.blocks.1.attn.w_msa.qkv.weight",
475
+ "stages.3.blocks.1.attn.w_msa.v_bias",
476
+ "stages.3.blocks.1.ffn.layers.0.bias",
477
+ "stages.3.blocks.1.ffn.layers.0.weight",
478
+ "stages.3.blocks.1.ffn.layers.3.bias",
479
+ "stages.3.blocks.1.ffn.layers.3.weight",
480
+ "stages.3.blocks.1.norm1.bias",
481
+ "stages.3.blocks.1.norm1.weight",
482
+ "stages.3.blocks.1.norm2.bias",
483
+ "stages.3.blocks.1.norm2.weight",
484
+ "stages.3.downsample.norm.bias",
485
+ "stages.3.downsample.norm.weight",
486
+ "stages.3.downsample.reduction.weight"
487
+ ]
488
+ }
skysense-swinv2-huge-rgb/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:369453004c0d5d61cacdb97fcb1a8ae6eec475358ecf7bb14195d2b76a74b75d
3
+ size 2621181016
skysense-swinv2-huge-rgb/modeling_skysense_swinv2.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Swin Transformer V2 backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles high-resolution optical imagery (RGB/RGBNIR).
4
+ """
5
+
6
+ from copy import deepcopy
7
+ from typing import Optional, Sequence, Tuple, Union
8
+
9
+ import numpy as np
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseSwinV2Config
17
+ from .modeling_utils import (
18
+ DropPath,
19
+ FFN,
20
+ PatchEmbed,
21
+ PatchMerging,
22
+ ShiftWindowMSA,
23
+ to_2tuple,
24
+ )
25
+
26
+
27
+ class SwinBlockV2(nn.Module):
28
+ """Swin Transformer V2 block with post-normalization.
29
+
30
+ Args:
31
+ embed_dims (int): Number of input channels.
32
+ num_heads (int): Number of attention heads.
33
+ window_size (int): Window size. Default: 8.
34
+ shift (bool): Shift the attention window. Default: False.
35
+ extra_norm (bool): Extra norm at end of block. Default: False.
36
+ ffn_ratio (float): FFN expansion ratio. Default: 4.0.
37
+ drop_path (float): Drop path rate. Default: 0.0.
38
+ pad_small_map (bool): Pad small maps. Default: False.
39
+ with_cp (bool): Gradient checkpointing. Default: False.
40
+ pretrained_window_size (int): Pretrained window size. Default: 0.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ embed_dims: int,
46
+ num_heads: int,
47
+ window_size: int = 8,
48
+ shift: bool = False,
49
+ extra_norm: bool = False,
50
+ ffn_ratio: float = 4.0,
51
+ drop_path: float = 0.0,
52
+ pad_small_map: bool = False,
53
+ with_cp: bool = False,
54
+ pretrained_window_size: int = 0,
55
+ ):
56
+ super().__init__()
57
+ self.with_cp = with_cp
58
+ self.extra_norm = extra_norm
59
+
60
+ self.attn = ShiftWindowMSA(
61
+ embed_dims=embed_dims,
62
+ num_heads=num_heads,
63
+ window_size=window_size,
64
+ shift_size=window_size // 2 if shift else 0,
65
+ drop_path=drop_path,
66
+ pad_small_map=pad_small_map,
67
+ pretrained_window_size=pretrained_window_size,
68
+ )
69
+ self.norm1 = nn.LayerNorm(embed_dims)
70
+
71
+ self.ffn = FFN(
72
+ embed_dims=embed_dims,
73
+ feedforward_channels=int(embed_dims * ffn_ratio),
74
+ num_fcs=2,
75
+ drop_path=drop_path,
76
+ act_layer=nn.GELU,
77
+ add_identity=False,
78
+ )
79
+ self.norm2 = nn.LayerNorm(embed_dims)
80
+
81
+ if self.extra_norm:
82
+ self.norm3 = nn.LayerNorm(embed_dims)
83
+
84
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
85
+ def _inner_forward(x):
86
+ # Post normalization
87
+ identity = x
88
+ x = self.attn(x, hw_shape)
89
+ x = self.norm1(x)
90
+ x = x + identity
91
+
92
+ identity = x
93
+ x = self.ffn(x)
94
+ x = self.norm2(x)
95
+ x = x + identity
96
+
97
+ if self.extra_norm:
98
+ x = self.norm3(x)
99
+ return x
100
+
101
+ if self.with_cp and x.requires_grad:
102
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
103
+ else:
104
+ x = _inner_forward(x)
105
+ return x
106
+
107
+
108
+ class SwinBlockV2Sequence(nn.Module):
109
+ """Sequence of Swin Transformer V2 blocks with optional downsample.
110
+
111
+ Args:
112
+ embed_dims (int): Number of input channels.
113
+ depth (int): Number of blocks.
114
+ num_heads (int): Number of attention heads.
115
+ window_size (int): Window size. Default: 8.
116
+ downsample (bool): Apply downsample. Default: False.
117
+ drop_paths (list or float): Drop path rates. Default: 0.0.
118
+ with_cp (bool): Gradient checkpointing. Default: False.
119
+ pad_small_map (bool): Pad small maps. Default: False.
120
+ extra_norm_every_n_blocks (int): Extra norm interval. Default: 0.
121
+ pretrained_window_size (int): Pretrained window size. Default: 0.
122
+ is_post_norm_downsample (bool): Post-norm in downsample. Default: True.
123
+ """
124
+
125
+ def __init__(
126
+ self,
127
+ embed_dims: int,
128
+ depth: int,
129
+ num_heads: int,
130
+ window_size: int = 8,
131
+ downsample: bool = False,
132
+ drop_paths: Union[Sequence[float], float] = 0.0,
133
+ with_cp: bool = False,
134
+ pad_small_map: bool = False,
135
+ extra_norm_every_n_blocks: int = 0,
136
+ pretrained_window_size: int = 0,
137
+ is_post_norm_downsample: bool = True,
138
+ ):
139
+ super().__init__()
140
+
141
+ if not isinstance(drop_paths, Sequence):
142
+ drop_paths = [drop_paths] * depth
143
+
144
+ if downsample:
145
+ self.out_channels = 2 * embed_dims
146
+ self.downsample = PatchMerging(
147
+ in_channels=embed_dims,
148
+ out_channels=self.out_channels,
149
+ is_post_norm=is_post_norm_downsample,
150
+ )
151
+ else:
152
+ self.out_channels = embed_dims
153
+ self.downsample = None
154
+
155
+ self.blocks = nn.ModuleList()
156
+ for i in range(depth):
157
+ extra_norm = (
158
+ extra_norm_every_n_blocks > 0
159
+ and (i + 1) % extra_norm_every_n_blocks == 0
160
+ )
161
+ block = SwinBlockV2(
162
+ embed_dims=self.out_channels,
163
+ num_heads=num_heads,
164
+ window_size=window_size,
165
+ shift=(i % 2 == 1),
166
+ extra_norm=extra_norm,
167
+ drop_path=drop_paths[i],
168
+ with_cp=with_cp,
169
+ pad_small_map=pad_small_map,
170
+ pretrained_window_size=pretrained_window_size,
171
+ )
172
+ self.blocks.append(block)
173
+
174
+ def forward(
175
+ self, x: torch.Tensor, in_shape: Tuple[int, int]
176
+ ) -> Tuple[torch.Tensor, Tuple[int, int]]:
177
+ if self.downsample is not None:
178
+ x, out_shape = self.downsample(x, in_shape)
179
+ else:
180
+ out_shape = in_shape
181
+
182
+ for block in self.blocks:
183
+ x = block(x, out_shape)
184
+
185
+ return x, out_shape
186
+
187
+
188
+ class SkySenseSwinV2PreTrainedModel(PreTrainedModel):
189
+ """Base class for SkySense Swin Transformer V2 models."""
190
+
191
+ config_class = SkySenseSwinV2Config
192
+ base_model_prefix = "skysense_swinv2"
193
+ supports_gradient_checkpointing = True
194
+
195
+ def _init_weights(self, module):
196
+ """Initialize weights."""
197
+ if isinstance(module, nn.Linear):
198
+ nn.init.trunc_normal_(module.weight, std=0.02)
199
+ if module.bias is not None:
200
+ nn.init.zeros_(module.bias)
201
+ elif isinstance(module, nn.LayerNorm):
202
+ nn.init.ones_(module.weight)
203
+ nn.init.zeros_(module.bias)
204
+ elif isinstance(module, nn.Conv2d):
205
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
206
+ if module.bias is not None:
207
+ nn.init.zeros_(module.bias)
208
+
209
+
210
+ class SkySenseSwinV2Model(SkySenseSwinV2PreTrainedModel):
211
+ """SkySense Swin Transformer V2 backbone.
212
+
213
+ A pure PyTorch + HuggingFace implementation of the Swin Transformer V2
214
+ used in SkySense for high-resolution optical remote sensing imagery.
215
+ """
216
+
217
+ def __init__(self, config: SkySenseSwinV2Config):
218
+ super().__init__(config)
219
+
220
+ self.num_layers = len(config.depths)
221
+ self.out_indices = config.out_indices
222
+
223
+ # Window sizes per stage
224
+ if isinstance(config.window_size, int):
225
+ window_sizes = [config.window_size] * self.num_layers
226
+ else:
227
+ window_sizes = list(config.window_size)
228
+
229
+ # Patch embedding
230
+ self.patch_embed = PatchEmbed(
231
+ in_channels=config.in_channels,
232
+ embed_dims=config.embed_dims,
233
+ kernel_size=config.patch_size,
234
+ stride=config.patch_size,
235
+ norm_layer=nn.LayerNorm,
236
+ input_size=config.img_size,
237
+ )
238
+
239
+ # Optional absolute position embedding
240
+ self.use_abs_pos_embed = config.use_abs_pos_embed
241
+ if self.use_abs_pos_embed:
242
+ patch_resolution = self.patch_embed.init_out_size
243
+ num_patches = patch_resolution[0] * patch_resolution[1]
244
+ self.absolute_pos_embed = nn.Parameter(
245
+ torch.zeros(1, num_patches, config.embed_dims)
246
+ )
247
+
248
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
249
+
250
+ # Stochastic depth decay (computed without tensors for meta-device compat)
251
+ total_depth = sum(config.depths)
252
+ if total_depth > 1:
253
+ dpr = [config.drop_path_rate * i / (total_depth - 1) for i in range(total_depth)]
254
+ else:
255
+ dpr = [0.0]
256
+
257
+ # Build stages
258
+ self.stages = nn.ModuleList()
259
+ embed_dims_list = [config.embed_dims]
260
+ for i, (depth, num_heads) in enumerate(
261
+ zip(config.depths, config.num_heads)
262
+ ):
263
+ stage = SwinBlockV2Sequence(
264
+ embed_dims=embed_dims_list[-1],
265
+ depth=depth,
266
+ num_heads=num_heads,
267
+ window_size=window_sizes[i],
268
+ downsample=(i > 0),
269
+ drop_paths=dpr[:depth],
270
+ with_cp=config.with_cp,
271
+ pad_small_map=config.pad_small_map,
272
+ extra_norm_every_n_blocks=config.extra_norm_every_n_blocks,
273
+ pretrained_window_size=config.pretrained_window_sizes[i],
274
+ is_post_norm_downsample=config.is_post_norm_downsample,
275
+ )
276
+ self.stages.append(stage)
277
+ dpr = dpr[depth:]
278
+ embed_dims_list.append(stage.out_channels)
279
+
280
+ # Output norms
281
+ for i in self.out_indices:
282
+ norm = nn.LayerNorm(embed_dims_list[i + 1])
283
+ self.add_module(f"norm{i}", norm)
284
+
285
+ self.post_init()
286
+
287
+ def _delete_reinit_params(self, state_dict, prefix, *args, **kwargs):
288
+ """Delete relative_position_index and relative_coords_table from state_dict."""
289
+ keys_to_delete = [
290
+ k for k in state_dict.keys()
291
+ if 'relative_position_index' in k or 'relative_coords_table' in k
292
+ ]
293
+ for k in keys_to_delete:
294
+ del state_dict[k]
295
+
296
+ def forward(
297
+ self,
298
+ pixel_values: torch.Tensor,
299
+ output_hidden_states: Optional[bool] = None,
300
+ return_dict: Optional[bool] = None,
301
+ ) -> Union[Tuple, BaseModelOutput]:
302
+ """
303
+ Args:
304
+ pixel_values: (B, C, H, W) input image tensor.
305
+ output_hidden_states: Whether to return all hidden states.
306
+ return_dict: Whether to return a BaseModelOutput.
307
+
308
+ Returns:
309
+ BaseModelOutput or tuple of feature maps.
310
+ """
311
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
312
+
313
+ x, hw_shape = self.patch_embed(pixel_values)
314
+
315
+ if self.use_abs_pos_embed:
316
+ x = x + self.absolute_pos_embed
317
+ x = self.drop_after_pos(x)
318
+
319
+ all_hidden_states = () if output_hidden_states else None
320
+ feature_maps = []
321
+
322
+ for i, stage in enumerate(self.stages):
323
+ x, hw_shape = stage(x, hw_shape)
324
+ if output_hidden_states:
325
+ all_hidden_states = all_hidden_states + (x,)
326
+ if i in self.out_indices:
327
+ norm_layer = getattr(self, f"norm{i}")
328
+ out = norm_layer(x)
329
+ out = out.view(
330
+ -1, *hw_shape, stage.out_channels
331
+ ).permute(0, 3, 1, 2).contiguous()
332
+ feature_maps.append(out)
333
+
334
+ if not return_dict:
335
+ return tuple(feature_maps)
336
+
337
+ return BaseModelOutput(
338
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
339
+ hidden_states=all_hidden_states,
340
+ )
skysense-swinv2-huge-rgb/modeling_skysense_vit.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Vision Transformer backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple, Union
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseViTConfig
17
+ from .modeling_utils import DropPath, FFN, PatchEmbed, to_2tuple
18
+
19
+
20
+ class TransformerEncoderLayer(nn.Module):
21
+ """Single encoder layer for the Vision Transformer.
22
+
23
+ Args:
24
+ embed_dims (int): Embedding dimension.
25
+ num_heads (int): Number of attention heads.
26
+ feedforward_channels (int): FFN hidden dimension.
27
+ drop_rate (float): Dropout rate. Default: 0.0.
28
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
29
+ drop_path_rate (float): Drop path rate. Default: 0.0.
30
+ num_fcs (int): Number of FC layers in FFN. Default: 2.
31
+ qkv_bias (bool): QKV bias. Default: True.
32
+ with_cp (bool): Gradient checkpointing. Default: False.
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ embed_dims: int,
38
+ num_heads: int,
39
+ feedforward_channels: int,
40
+ drop_rate: float = 0.0,
41
+ attn_drop_rate: float = 0.0,
42
+ drop_path_rate: float = 0.0,
43
+ num_fcs: int = 2,
44
+ qkv_bias: bool = True,
45
+ with_cp: bool = False,
46
+ ):
47
+ super().__init__()
48
+ self.with_cp = with_cp
49
+
50
+ self.norm1 = nn.LayerNorm(embed_dims)
51
+ self.attn = nn.MultiheadAttention(
52
+ embed_dim=embed_dims,
53
+ num_heads=num_heads,
54
+ dropout=attn_drop_rate,
55
+ bias=qkv_bias,
56
+ batch_first=True,
57
+ )
58
+ self.proj_drop = nn.Dropout(drop_rate)
59
+
60
+ self.norm2 = nn.LayerNorm(embed_dims)
61
+ self.ffn = FFN(
62
+ embed_dims=embed_dims,
63
+ feedforward_channels=feedforward_channels,
64
+ num_fcs=num_fcs,
65
+ ffn_drop=drop_rate,
66
+ drop_path=drop_path_rate,
67
+ act_layer=nn.GELU,
68
+ add_identity=True,
69
+ )
70
+
71
+ self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
72
+
73
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
74
+ def _inner_forward(x):
75
+ # Pre-norm attention with residual
76
+ residual = x
77
+ x_norm = self.norm1(x)
78
+ attn_out, _ = self.attn(x_norm, x_norm, x_norm)
79
+ attn_out = self.proj_drop(attn_out)
80
+ x = residual + self.drop_path(attn_out)
81
+
82
+ # Pre-norm FFN with residual (FFN handles its own residual)
83
+ x = self.ffn(self.norm2(x), identity=x)
84
+ return x
85
+
86
+ if self.with_cp and x.requires_grad:
87
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
88
+ else:
89
+ x = _inner_forward(x)
90
+ return x
91
+
92
+
93
+ class SkySenseViTPreTrainedModel(PreTrainedModel):
94
+ """Base class for SkySense Vision Transformer models."""
95
+
96
+ config_class = SkySenseViTConfig
97
+ base_model_prefix = "skysense_vit"
98
+ supports_gradient_checkpointing = True
99
+
100
+ def _init_weights(self, module):
101
+ """Initialize weights following jax_impl."""
102
+ if isinstance(module, nn.Linear):
103
+ nn.init.trunc_normal_(module.weight, std=0.02)
104
+ if module.bias is not None:
105
+ nn.init.zeros_(module.bias)
106
+ elif isinstance(module, (nn.LayerNorm, nn.GroupNorm)):
107
+ nn.init.ones_(module.weight)
108
+ nn.init.zeros_(module.bias)
109
+ elif isinstance(module, nn.Conv2d):
110
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
111
+ if module.bias is not None:
112
+ nn.init.zeros_(module.bias)
113
+
114
+
115
+ class SkySenseViTModel(SkySenseViTPreTrainedModel):
116
+ """SkySense Vision Transformer backbone.
117
+
118
+ A pure PyTorch + HuggingFace implementation of the ViT used in SkySense
119
+ for Sentinel-2 multispectral and Sentinel-1 SAR imagery.
120
+ """
121
+
122
+ def __init__(self, config: SkySenseViTConfig):
123
+ super().__init__(config)
124
+
125
+ img_size = to_2tuple(config.img_size)
126
+ self.img_size = img_size
127
+ self.patch_size = config.patch_size
128
+ self.with_cls_token = config.with_cls_token
129
+ self.output_cls_token = config.output_cls_token
130
+ self.interpolate_mode = 'bicubic'
131
+
132
+ # Patch embedding
133
+ self.patch_embed = PatchEmbed(
134
+ in_channels=config.in_channels,
135
+ embed_dims=config.embed_dims,
136
+ kernel_size=config.patch_size,
137
+ stride=config.patch_size,
138
+ norm_layer=nn.LayerNorm if config.patch_norm else None,
139
+ )
140
+
141
+ num_patches = (img_size[0] // config.patch_size) * (
142
+ img_size[1] // config.patch_size
143
+ )
144
+
145
+ self.cls_token = nn.Parameter(torch.zeros(1, 1, config.embed_dims))
146
+ self.pos_embed = nn.Parameter(
147
+ torch.zeros(1, num_patches + 1, config.embed_dims)
148
+ )
149
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
150
+
151
+ # Resolve out_indices
152
+ out_indices = list(config.out_indices)
153
+ resolved = []
154
+ for idx in out_indices:
155
+ if idx < 0:
156
+ idx = config.num_layers + idx
157
+ resolved.append(idx)
158
+ self.out_indices = resolved
159
+
160
+ # Stochastic depth (computed without tensors for meta-device compat)
161
+ num_layers = config.num_layers
162
+ if num_layers > 1:
163
+ dpr = [config.drop_path_rate * i / (num_layers - 1) for i in range(num_layers)]
164
+ else:
165
+ dpr = [0.0]
166
+
167
+ # Transformer encoder layers
168
+ self.layers = nn.ModuleList()
169
+ for i in range(config.num_layers):
170
+ self.layers.append(
171
+ TransformerEncoderLayer(
172
+ embed_dims=config.embed_dims,
173
+ num_heads=config.num_heads,
174
+ feedforward_channels=config.mlp_ratio * config.embed_dims,
175
+ attn_drop_rate=config.attn_drop_rate,
176
+ drop_rate=config.drop_rate,
177
+ drop_path_rate=dpr[i],
178
+ num_fcs=2,
179
+ qkv_bias=config.qkv_bias,
180
+ with_cp=config.with_cp,
181
+ )
182
+ )
183
+
184
+ # Final norm
185
+ self.final_norm = config.final_norm
186
+ if config.final_norm:
187
+ self.norm = nn.LayerNorm(config.embed_dims)
188
+
189
+ self.post_init()
190
+
191
+ @staticmethod
192
+ def resize_pos_embed(pos_embed, input_shape, pos_shape, mode='bicubic'):
193
+ """Resize position embeddings via interpolation.
194
+
195
+ Args:
196
+ pos_embed (torch.Tensor): Position embedding of shape (B, L, C),
197
+ where L = 1 (cls_token) + pos_h * pos_w.
198
+ input_shape (tuple[int, int]): Target spatial size (H, W).
199
+ pos_shape (tuple[int, int]): Original spatial size (pos_h, pos_w).
200
+ mode (str): Interpolation mode. Default: 'bicubic'.
201
+
202
+ Returns:
203
+ torch.Tensor: Resized position embedding of shape (B, 1 + H*W, C).
204
+ """
205
+ assert pos_embed.ndim == 3
206
+ pos_h, pos_w = pos_shape
207
+ cls_token_weight = pos_embed[:, 0:1]
208
+ pos_embed_weight = pos_embed[:, (-1 * pos_h * pos_w):]
209
+ pos_embed_weight = pos_embed_weight.reshape(
210
+ 1, pos_h, pos_w, pos_embed.shape[2]
211
+ ).permute(0, 3, 1, 2)
212
+ pos_embed_weight = F.interpolate(
213
+ pos_embed_weight,
214
+ size=input_shape,
215
+ align_corners=False,
216
+ mode=mode,
217
+ )
218
+ pos_embed_weight = torch.flatten(pos_embed_weight, 2).transpose(1, 2)
219
+ pos_embed = torch.cat((cls_token_weight, pos_embed_weight), dim=1)
220
+ return pos_embed
221
+
222
+ def _pos_embedding(self, patched_img, hw_shape, pos_embed):
223
+ """Apply position embedding with optional interpolation."""
224
+ x_len, pos_len = patched_img.shape[1], pos_embed.shape[1]
225
+ if x_len != pos_len:
226
+ pos_h = self.img_size[0] // self.patch_size
227
+ pos_w = self.img_size[1] // self.patch_size
228
+ pos_embed = self.resize_pos_embed(
229
+ pos_embed, hw_shape, (pos_h, pos_w), self.interpolate_mode
230
+ )
231
+ return self.drop_after_pos(patched_img + pos_embed)
232
+
233
+ def forward(
234
+ self,
235
+ pixel_values: torch.Tensor,
236
+ output_hidden_states: Optional[bool] = None,
237
+ return_dict: Optional[bool] = None,
238
+ ) -> Union[Tuple, BaseModelOutput]:
239
+ """
240
+ Args:
241
+ pixel_values: (B, C, H, W) input tensor.
242
+ output_hidden_states: Return all hidden states.
243
+ return_dict: Return BaseModelOutput.
244
+
245
+ Returns:
246
+ Feature maps or BaseModelOutput.
247
+ """
248
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
249
+ B = pixel_values.shape[0]
250
+
251
+ x, hw_shape = self.patch_embed(pixel_values)
252
+
253
+ # Prepend CLS token
254
+ cls_tokens = self.cls_token.expand(B, -1, -1)
255
+ x = torch.cat((cls_tokens, x), dim=1)
256
+ x = self._pos_embedding(x, hw_shape, self.pos_embed)
257
+
258
+ if not self.with_cls_token:
259
+ x = x[:, 1:]
260
+
261
+ all_hidden_states = () if output_hidden_states else None
262
+ feature_maps = []
263
+
264
+ for i, layer in enumerate(self.layers):
265
+ x = layer(x)
266
+
267
+ if i == len(self.layers) - 1 and self.final_norm:
268
+ x = self.norm(x)
269
+
270
+ if output_hidden_states:
271
+ all_hidden_states = all_hidden_states + (x,)
272
+
273
+ if i in self.out_indices:
274
+ if self.with_cls_token:
275
+ out = x[:, 1:]
276
+ else:
277
+ out = x
278
+ B_, _, C = out.shape
279
+ out = out.reshape(
280
+ B_, hw_shape[0], hw_shape[1], C
281
+ ).permute(0, 3, 1, 2).contiguous()
282
+ if self.output_cls_token:
283
+ out = [out, x[:, 0]]
284
+ feature_maps.append(out)
285
+
286
+ if not return_dict:
287
+ return tuple(feature_maps)
288
+
289
+ return BaseModelOutput(
290
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
291
+ hidden_states=all_hidden_states,
292
+ )
skysense-swinv2-huge-rgb/modeling_utils.py ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense: Pure PyTorch + HuggingFace Transformers implementation.
2
+
3
+ Shared utility modules used across SkySense model implementations.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+
13
+
14
+ def to_2tuple(x):
15
+ """Convert to a 2-tuple."""
16
+ if isinstance(x, (list, tuple)):
17
+ return tuple(x)
18
+ return (x, x)
19
+
20
+
21
+ class DropPath(nn.Module):
22
+ """Drop paths (stochastic depth) per sample.
23
+
24
+ Args:
25
+ drop_prob (float): Probability of dropping a path. Default: 0.0.
26
+ """
27
+
28
+ def __init__(self, drop_prob: float = 0.0):
29
+ super().__init__()
30
+ self.drop_prob = drop_prob
31
+
32
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
33
+ if self.drop_prob == 0.0 or not self.training:
34
+ return x
35
+ keep_prob = 1 - self.drop_prob
36
+ shape = (x.shape[0],) + (1,) * (x.ndim - 1)
37
+ random_tensor = torch.rand(shape, dtype=x.dtype, device=x.device)
38
+ random_tensor = torch.floor(random_tensor + keep_prob)
39
+ output = x / keep_prob * random_tensor
40
+ return output
41
+
42
+
43
+ class PatchEmbed(nn.Module):
44
+ """Image to Patch Embedding using Conv2d.
45
+
46
+ Args:
47
+ in_channels (int): Number of input channels. Default: 3.
48
+ embed_dims (int): Embedding dimension. Default: 96.
49
+ kernel_size (int): Kernel size of the projection. Default: 4.
50
+ stride (int): Stride of the projection. Default: 4.
51
+ padding (int): Padding of the projection. Default: 0.
52
+ norm_layer (nn.Module or None): Normalization layer. Default: nn.LayerNorm.
53
+ input_size (int or tuple or None): Input resolution for calculating output size.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ in_channels: int = 3,
59
+ embed_dims: int = 96,
60
+ kernel_size: int = 4,
61
+ stride: int = 4,
62
+ padding: int = 0,
63
+ norm_layer: Optional[type] = nn.LayerNorm,
64
+ input_size: Optional[int] = None,
65
+ ):
66
+ super().__init__()
67
+ self.projection = nn.Conv2d(
68
+ in_channels, embed_dims,
69
+ kernel_size=kernel_size, stride=stride, padding=padding,
70
+ )
71
+ self.norm = norm_layer(embed_dims) if norm_layer else nn.Identity()
72
+
73
+ # Compute init output size if input_size is given
74
+ if input_size is not None:
75
+ input_size = to_2tuple(input_size)
76
+ self.init_out_size = (
77
+ (input_size[0] - kernel_size + 2 * padding) // stride + 1,
78
+ (input_size[1] - kernel_size + 2 * padding) // stride + 1,
79
+ )
80
+ else:
81
+ self.init_out_size = None
82
+
83
+ def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, Tuple[int, int]]:
84
+ x = self.projection(x) # (B, C, H, W)
85
+ out_size = (x.shape[2], x.shape[3])
86
+ x = x.flatten(2).transpose(1, 2) # (B, H*W, C)
87
+ x = self.norm(x)
88
+ return x, out_size
89
+
90
+
91
+ class FFN(nn.Module):
92
+ """Feed-Forward Network.
93
+
94
+ Args:
95
+ embed_dims (int): Input dimension.
96
+ feedforward_channels (int): Hidden dimension.
97
+ num_fcs (int): Number of FC layers. Default: 2.
98
+ ffn_drop (float): Dropout rate. Default: 0.0.
99
+ drop_path (float): Drop path rate. Default: 0.0.
100
+ act_layer (nn.Module): Activation layer class. Default: nn.GELU.
101
+ add_identity (bool): Whether to add identity connection. Default: True.
102
+ """
103
+
104
+ def __init__(
105
+ self,
106
+ embed_dims: int,
107
+ feedforward_channels: int,
108
+ num_fcs: int = 2,
109
+ ffn_drop: float = 0.0,
110
+ drop_path: float = 0.0,
111
+ act_layer: type = nn.GELU,
112
+ add_identity: bool = True,
113
+ ):
114
+ super().__init__()
115
+ assert num_fcs >= 2, f"num_fcs must be >= 2, got {num_fcs}"
116
+ self.embed_dims = embed_dims
117
+ self.feedforward_channels = feedforward_channels
118
+ self.add_identity = add_identity
119
+
120
+ layers = []
121
+ in_channels = embed_dims
122
+ for i in range(num_fcs - 1):
123
+ layers.append(nn.Linear(in_channels, feedforward_channels))
124
+ layers.append(act_layer())
125
+ layers.append(nn.Dropout(ffn_drop))
126
+ in_channels = feedforward_channels
127
+ layers.append(nn.Linear(feedforward_channels, embed_dims))
128
+ layers.append(nn.Dropout(ffn_drop))
129
+ self.layers = nn.Sequential(*layers)
130
+
131
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
132
+
133
+ def forward(self, x: torch.Tensor, identity: Optional[torch.Tensor] = None) -> torch.Tensor:
134
+ out = self.layers(x)
135
+ out = self.drop_path(out)
136
+ if self.add_identity:
137
+ if identity is None:
138
+ identity = x
139
+ out = out + identity
140
+ return out
141
+
142
+
143
+ class WindowMSAV2(nn.Module):
144
+ """Window-based Multi-head Self-Attention for Swin Transformer V2.
145
+
146
+ Uses cosine attention and log-spaced continuous position bias (log-CPB).
147
+
148
+ Args:
149
+ embed_dims (int): Number of input channels.
150
+ num_heads (int): Number of attention heads.
151
+ window_size (tuple[int]): Window size (Wh, Ww).
152
+ pretrained_window_size (tuple[int]): Pretrained window size for CPB. Default: (0, 0).
153
+ qkv_bias (bool): If True, add learnable bias to q, k, v. Default: True.
154
+ attn_drop (float): Attention dropout rate. Default: 0.0.
155
+ proj_drop (float): Output projection dropout rate. Default: 0.0.
156
+ """
157
+
158
+ def __init__(
159
+ self,
160
+ embed_dims: int,
161
+ num_heads: int,
162
+ window_size: Tuple[int, int],
163
+ pretrained_window_size: Tuple[int, int] = (0, 0),
164
+ qkv_bias: bool = True,
165
+ attn_drop: float = 0.0,
166
+ proj_drop: float = 0.0,
167
+ ):
168
+ super().__init__()
169
+ self.embed_dims = embed_dims
170
+ self.num_heads = num_heads
171
+ self.window_size = window_size
172
+ self.pretrained_window_size = pretrained_window_size
173
+
174
+ self.logit_scale = nn.Parameter(
175
+ torch.log(10 * torch.ones((num_heads, 1, 1))))
176
+
177
+ # MLP for continuous relative position bias (log-CPB)
178
+ self.cpb_mlp = nn.Sequential(
179
+ nn.Linear(2, 512, bias=True),
180
+ nn.ReLU(inplace=True),
181
+ nn.Linear(512, num_heads, bias=False),
182
+ )
183
+
184
+ # Build relative coords table
185
+ self._build_relative_coords_table()
186
+ # Build relative position index
187
+ self._build_relative_position_index()
188
+
189
+ self.qkv = nn.Linear(embed_dims, embed_dims * 3, bias=False)
190
+ if qkv_bias:
191
+ self.q_bias = nn.Parameter(torch.zeros(embed_dims))
192
+ self.v_bias = nn.Parameter(torch.zeros(embed_dims))
193
+ else:
194
+ self.q_bias = None
195
+ self.v_bias = None
196
+
197
+ self.attn_drop = nn.Dropout(attn_drop)
198
+ self.proj = nn.Linear(embed_dims, embed_dims)
199
+ self.proj_drop = nn.Dropout(proj_drop)
200
+ self.softmax = nn.Softmax(dim=-1)
201
+
202
+ def _build_relative_coords_table(self):
203
+ """Build the relative coordinates table for log-CPB."""
204
+ Wh, Ww = self.window_size
205
+ # Table of relative coordinates
206
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32)
207
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32)
208
+ coords_table = torch.stack(
209
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
210
+ ).flatten(1).transpose(0, 1).unsqueeze(0) # (1, (2Wh-1)*(2Ww-1), 2)
211
+
212
+ # Normalize to [-1, 1] and apply log-scale
213
+ if self.pretrained_window_size[0] > 0:
214
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
215
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
216
+ else:
217
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
218
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
219
+ coords_table *= 8 # normalize to -8, 8
220
+ coords_table = (
221
+ torch.sign(coords_table)
222
+ * torch.log2(torch.abs(coords_table) + 1.0)
223
+ / math.log2(8)
224
+ )
225
+ self.register_buffer("relative_coords_table", coords_table)
226
+
227
+ def _build_relative_position_index(self):
228
+ """Build the pairwise relative position index for each window token."""
229
+ Wh, Ww = self.window_size
230
+ coords_h = torch.arange(Wh)
231
+ coords_w = torch.arange(Ww)
232
+ coords = torch.stack(torch.meshgrid(coords_h, coords_w, indexing='ij'))
233
+ coords_flatten = coords.view(2, -1)
234
+
235
+ relative_coords = (
236
+ coords_flatten[:, :, None] - coords_flatten[:, None, :]
237
+ ) # (2, Wh*Ww, Wh*Ww)
238
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous()
239
+ relative_coords[:, :, 0] += Wh - 1
240
+ relative_coords[:, :, 1] += Ww - 1
241
+ relative_coords[:, :, 0] *= 2 * Ww - 1
242
+ relative_position_index = relative_coords.sum(-1) # (Wh*Ww, Wh*Ww)
243
+ self.register_buffer("relative_position_index", relative_position_index)
244
+
245
+ def _compute_position_bias(self, N):
246
+ """Compute relative position bias, supporting dynamic window sizes.
247
+
248
+ The log-CPB (Continuous Position Bias) MLP can generalize to any window
249
+ size by computing bias from normalized relative coordinates.
250
+ """
251
+ init_N = self.window_size[0] * self.window_size[1]
252
+ if N == init_N:
253
+ # Use pre-built tables
254
+ relative_position_bias_table = self.cpb_mlp(
255
+ self.relative_coords_table
256
+ ).view(-1, self.num_heads)
257
+ relative_position_bias = relative_position_bias_table[
258
+ self.relative_position_index.view(-1)
259
+ ].view(N, N, -1)
260
+ else:
261
+ # Dynamic: compute for actual window size on-the-fly
262
+ Wh = Ww = int(math.sqrt(N))
263
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32, device=self.logit_scale.device)
264
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32, device=self.logit_scale.device)
265
+ coords_table = torch.stack(
266
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
267
+ ).flatten(1).transpose(0, 1).unsqueeze(0)
268
+ if self.pretrained_window_size[0] > 0:
269
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
270
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
271
+ else:
272
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
273
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
274
+ coords_table *= 8
275
+ coords_table = (
276
+ torch.sign(coords_table)
277
+ * torch.log2(torch.abs(coords_table) + 1.0)
278
+ / math.log2(8)
279
+ )
280
+ # Build position index for actual window size
281
+ ch = torch.arange(Wh, device=self.logit_scale.device)
282
+ cw = torch.arange(Ww, device=self.logit_scale.device)
283
+ coords = torch.stack(torch.meshgrid(ch, cw, indexing='ij'))
284
+ coords_flat = coords.view(2, -1)
285
+ rel = coords_flat[:, :, None] - coords_flat[:, None, :]
286
+ rel = rel.permute(1, 2, 0).contiguous()
287
+ rel[:, :, 0] += Wh - 1
288
+ rel[:, :, 1] += Ww - 1
289
+ rel[:, :, 0] *= 2 * Ww - 1
290
+ pos_index = rel.sum(-1)
291
+
292
+ bias_table = self.cpb_mlp(coords_table).view(-1, self.num_heads)
293
+ relative_position_bias = bias_table[
294
+ pos_index.view(-1)
295
+ ].view(N, N, -1)
296
+
297
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()
298
+ relative_position_bias = 16 * torch.sigmoid(relative_position_bias)
299
+ return relative_position_bias
300
+
301
+ def forward(self, x: torch.Tensor, mask: Optional[torch.Tensor] = None) -> torch.Tensor:
302
+ """
303
+ Args:
304
+ x: (num_windows*B, N, C) where N = Wh*Ww
305
+ mask: (num_windows, N, N) or None
306
+ """
307
+ B_, N, C = x.shape
308
+
309
+ # Compute QKV with bias
310
+ if self.q_bias is not None:
311
+ qkv_bias = torch.cat(
312
+ (self.q_bias,
313
+ torch.zeros_like(self.v_bias, requires_grad=False),
314
+ self.v_bias))
315
+ qkv = F.linear(x, self.qkv.weight, qkv_bias)
316
+ else:
317
+ qkv = self.qkv(x)
318
+
319
+ qkv = qkv.reshape(B_, N, 3, self.num_heads, C // self.num_heads)
320
+ qkv = qkv.permute(2, 0, 3, 1, 4)
321
+ q, k, v = qkv.unbind(0)
322
+
323
+ # Cosine attention
324
+ attn = F.normalize(q, dim=-1) @ F.normalize(k, dim=-1).transpose(-2, -1)
325
+ logit_scale = torch.clamp(
326
+ self.logit_scale, max=math.log(1.0 / 0.01)
327
+ ).exp()
328
+ attn = attn * logit_scale
329
+
330
+ # Log-CPB relative position bias (supports dynamic window sizes)
331
+ relative_position_bias = self._compute_position_bias(N)
332
+ attn = attn + relative_position_bias.unsqueeze(0)
333
+
334
+ if mask is not None:
335
+ nW = mask.shape[0]
336
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N)
337
+ attn = attn + mask.unsqueeze(1).unsqueeze(0)
338
+ attn = attn.view(-1, self.num_heads, N, N)
339
+
340
+ attn = self.softmax(attn)
341
+ attn = self.attn_drop(attn)
342
+
343
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
344
+ x = self.proj(x)
345
+ x = self.proj_drop(x)
346
+ return x
347
+
348
+
349
+ class ShiftWindowMSA(nn.Module):
350
+ """Shifted Window Multi-head Self-Attention.
351
+
352
+ Args:
353
+ embed_dims (int): Number of input channels.
354
+ num_heads (int): Number of attention heads.
355
+ window_size (int): Window size.
356
+ shift_size (int): Shift size for SW-MSA. Default: 0.
357
+ attn_drop (float): Attention dropout rate. Default: 0.0.
358
+ proj_drop (float): Projection dropout rate. Default: 0.0.
359
+ drop_path (float): Drop path rate. Default: 0.0.
360
+ pad_small_map (bool): Pad small feature maps to window size. Default: False.
361
+ pretrained_window_size (int): Pretrained window size. Default: 0.
362
+ """
363
+
364
+ def __init__(
365
+ self,
366
+ embed_dims: int,
367
+ num_heads: int,
368
+ window_size: int,
369
+ shift_size: int = 0,
370
+ attn_drop: float = 0.0,
371
+ proj_drop: float = 0.0,
372
+ drop_path: float = 0.0,
373
+ pad_small_map: bool = False,
374
+ pretrained_window_size: int = 0,
375
+ ):
376
+ super().__init__()
377
+ self.window_size = window_size
378
+ self.shift_size = shift_size
379
+ self.pad_small_map = pad_small_map
380
+
381
+ self.w_msa = WindowMSAV2(
382
+ embed_dims=embed_dims,
383
+ num_heads=num_heads,
384
+ window_size=to_2tuple(window_size),
385
+ pretrained_window_size=to_2tuple(pretrained_window_size),
386
+ attn_drop=attn_drop,
387
+ proj_drop=proj_drop,
388
+ )
389
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
390
+
391
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
392
+ B, L, C = x.shape
393
+ H, W = hw_shape
394
+ assert L == H * W, f"Input length {L} != H*W ({H}*{W})"
395
+
396
+ x = x.view(B, H, W, C)
397
+
398
+ window_size = self.window_size
399
+ shift_size = self.shift_size
400
+
401
+ # Pad or shrink window
402
+ if self.pad_small_map:
403
+ pad_r = (window_size - W % window_size) % window_size
404
+ pad_b = (window_size - H % window_size) % window_size
405
+ x = F.pad(x, (0, 0, 0, pad_r, 0, pad_b))
406
+ _, Hp, Wp, _ = x.shape
407
+ else:
408
+ Hp, Wp = H, W
409
+ if window_size > Hp:
410
+ window_size = Hp
411
+ shift_size = 0
412
+ if window_size > Wp:
413
+ window_size = Wp
414
+ shift_size = 0
415
+
416
+ # Compute attention mask for SW-MSA
417
+ attn_mask = self._compute_attn_mask(Hp, Wp, window_size, shift_size, x.device)
418
+
419
+ # Cyclic shift
420
+ if shift_size > 0:
421
+ x = torch.roll(x, shifts=(-shift_size, -shift_size), dims=(1, 2))
422
+
423
+ # Partition windows
424
+ x_windows = self._window_partition(x, window_size)
425
+ # (num_windows*B, window_size*window_size, C)
426
+
427
+ # W-MSA/SW-MSA
428
+ attn_windows = self.w_msa(x_windows, mask=attn_mask)
429
+
430
+ # Merge windows
431
+ x = self._window_reverse(attn_windows, window_size, Hp, Wp)
432
+
433
+ # Reverse cyclic shift
434
+ if shift_size > 0:
435
+ x = torch.roll(x, shifts=(shift_size, shift_size), dims=(1, 2))
436
+
437
+ if self.pad_small_map and (pad_r > 0 or pad_b > 0):
438
+ x = x[:, :H, :W, :].contiguous()
439
+
440
+ x = x.view(B, H * W, C)
441
+ x = self.drop_path(x)
442
+ return x
443
+
444
+ @staticmethod
445
+ def _window_partition(x: torch.Tensor, window_size: int) -> torch.Tensor:
446
+ """Partition into non-overlapping windows."""
447
+ B, H, W, C = x.shape
448
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
449
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous()
450
+ windows = windows.view(-1, window_size * window_size, C)
451
+ return windows
452
+
453
+ @staticmethod
454
+ def _window_reverse(windows: torch.Tensor, window_size: int, H: int, W: int) -> torch.Tensor:
455
+ """Reverse window partition."""
456
+ B_nW = windows.shape[0]
457
+ nH = H // window_size
458
+ nW = W // window_size
459
+ B = B_nW // (nH * nW)
460
+ x = windows.view(B, nH, nW, window_size, window_size, -1)
461
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous()
462
+ x = x.view(B, H, W, -1)
463
+ return x
464
+
465
+ @staticmethod
466
+ def _compute_attn_mask(H, W, window_size, shift_size, device):
467
+ """Compute attention mask for shifted window attention."""
468
+ if shift_size <= 0:
469
+ return None
470
+ img_mask = torch.zeros((1, H, W, 1), device=device)
471
+ h_slices = (
472
+ slice(0, -window_size),
473
+ slice(-window_size, -shift_size),
474
+ slice(-shift_size, None),
475
+ )
476
+ w_slices = (
477
+ slice(0, -window_size),
478
+ slice(-window_size, -shift_size),
479
+ slice(-shift_size, None),
480
+ )
481
+ cnt = 0
482
+ for h in h_slices:
483
+ for w in w_slices:
484
+ img_mask[:, h, w, :] = cnt
485
+ cnt += 1
486
+
487
+ # Partition mask
488
+ mask_windows = img_mask.view(
489
+ 1, H // window_size, window_size, W // window_size, window_size, 1
490
+ )
491
+ mask_windows = mask_windows.permute(0, 1, 3, 2, 4, 5).contiguous()
492
+ mask_windows = mask_windows.view(-1, window_size * window_size)
493
+
494
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
495
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, -100.0)
496
+ attn_mask = attn_mask.masked_fill(attn_mask == 0, 0.0)
497
+ return attn_mask
498
+
499
+
500
+ class PatchMerging(nn.Module):
501
+ """Patch Merging Layer for downsampling (2x).
502
+
503
+ Args:
504
+ in_channels (int): Input channels.
505
+ out_channels (int): Output channels.
506
+ norm_layer (type): Normalization layer. Default: nn.LayerNorm.
507
+ is_post_norm (bool): Apply norm after linear. Default: True.
508
+ """
509
+
510
+ def __init__(
511
+ self,
512
+ in_channels: int,
513
+ out_channels: int,
514
+ norm_layer: type = nn.LayerNorm,
515
+ is_post_norm: bool = True,
516
+ ):
517
+ super().__init__()
518
+ self.in_channels = in_channels
519
+ self.out_channels = out_channels
520
+ self.is_post_norm = is_post_norm
521
+ self.reduction = nn.Linear(4 * in_channels, out_channels, bias=False)
522
+ if is_post_norm:
523
+ self.norm = norm_layer(out_channels)
524
+ else:
525
+ self.norm = norm_layer(4 * in_channels)
526
+
527
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> Tuple[torch.Tensor, Tuple[int, int]]:
528
+ B, L, C = x.shape
529
+ H, W = hw_shape
530
+ assert L == H * W
531
+
532
+ x = x.view(B, H, W, C)
533
+
534
+ # Pad if needed
535
+ pad_h = H % 2
536
+ pad_w = W % 2
537
+ if pad_h or pad_w:
538
+ x = F.pad(x, (0, 0, 0, pad_w, 0, pad_h))
539
+
540
+ x0 = x[:, 0::2, 0::2, :]
541
+ x1 = x[:, 1::2, 0::2, :]
542
+ x2 = x[:, 0::2, 1::2, :]
543
+ x3 = x[:, 1::2, 1::2, :]
544
+ x = torch.cat([x0, x1, x2, x3], dim=-1)
545
+
546
+ out_h = (H + pad_h) // 2
547
+ out_w = (W + pad_w) // 2
548
+ x = x.view(B, out_h * out_w, 4 * C)
549
+
550
+ if self.is_post_norm:
551
+ x = self.reduction(x)
552
+ x = self.norm(x)
553
+ else:
554
+ x = self.norm(x)
555
+ x = self.reduction(x)
556
+
557
+ return x, (out_h, out_w)
skysense-swinv2-huge-rgb/pipeline_skysense.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Custom HuggingFace pipeline for SkySense feature extraction."""
2
+
3
+ from typing import Any, Dict, Optional, Union
4
+
5
+ import numpy as np
6
+ import torch
7
+ from transformers import Pipeline
8
+
9
+
10
+ class SkySenseFeatureExtractionPipeline(Pipeline):
11
+ """Pipeline for SkySense backbone feature extraction.
12
+
13
+ Accepts remote-sensing tensors with arbitrary channel counts
14
+ (e.g. 3-band RGB, 10-band Sentinel-2, 2-band Sentinel-1).
15
+ """
16
+
17
+ def _sanitize_parameters(
18
+ self,
19
+ output_hidden_states=None,
20
+ **kwargs,
21
+ ):
22
+ preprocess_params = {}
23
+ forward_params = {}
24
+ postprocess_params = {}
25
+
26
+ if output_hidden_states is not None:
27
+ forward_params["output_hidden_states"] = output_hidden_states
28
+
29
+ return preprocess_params, forward_params, postprocess_params
30
+
31
+ def preprocess(self, pixel_values: Any, **kwargs) -> Dict[str, torch.Tensor]:
32
+ if isinstance(pixel_values, dict):
33
+ pixel_values = pixel_values.get("pixel_values", pixel_values)
34
+
35
+ if isinstance(pixel_values, np.ndarray):
36
+ pixel_values = torch.from_numpy(pixel_values).float()
37
+ elif isinstance(pixel_values, torch.Tensor):
38
+ pixel_values = pixel_values.float()
39
+ else:
40
+ raise TypeError(
41
+ f"Expected torch.Tensor or numpy.ndarray, got {type(pixel_values)}"
42
+ )
43
+
44
+ if pixel_values.ndim == 3:
45
+ pixel_values = pixel_values.unsqueeze(0)
46
+
47
+ return {"pixel_values": pixel_values}
48
+
49
+ def _forward(self, model_inputs: Dict[str, torch.Tensor], **kwargs) -> Dict[str, Any]:
50
+ with torch.no_grad():
51
+ outputs = self.model(
52
+ pixel_values=model_inputs["pixel_values"],
53
+ output_hidden_states=kwargs.get("output_hidden_states", False),
54
+ return_dict=True,
55
+ )
56
+ return {"outputs": outputs}
57
+
58
+ def postprocess(
59
+ self,
60
+ model_outputs: Dict[str, Any],
61
+ **kwargs,
62
+ ) -> Dict[str, Any]:
63
+ outputs = model_outputs["outputs"]
64
+ result: Dict[str, Union[torch.Tensor, tuple]] = {
65
+ "last_hidden_state": outputs.last_hidden_state,
66
+ }
67
+ if getattr(outputs, "hidden_states", None) is not None:
68
+ result["hidden_states"] = outputs.hidden_states
69
+ return result
skysense-vit-large-s1/config.json ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "return_dict": true,
3
+ "output_hidden_states": false,
4
+ "dtype": "float32",
5
+ "chunk_size_feed_forward": 0,
6
+ "is_encoder_decoder": false,
7
+ "architectures": [
8
+ "SkySenseViTModel"
9
+ ],
10
+ "id2label": {
11
+ "0": "LABEL_0",
12
+ "1": "LABEL_1"
13
+ },
14
+ "label2id": {
15
+ "LABEL_0": 0,
16
+ "LABEL_1": 1
17
+ },
18
+ "problem_type": null,
19
+ "_name_or_path": "",
20
+ "transformers_version": "5.0.0",
21
+ "img_size": 64,
22
+ "patch_size": 4,
23
+ "in_channels": 2,
24
+ "embed_dims": 1024,
25
+ "num_layers": 24,
26
+ "num_heads": 16,
27
+ "mlp_ratio": 4,
28
+ "out_indices": [
29
+ -1
30
+ ],
31
+ "qkv_bias": true,
32
+ "drop_rate": 0.0,
33
+ "attn_drop_rate": 0.0,
34
+ "drop_path_rate": 0.3,
35
+ "with_cls_token": true,
36
+ "output_cls_token": false,
37
+ "patch_norm": false,
38
+ "final_norm": false,
39
+ "with_cp": false,
40
+ "model_type": "skysense_vit",
41
+ "output_attentions": false,
42
+ "auto_map": {
43
+ "AutoConfig": "configuration_skysense.SkySenseViTConfig",
44
+ "AutoModel": "modeling_skysense_vit.SkySenseViTModel"
45
+ },
46
+ "custom_pipelines": {
47
+ "skysense-feature-extraction": {
48
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
49
+ "pt": [
50
+ "AutoModel"
51
+ ]
52
+ },
53
+ "image-feature-extraction": {
54
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
55
+ "pt": [
56
+ "AutoModel"
57
+ ]
58
+ }
59
+ }
60
+ }
skysense-vit-large-s1/configuration_skysense.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration classes for SkySense models."""
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class SkySenseSwinV2Config(PretrainedConfig):
7
+ """Configuration class for SkySense Swin Transformer V2 backbone.
8
+
9
+ This model handles high-resolution optical imagery (RGB/RGBNIR).
10
+
11
+ Args:
12
+ arch (str): Architecture variant. One of 'tiny', 'small', 'base',
13
+ 'large', 'huge', 'giant'. Default: 'huge'.
14
+ img_size (int): Input image size. Default: 224.
15
+ patch_size (int): Patch size. Default: 4.
16
+ in_channels (int): Number of input channels. Default: 3.
17
+ window_size (int or list): Window size for each stage. Default: 8.
18
+ drop_rate (float): Dropout rate after embedding. Default: 0.0.
19
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1.
20
+ out_indices (list): Output indices from stages. Default: [3].
21
+ use_abs_pos_embed (bool): Use absolute position embedding. Default: False.
22
+ with_cp (bool): Use gradient checkpointing. Default: False.
23
+ pad_small_map (bool): Pad small maps to window size. Default: False.
24
+ pretrained_window_sizes (list): Pretrained window sizes. Default: [0, 0, 0, 0].
25
+ is_post_norm_downsample (bool): Use post-norm in downsample. Default: True.
26
+ """
27
+
28
+ model_type = "skysense_swinv2"
29
+
30
+ arch_zoo = {
31
+ 'tiny': {'embed_dims': 96, 'depths': [2, 2, 6, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
32
+ 'small': {'embed_dims': 96, 'depths': [2, 2, 18, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
33
+ 'base': {'embed_dims': 128, 'depths': [2, 2, 18, 2], 'num_heads': [4, 8, 16, 32], 'extra_norm_every_n_blocks': 0},
34
+ 'large': {'embed_dims': 192, 'depths': [2, 2, 18, 2], 'num_heads': [6, 12, 24, 48], 'extra_norm_every_n_blocks': 0},
35
+ 'huge': {'embed_dims': 352, 'depths': [2, 2, 18, 2], 'num_heads': [8, 16, 32, 64], 'extra_norm_every_n_blocks': 6},
36
+ 'giant': {'embed_dims': 512, 'depths': [2, 2, 42, 4], 'num_heads': [16, 32, 64, 128], 'extra_norm_every_n_blocks': 6},
37
+ }
38
+
39
+ def __init__(
40
+ self,
41
+ arch="huge",
42
+ img_size=224,
43
+ patch_size=4,
44
+ in_channels=3,
45
+ window_size=8,
46
+ drop_rate=0.0,
47
+ drop_path_rate=0.1,
48
+ out_indices=(3,),
49
+ use_abs_pos_embed=False,
50
+ with_cp=False,
51
+ pad_small_map=False,
52
+ pretrained_window_sizes=(0, 0, 0, 0),
53
+ is_post_norm_downsample=True,
54
+ **kwargs,
55
+ ):
56
+ super().__init__(**kwargs)
57
+
58
+ if isinstance(arch, str):
59
+ arch = arch.lower()
60
+ if arch not in self.arch_zoo:
61
+ raise ValueError(f"Unknown arch '{arch}'. Choose from {list(self.arch_zoo.keys())}")
62
+ arch_settings = self.arch_zoo[arch]
63
+ else:
64
+ arch_settings = arch
65
+
66
+ self.arch = arch
67
+ self.embed_dims = arch_settings['embed_dims']
68
+ self.depths = arch_settings['depths']
69
+ self.num_heads = arch_settings['num_heads']
70
+ self.extra_norm_every_n_blocks = arch_settings['extra_norm_every_n_blocks']
71
+
72
+ self.img_size = img_size
73
+ self.patch_size = patch_size
74
+ self.in_channels = in_channels
75
+ self.window_size = window_size
76
+ self.drop_rate = drop_rate
77
+ self.drop_path_rate = drop_path_rate
78
+ self.out_indices = list(out_indices)
79
+ self.use_abs_pos_embed = use_abs_pos_embed
80
+ self.with_cp = with_cp
81
+ self.pad_small_map = pad_small_map
82
+ self.pretrained_window_sizes = list(pretrained_window_sizes)
83
+ self.is_post_norm_downsample = is_post_norm_downsample
84
+
85
+
86
+ class SkySenseViTConfig(PretrainedConfig):
87
+ """Configuration class for SkySense Vision Transformer backbone.
88
+
89
+ This model handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
90
+
91
+ Args:
92
+ img_size (int): Input image size. Default: 64.
93
+ patch_size (int): Patch size. Default: 4.
94
+ in_channels (int): Number of input channels.
95
+ 10 for Sentinel-2, 2 for Sentinel-1. Default: 10.
96
+ embed_dims (int): Embedding dimension. Default: 1024.
97
+ num_layers (int): Number of transformer layers. Default: 24.
98
+ num_heads (int): Number of attention heads. Default: 16.
99
+ mlp_ratio (int): MLP hidden dim ratio. Default: 4.
100
+ out_indices (list): Output indices. Default: [-1].
101
+ qkv_bias (bool): QKV bias. Default: True.
102
+ drop_rate (float): Dropout rate. Default: 0.0.
103
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
104
+ drop_path_rate (float): Stochastic depth rate. Default: 0.3.
105
+ with_cls_token (bool): Use CLS token. Default: True.
106
+ output_cls_token (bool): Output CLS token. Default: False.
107
+ patch_norm (bool): Norm in patch embed. Default: False.
108
+ final_norm (bool): Final layer norm. Default: False.
109
+ with_cp (bool): Use gradient checkpointing. Default: False.
110
+ """
111
+
112
+ model_type = "skysense_vit"
113
+
114
+ def __init__(
115
+ self,
116
+ img_size=64,
117
+ patch_size=4,
118
+ in_channels=10,
119
+ embed_dims=1024,
120
+ num_layers=24,
121
+ num_heads=16,
122
+ mlp_ratio=4,
123
+ out_indices=(-1,),
124
+ qkv_bias=True,
125
+ drop_rate=0.0,
126
+ attn_drop_rate=0.0,
127
+ drop_path_rate=0.3,
128
+ with_cls_token=True,
129
+ output_cls_token=False,
130
+ patch_norm=False,
131
+ final_norm=False,
132
+ with_cp=False,
133
+ **kwargs,
134
+ ):
135
+ super().__init__(**kwargs)
136
+ self.img_size = img_size
137
+ self.patch_size = patch_size
138
+ self.in_channels = in_channels
139
+ self.embed_dims = embed_dims
140
+ self.num_layers = num_layers
141
+ self.num_heads = num_heads
142
+ self.mlp_ratio = mlp_ratio
143
+ self.out_indices = list(out_indices)
144
+ self.qkv_bias = qkv_bias
145
+ self.drop_rate = drop_rate
146
+ self.attn_drop_rate = attn_drop_rate
147
+ self.drop_path_rate = drop_path_rate
148
+ self.with_cls_token = with_cls_token
149
+ self.output_cls_token = output_cls_token
150
+ self.patch_norm = patch_norm
151
+ self.final_norm = final_norm
152
+ self.with_cp = with_cp
skysense-vit-large-s1/conversion_manifest.json ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_checkpoint": "/exstorage/czy/models/raw/skysense_model_backbone_s1.pth",
3
+ "modality": "s1",
4
+ "model_class": "SkySenseViTModel",
5
+ "num_tensors": 292,
6
+ "missing_keys": [],
7
+ "unexpected_keys": [],
8
+ "tensor_names": [
9
+ "cls_token",
10
+ "layers.0.attn.in_proj_bias",
11
+ "layers.0.attn.in_proj_weight",
12
+ "layers.0.attn.out_proj.bias",
13
+ "layers.0.attn.out_proj.weight",
14
+ "layers.0.ffn.layers.0.bias",
15
+ "layers.0.ffn.layers.0.weight",
16
+ "layers.0.ffn.layers.3.bias",
17
+ "layers.0.ffn.layers.3.weight",
18
+ "layers.0.norm1.bias",
19
+ "layers.0.norm1.weight",
20
+ "layers.0.norm2.bias",
21
+ "layers.0.norm2.weight",
22
+ "layers.1.attn.in_proj_bias",
23
+ "layers.1.attn.in_proj_weight",
24
+ "layers.1.attn.out_proj.bias",
25
+ "layers.1.attn.out_proj.weight",
26
+ "layers.1.ffn.layers.0.bias",
27
+ "layers.1.ffn.layers.0.weight",
28
+ "layers.1.ffn.layers.3.bias",
29
+ "layers.1.ffn.layers.3.weight",
30
+ "layers.1.norm1.bias",
31
+ "layers.1.norm1.weight",
32
+ "layers.1.norm2.bias",
33
+ "layers.1.norm2.weight",
34
+ "layers.10.attn.in_proj_bias",
35
+ "layers.10.attn.in_proj_weight",
36
+ "layers.10.attn.out_proj.bias",
37
+ "layers.10.attn.out_proj.weight",
38
+ "layers.10.ffn.layers.0.bias",
39
+ "layers.10.ffn.layers.0.weight",
40
+ "layers.10.ffn.layers.3.bias",
41
+ "layers.10.ffn.layers.3.weight",
42
+ "layers.10.norm1.bias",
43
+ "layers.10.norm1.weight",
44
+ "layers.10.norm2.bias",
45
+ "layers.10.norm2.weight",
46
+ "layers.11.attn.in_proj_bias",
47
+ "layers.11.attn.in_proj_weight",
48
+ "layers.11.attn.out_proj.bias",
49
+ "layers.11.attn.out_proj.weight",
50
+ "layers.11.ffn.layers.0.bias",
51
+ "layers.11.ffn.layers.0.weight",
52
+ "layers.11.ffn.layers.3.bias",
53
+ "layers.11.ffn.layers.3.weight",
54
+ "layers.11.norm1.bias",
55
+ "layers.11.norm1.weight",
56
+ "layers.11.norm2.bias",
57
+ "layers.11.norm2.weight",
58
+ "layers.12.attn.in_proj_bias",
59
+ "layers.12.attn.in_proj_weight",
60
+ "layers.12.attn.out_proj.bias",
61
+ "layers.12.attn.out_proj.weight",
62
+ "layers.12.ffn.layers.0.bias",
63
+ "layers.12.ffn.layers.0.weight",
64
+ "layers.12.ffn.layers.3.bias",
65
+ "layers.12.ffn.layers.3.weight",
66
+ "layers.12.norm1.bias",
67
+ "layers.12.norm1.weight",
68
+ "layers.12.norm2.bias",
69
+ "layers.12.norm2.weight",
70
+ "layers.13.attn.in_proj_bias",
71
+ "layers.13.attn.in_proj_weight",
72
+ "layers.13.attn.out_proj.bias",
73
+ "layers.13.attn.out_proj.weight",
74
+ "layers.13.ffn.layers.0.bias",
75
+ "layers.13.ffn.layers.0.weight",
76
+ "layers.13.ffn.layers.3.bias",
77
+ "layers.13.ffn.layers.3.weight",
78
+ "layers.13.norm1.bias",
79
+ "layers.13.norm1.weight",
80
+ "layers.13.norm2.bias",
81
+ "layers.13.norm2.weight",
82
+ "layers.14.attn.in_proj_bias",
83
+ "layers.14.attn.in_proj_weight",
84
+ "layers.14.attn.out_proj.bias",
85
+ "layers.14.attn.out_proj.weight",
86
+ "layers.14.ffn.layers.0.bias",
87
+ "layers.14.ffn.layers.0.weight",
88
+ "layers.14.ffn.layers.3.bias",
89
+ "layers.14.ffn.layers.3.weight",
90
+ "layers.14.norm1.bias",
91
+ "layers.14.norm1.weight",
92
+ "layers.14.norm2.bias",
93
+ "layers.14.norm2.weight",
94
+ "layers.15.attn.in_proj_bias",
95
+ "layers.15.attn.in_proj_weight",
96
+ "layers.15.attn.out_proj.bias",
97
+ "layers.15.attn.out_proj.weight",
98
+ "layers.15.ffn.layers.0.bias",
99
+ "layers.15.ffn.layers.0.weight",
100
+ "layers.15.ffn.layers.3.bias",
101
+ "layers.15.ffn.layers.3.weight",
102
+ "layers.15.norm1.bias",
103
+ "layers.15.norm1.weight",
104
+ "layers.15.norm2.bias",
105
+ "layers.15.norm2.weight",
106
+ "layers.16.attn.in_proj_bias",
107
+ "layers.16.attn.in_proj_weight",
108
+ "layers.16.attn.out_proj.bias",
109
+ "layers.16.attn.out_proj.weight",
110
+ "layers.16.ffn.layers.0.bias",
111
+ "layers.16.ffn.layers.0.weight",
112
+ "layers.16.ffn.layers.3.bias",
113
+ "layers.16.ffn.layers.3.weight",
114
+ "layers.16.norm1.bias",
115
+ "layers.16.norm1.weight",
116
+ "layers.16.norm2.bias",
117
+ "layers.16.norm2.weight",
118
+ "layers.17.attn.in_proj_bias",
119
+ "layers.17.attn.in_proj_weight",
120
+ "layers.17.attn.out_proj.bias",
121
+ "layers.17.attn.out_proj.weight",
122
+ "layers.17.ffn.layers.0.bias",
123
+ "layers.17.ffn.layers.0.weight",
124
+ "layers.17.ffn.layers.3.bias",
125
+ "layers.17.ffn.layers.3.weight",
126
+ "layers.17.norm1.bias",
127
+ "layers.17.norm1.weight",
128
+ "layers.17.norm2.bias",
129
+ "layers.17.norm2.weight",
130
+ "layers.18.attn.in_proj_bias",
131
+ "layers.18.attn.in_proj_weight",
132
+ "layers.18.attn.out_proj.bias",
133
+ "layers.18.attn.out_proj.weight",
134
+ "layers.18.ffn.layers.0.bias",
135
+ "layers.18.ffn.layers.0.weight",
136
+ "layers.18.ffn.layers.3.bias",
137
+ "layers.18.ffn.layers.3.weight",
138
+ "layers.18.norm1.bias",
139
+ "layers.18.norm1.weight",
140
+ "layers.18.norm2.bias",
141
+ "layers.18.norm2.weight",
142
+ "layers.19.attn.in_proj_bias",
143
+ "layers.19.attn.in_proj_weight",
144
+ "layers.19.attn.out_proj.bias",
145
+ "layers.19.attn.out_proj.weight",
146
+ "layers.19.ffn.layers.0.bias",
147
+ "layers.19.ffn.layers.0.weight",
148
+ "layers.19.ffn.layers.3.bias",
149
+ "layers.19.ffn.layers.3.weight",
150
+ "layers.19.norm1.bias",
151
+ "layers.19.norm1.weight",
152
+ "layers.19.norm2.bias",
153
+ "layers.19.norm2.weight",
154
+ "layers.2.attn.in_proj_bias",
155
+ "layers.2.attn.in_proj_weight",
156
+ "layers.2.attn.out_proj.bias",
157
+ "layers.2.attn.out_proj.weight",
158
+ "layers.2.ffn.layers.0.bias",
159
+ "layers.2.ffn.layers.0.weight",
160
+ "layers.2.ffn.layers.3.bias",
161
+ "layers.2.ffn.layers.3.weight",
162
+ "layers.2.norm1.bias",
163
+ "layers.2.norm1.weight",
164
+ "layers.2.norm2.bias",
165
+ "layers.2.norm2.weight",
166
+ "layers.20.attn.in_proj_bias",
167
+ "layers.20.attn.in_proj_weight",
168
+ "layers.20.attn.out_proj.bias",
169
+ "layers.20.attn.out_proj.weight",
170
+ "layers.20.ffn.layers.0.bias",
171
+ "layers.20.ffn.layers.0.weight",
172
+ "layers.20.ffn.layers.3.bias",
173
+ "layers.20.ffn.layers.3.weight",
174
+ "layers.20.norm1.bias",
175
+ "layers.20.norm1.weight",
176
+ "layers.20.norm2.bias",
177
+ "layers.20.norm2.weight",
178
+ "layers.21.attn.in_proj_bias",
179
+ "layers.21.attn.in_proj_weight",
180
+ "layers.21.attn.out_proj.bias",
181
+ "layers.21.attn.out_proj.weight",
182
+ "layers.21.ffn.layers.0.bias",
183
+ "layers.21.ffn.layers.0.weight",
184
+ "layers.21.ffn.layers.3.bias",
185
+ "layers.21.ffn.layers.3.weight",
186
+ "layers.21.norm1.bias",
187
+ "layers.21.norm1.weight",
188
+ "layers.21.norm2.bias",
189
+ "layers.21.norm2.weight",
190
+ "layers.22.attn.in_proj_bias",
191
+ "layers.22.attn.in_proj_weight",
192
+ "layers.22.attn.out_proj.bias",
193
+ "layers.22.attn.out_proj.weight",
194
+ "layers.22.ffn.layers.0.bias",
195
+ "layers.22.ffn.layers.0.weight",
196
+ "layers.22.ffn.layers.3.bias",
197
+ "layers.22.ffn.layers.3.weight",
198
+ "layers.22.norm1.bias",
199
+ "layers.22.norm1.weight",
200
+ "layers.22.norm2.bias",
201
+ "layers.22.norm2.weight",
202
+ "layers.23.attn.in_proj_bias",
203
+ "layers.23.attn.in_proj_weight",
204
+ "layers.23.attn.out_proj.bias",
205
+ "layers.23.attn.out_proj.weight",
206
+ "layers.23.ffn.layers.0.bias",
207
+ "layers.23.ffn.layers.0.weight",
208
+ "layers.23.ffn.layers.3.bias",
209
+ "layers.23.ffn.layers.3.weight",
210
+ "layers.23.norm1.bias",
211
+ "layers.23.norm1.weight",
212
+ "layers.23.norm2.bias",
213
+ "layers.23.norm2.weight",
214
+ "layers.3.attn.in_proj_bias",
215
+ "layers.3.attn.in_proj_weight",
216
+ "layers.3.attn.out_proj.bias",
217
+ "layers.3.attn.out_proj.weight",
218
+ "layers.3.ffn.layers.0.bias",
219
+ "layers.3.ffn.layers.0.weight",
220
+ "layers.3.ffn.layers.3.bias",
221
+ "layers.3.ffn.layers.3.weight",
222
+ "layers.3.norm1.bias",
223
+ "layers.3.norm1.weight",
224
+ "layers.3.norm2.bias",
225
+ "layers.3.norm2.weight",
226
+ "layers.4.attn.in_proj_bias",
227
+ "layers.4.attn.in_proj_weight",
228
+ "layers.4.attn.out_proj.bias",
229
+ "layers.4.attn.out_proj.weight",
230
+ "layers.4.ffn.layers.0.bias",
231
+ "layers.4.ffn.layers.0.weight",
232
+ "layers.4.ffn.layers.3.bias",
233
+ "layers.4.ffn.layers.3.weight",
234
+ "layers.4.norm1.bias",
235
+ "layers.4.norm1.weight",
236
+ "layers.4.norm2.bias",
237
+ "layers.4.norm2.weight",
238
+ "layers.5.attn.in_proj_bias",
239
+ "layers.5.attn.in_proj_weight",
240
+ "layers.5.attn.out_proj.bias",
241
+ "layers.5.attn.out_proj.weight",
242
+ "layers.5.ffn.layers.0.bias",
243
+ "layers.5.ffn.layers.0.weight",
244
+ "layers.5.ffn.layers.3.bias",
245
+ "layers.5.ffn.layers.3.weight",
246
+ "layers.5.norm1.bias",
247
+ "layers.5.norm1.weight",
248
+ "layers.5.norm2.bias",
249
+ "layers.5.norm2.weight",
250
+ "layers.6.attn.in_proj_bias",
251
+ "layers.6.attn.in_proj_weight",
252
+ "layers.6.attn.out_proj.bias",
253
+ "layers.6.attn.out_proj.weight",
254
+ "layers.6.ffn.layers.0.bias",
255
+ "layers.6.ffn.layers.0.weight",
256
+ "layers.6.ffn.layers.3.bias",
257
+ "layers.6.ffn.layers.3.weight",
258
+ "layers.6.norm1.bias",
259
+ "layers.6.norm1.weight",
260
+ "layers.6.norm2.bias",
261
+ "layers.6.norm2.weight",
262
+ "layers.7.attn.in_proj_bias",
263
+ "layers.7.attn.in_proj_weight",
264
+ "layers.7.attn.out_proj.bias",
265
+ "layers.7.attn.out_proj.weight",
266
+ "layers.7.ffn.layers.0.bias",
267
+ "layers.7.ffn.layers.0.weight",
268
+ "layers.7.ffn.layers.3.bias",
269
+ "layers.7.ffn.layers.3.weight",
270
+ "layers.7.norm1.bias",
271
+ "layers.7.norm1.weight",
272
+ "layers.7.norm2.bias",
273
+ "layers.7.norm2.weight",
274
+ "layers.8.attn.in_proj_bias",
275
+ "layers.8.attn.in_proj_weight",
276
+ "layers.8.attn.out_proj.bias",
277
+ "layers.8.attn.out_proj.weight",
278
+ "layers.8.ffn.layers.0.bias",
279
+ "layers.8.ffn.layers.0.weight",
280
+ "layers.8.ffn.layers.3.bias",
281
+ "layers.8.ffn.layers.3.weight",
282
+ "layers.8.norm1.bias",
283
+ "layers.8.norm1.weight",
284
+ "layers.8.norm2.bias",
285
+ "layers.8.norm2.weight",
286
+ "layers.9.attn.in_proj_bias",
287
+ "layers.9.attn.in_proj_weight",
288
+ "layers.9.attn.out_proj.bias",
289
+ "layers.9.attn.out_proj.weight",
290
+ "layers.9.ffn.layers.0.bias",
291
+ "layers.9.ffn.layers.0.weight",
292
+ "layers.9.ffn.layers.3.bias",
293
+ "layers.9.ffn.layers.3.weight",
294
+ "layers.9.norm1.bias",
295
+ "layers.9.norm1.weight",
296
+ "layers.9.norm2.bias",
297
+ "layers.9.norm2.weight",
298
+ "patch_embed.projection.bias",
299
+ "patch_embed.projection.weight",
300
+ "pos_embed"
301
+ ]
302
+ }
skysense-vit-large-s1/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:51713a8bb27b1e6644a4b3701752f8609126b653c806e748ed6264be2a247a4b
3
+ size 1210458152
skysense-vit-large-s1/modeling_skysense_swinv2.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Swin Transformer V2 backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles high-resolution optical imagery (RGB/RGBNIR).
4
+ """
5
+
6
+ from copy import deepcopy
7
+ from typing import Optional, Sequence, Tuple, Union
8
+
9
+ import numpy as np
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseSwinV2Config
17
+ from .modeling_utils import (
18
+ DropPath,
19
+ FFN,
20
+ PatchEmbed,
21
+ PatchMerging,
22
+ ShiftWindowMSA,
23
+ to_2tuple,
24
+ )
25
+
26
+
27
+ class SwinBlockV2(nn.Module):
28
+ """Swin Transformer V2 block with post-normalization.
29
+
30
+ Args:
31
+ embed_dims (int): Number of input channels.
32
+ num_heads (int): Number of attention heads.
33
+ window_size (int): Window size. Default: 8.
34
+ shift (bool): Shift the attention window. Default: False.
35
+ extra_norm (bool): Extra norm at end of block. Default: False.
36
+ ffn_ratio (float): FFN expansion ratio. Default: 4.0.
37
+ drop_path (float): Drop path rate. Default: 0.0.
38
+ pad_small_map (bool): Pad small maps. Default: False.
39
+ with_cp (bool): Gradient checkpointing. Default: False.
40
+ pretrained_window_size (int): Pretrained window size. Default: 0.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ embed_dims: int,
46
+ num_heads: int,
47
+ window_size: int = 8,
48
+ shift: bool = False,
49
+ extra_norm: bool = False,
50
+ ffn_ratio: float = 4.0,
51
+ drop_path: float = 0.0,
52
+ pad_small_map: bool = False,
53
+ with_cp: bool = False,
54
+ pretrained_window_size: int = 0,
55
+ ):
56
+ super().__init__()
57
+ self.with_cp = with_cp
58
+ self.extra_norm = extra_norm
59
+
60
+ self.attn = ShiftWindowMSA(
61
+ embed_dims=embed_dims,
62
+ num_heads=num_heads,
63
+ window_size=window_size,
64
+ shift_size=window_size // 2 if shift else 0,
65
+ drop_path=drop_path,
66
+ pad_small_map=pad_small_map,
67
+ pretrained_window_size=pretrained_window_size,
68
+ )
69
+ self.norm1 = nn.LayerNorm(embed_dims)
70
+
71
+ self.ffn = FFN(
72
+ embed_dims=embed_dims,
73
+ feedforward_channels=int(embed_dims * ffn_ratio),
74
+ num_fcs=2,
75
+ drop_path=drop_path,
76
+ act_layer=nn.GELU,
77
+ add_identity=False,
78
+ )
79
+ self.norm2 = nn.LayerNorm(embed_dims)
80
+
81
+ if self.extra_norm:
82
+ self.norm3 = nn.LayerNorm(embed_dims)
83
+
84
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
85
+ def _inner_forward(x):
86
+ # Post normalization
87
+ identity = x
88
+ x = self.attn(x, hw_shape)
89
+ x = self.norm1(x)
90
+ x = x + identity
91
+
92
+ identity = x
93
+ x = self.ffn(x)
94
+ x = self.norm2(x)
95
+ x = x + identity
96
+
97
+ if self.extra_norm:
98
+ x = self.norm3(x)
99
+ return x
100
+
101
+ if self.with_cp and x.requires_grad:
102
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
103
+ else:
104
+ x = _inner_forward(x)
105
+ return x
106
+
107
+
108
+ class SwinBlockV2Sequence(nn.Module):
109
+ """Sequence of Swin Transformer V2 blocks with optional downsample.
110
+
111
+ Args:
112
+ embed_dims (int): Number of input channels.
113
+ depth (int): Number of blocks.
114
+ num_heads (int): Number of attention heads.
115
+ window_size (int): Window size. Default: 8.
116
+ downsample (bool): Apply downsample. Default: False.
117
+ drop_paths (list or float): Drop path rates. Default: 0.0.
118
+ with_cp (bool): Gradient checkpointing. Default: False.
119
+ pad_small_map (bool): Pad small maps. Default: False.
120
+ extra_norm_every_n_blocks (int): Extra norm interval. Default: 0.
121
+ pretrained_window_size (int): Pretrained window size. Default: 0.
122
+ is_post_norm_downsample (bool): Post-norm in downsample. Default: True.
123
+ """
124
+
125
+ def __init__(
126
+ self,
127
+ embed_dims: int,
128
+ depth: int,
129
+ num_heads: int,
130
+ window_size: int = 8,
131
+ downsample: bool = False,
132
+ drop_paths: Union[Sequence[float], float] = 0.0,
133
+ with_cp: bool = False,
134
+ pad_small_map: bool = False,
135
+ extra_norm_every_n_blocks: int = 0,
136
+ pretrained_window_size: int = 0,
137
+ is_post_norm_downsample: bool = True,
138
+ ):
139
+ super().__init__()
140
+
141
+ if not isinstance(drop_paths, Sequence):
142
+ drop_paths = [drop_paths] * depth
143
+
144
+ if downsample:
145
+ self.out_channels = 2 * embed_dims
146
+ self.downsample = PatchMerging(
147
+ in_channels=embed_dims,
148
+ out_channels=self.out_channels,
149
+ is_post_norm=is_post_norm_downsample,
150
+ )
151
+ else:
152
+ self.out_channels = embed_dims
153
+ self.downsample = None
154
+
155
+ self.blocks = nn.ModuleList()
156
+ for i in range(depth):
157
+ extra_norm = (
158
+ extra_norm_every_n_blocks > 0
159
+ and (i + 1) % extra_norm_every_n_blocks == 0
160
+ )
161
+ block = SwinBlockV2(
162
+ embed_dims=self.out_channels,
163
+ num_heads=num_heads,
164
+ window_size=window_size,
165
+ shift=(i % 2 == 1),
166
+ extra_norm=extra_norm,
167
+ drop_path=drop_paths[i],
168
+ with_cp=with_cp,
169
+ pad_small_map=pad_small_map,
170
+ pretrained_window_size=pretrained_window_size,
171
+ )
172
+ self.blocks.append(block)
173
+
174
+ def forward(
175
+ self, x: torch.Tensor, in_shape: Tuple[int, int]
176
+ ) -> Tuple[torch.Tensor, Tuple[int, int]]:
177
+ if self.downsample is not None:
178
+ x, out_shape = self.downsample(x, in_shape)
179
+ else:
180
+ out_shape = in_shape
181
+
182
+ for block in self.blocks:
183
+ x = block(x, out_shape)
184
+
185
+ return x, out_shape
186
+
187
+
188
+ class SkySenseSwinV2PreTrainedModel(PreTrainedModel):
189
+ """Base class for SkySense Swin Transformer V2 models."""
190
+
191
+ config_class = SkySenseSwinV2Config
192
+ base_model_prefix = "skysense_swinv2"
193
+ supports_gradient_checkpointing = True
194
+
195
+ def _init_weights(self, module):
196
+ """Initialize weights."""
197
+ if isinstance(module, nn.Linear):
198
+ nn.init.trunc_normal_(module.weight, std=0.02)
199
+ if module.bias is not None:
200
+ nn.init.zeros_(module.bias)
201
+ elif isinstance(module, nn.LayerNorm):
202
+ nn.init.ones_(module.weight)
203
+ nn.init.zeros_(module.bias)
204
+ elif isinstance(module, nn.Conv2d):
205
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
206
+ if module.bias is not None:
207
+ nn.init.zeros_(module.bias)
208
+
209
+
210
+ class SkySenseSwinV2Model(SkySenseSwinV2PreTrainedModel):
211
+ """SkySense Swin Transformer V2 backbone.
212
+
213
+ A pure PyTorch + HuggingFace implementation of the Swin Transformer V2
214
+ used in SkySense for high-resolution optical remote sensing imagery.
215
+ """
216
+
217
+ def __init__(self, config: SkySenseSwinV2Config):
218
+ super().__init__(config)
219
+
220
+ self.num_layers = len(config.depths)
221
+ self.out_indices = config.out_indices
222
+
223
+ # Window sizes per stage
224
+ if isinstance(config.window_size, int):
225
+ window_sizes = [config.window_size] * self.num_layers
226
+ else:
227
+ window_sizes = list(config.window_size)
228
+
229
+ # Patch embedding
230
+ self.patch_embed = PatchEmbed(
231
+ in_channels=config.in_channels,
232
+ embed_dims=config.embed_dims,
233
+ kernel_size=config.patch_size,
234
+ stride=config.patch_size,
235
+ norm_layer=nn.LayerNorm,
236
+ input_size=config.img_size,
237
+ )
238
+
239
+ # Optional absolute position embedding
240
+ self.use_abs_pos_embed = config.use_abs_pos_embed
241
+ if self.use_abs_pos_embed:
242
+ patch_resolution = self.patch_embed.init_out_size
243
+ num_patches = patch_resolution[0] * patch_resolution[1]
244
+ self.absolute_pos_embed = nn.Parameter(
245
+ torch.zeros(1, num_patches, config.embed_dims)
246
+ )
247
+
248
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
249
+
250
+ # Stochastic depth decay (computed without tensors for meta-device compat)
251
+ total_depth = sum(config.depths)
252
+ if total_depth > 1:
253
+ dpr = [config.drop_path_rate * i / (total_depth - 1) for i in range(total_depth)]
254
+ else:
255
+ dpr = [0.0]
256
+
257
+ # Build stages
258
+ self.stages = nn.ModuleList()
259
+ embed_dims_list = [config.embed_dims]
260
+ for i, (depth, num_heads) in enumerate(
261
+ zip(config.depths, config.num_heads)
262
+ ):
263
+ stage = SwinBlockV2Sequence(
264
+ embed_dims=embed_dims_list[-1],
265
+ depth=depth,
266
+ num_heads=num_heads,
267
+ window_size=window_sizes[i],
268
+ downsample=(i > 0),
269
+ drop_paths=dpr[:depth],
270
+ with_cp=config.with_cp,
271
+ pad_small_map=config.pad_small_map,
272
+ extra_norm_every_n_blocks=config.extra_norm_every_n_blocks,
273
+ pretrained_window_size=config.pretrained_window_sizes[i],
274
+ is_post_norm_downsample=config.is_post_norm_downsample,
275
+ )
276
+ self.stages.append(stage)
277
+ dpr = dpr[depth:]
278
+ embed_dims_list.append(stage.out_channels)
279
+
280
+ # Output norms
281
+ for i in self.out_indices:
282
+ norm = nn.LayerNorm(embed_dims_list[i + 1])
283
+ self.add_module(f"norm{i}", norm)
284
+
285
+ self.post_init()
286
+
287
+ def _delete_reinit_params(self, state_dict, prefix, *args, **kwargs):
288
+ """Delete relative_position_index and relative_coords_table from state_dict."""
289
+ keys_to_delete = [
290
+ k for k in state_dict.keys()
291
+ if 'relative_position_index' in k or 'relative_coords_table' in k
292
+ ]
293
+ for k in keys_to_delete:
294
+ del state_dict[k]
295
+
296
+ def forward(
297
+ self,
298
+ pixel_values: torch.Tensor,
299
+ output_hidden_states: Optional[bool] = None,
300
+ return_dict: Optional[bool] = None,
301
+ ) -> Union[Tuple, BaseModelOutput]:
302
+ """
303
+ Args:
304
+ pixel_values: (B, C, H, W) input image tensor.
305
+ output_hidden_states: Whether to return all hidden states.
306
+ return_dict: Whether to return a BaseModelOutput.
307
+
308
+ Returns:
309
+ BaseModelOutput or tuple of feature maps.
310
+ """
311
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
312
+
313
+ x, hw_shape = self.patch_embed(pixel_values)
314
+
315
+ if self.use_abs_pos_embed:
316
+ x = x + self.absolute_pos_embed
317
+ x = self.drop_after_pos(x)
318
+
319
+ all_hidden_states = () if output_hidden_states else None
320
+ feature_maps = []
321
+
322
+ for i, stage in enumerate(self.stages):
323
+ x, hw_shape = stage(x, hw_shape)
324
+ if output_hidden_states:
325
+ all_hidden_states = all_hidden_states + (x,)
326
+ if i in self.out_indices:
327
+ norm_layer = getattr(self, f"norm{i}")
328
+ out = norm_layer(x)
329
+ out = out.view(
330
+ -1, *hw_shape, stage.out_channels
331
+ ).permute(0, 3, 1, 2).contiguous()
332
+ feature_maps.append(out)
333
+
334
+ if not return_dict:
335
+ return tuple(feature_maps)
336
+
337
+ return BaseModelOutput(
338
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
339
+ hidden_states=all_hidden_states,
340
+ )
skysense-vit-large-s1/modeling_skysense_vit.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Vision Transformer backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple, Union
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseViTConfig
17
+ from .modeling_utils import DropPath, FFN, PatchEmbed, to_2tuple
18
+
19
+
20
+ class TransformerEncoderLayer(nn.Module):
21
+ """Single encoder layer for the Vision Transformer.
22
+
23
+ Args:
24
+ embed_dims (int): Embedding dimension.
25
+ num_heads (int): Number of attention heads.
26
+ feedforward_channels (int): FFN hidden dimension.
27
+ drop_rate (float): Dropout rate. Default: 0.0.
28
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
29
+ drop_path_rate (float): Drop path rate. Default: 0.0.
30
+ num_fcs (int): Number of FC layers in FFN. Default: 2.
31
+ qkv_bias (bool): QKV bias. Default: True.
32
+ with_cp (bool): Gradient checkpointing. Default: False.
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ embed_dims: int,
38
+ num_heads: int,
39
+ feedforward_channels: int,
40
+ drop_rate: float = 0.0,
41
+ attn_drop_rate: float = 0.0,
42
+ drop_path_rate: float = 0.0,
43
+ num_fcs: int = 2,
44
+ qkv_bias: bool = True,
45
+ with_cp: bool = False,
46
+ ):
47
+ super().__init__()
48
+ self.with_cp = with_cp
49
+
50
+ self.norm1 = nn.LayerNorm(embed_dims)
51
+ self.attn = nn.MultiheadAttention(
52
+ embed_dim=embed_dims,
53
+ num_heads=num_heads,
54
+ dropout=attn_drop_rate,
55
+ bias=qkv_bias,
56
+ batch_first=True,
57
+ )
58
+ self.proj_drop = nn.Dropout(drop_rate)
59
+
60
+ self.norm2 = nn.LayerNorm(embed_dims)
61
+ self.ffn = FFN(
62
+ embed_dims=embed_dims,
63
+ feedforward_channels=feedforward_channels,
64
+ num_fcs=num_fcs,
65
+ ffn_drop=drop_rate,
66
+ drop_path=drop_path_rate,
67
+ act_layer=nn.GELU,
68
+ add_identity=True,
69
+ )
70
+
71
+ self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
72
+
73
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
74
+ def _inner_forward(x):
75
+ # Pre-norm attention with residual
76
+ residual = x
77
+ x_norm = self.norm1(x)
78
+ attn_out, _ = self.attn(x_norm, x_norm, x_norm)
79
+ attn_out = self.proj_drop(attn_out)
80
+ x = residual + self.drop_path(attn_out)
81
+
82
+ # Pre-norm FFN with residual (FFN handles its own residual)
83
+ x = self.ffn(self.norm2(x), identity=x)
84
+ return x
85
+
86
+ if self.with_cp and x.requires_grad:
87
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
88
+ else:
89
+ x = _inner_forward(x)
90
+ return x
91
+
92
+
93
+ class SkySenseViTPreTrainedModel(PreTrainedModel):
94
+ """Base class for SkySense Vision Transformer models."""
95
+
96
+ config_class = SkySenseViTConfig
97
+ base_model_prefix = "skysense_vit"
98
+ supports_gradient_checkpointing = True
99
+
100
+ def _init_weights(self, module):
101
+ """Initialize weights following jax_impl."""
102
+ if isinstance(module, nn.Linear):
103
+ nn.init.trunc_normal_(module.weight, std=0.02)
104
+ if module.bias is not None:
105
+ nn.init.zeros_(module.bias)
106
+ elif isinstance(module, (nn.LayerNorm, nn.GroupNorm)):
107
+ nn.init.ones_(module.weight)
108
+ nn.init.zeros_(module.bias)
109
+ elif isinstance(module, nn.Conv2d):
110
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
111
+ if module.bias is not None:
112
+ nn.init.zeros_(module.bias)
113
+
114
+
115
+ class SkySenseViTModel(SkySenseViTPreTrainedModel):
116
+ """SkySense Vision Transformer backbone.
117
+
118
+ A pure PyTorch + HuggingFace implementation of the ViT used in SkySense
119
+ for Sentinel-2 multispectral and Sentinel-1 SAR imagery.
120
+ """
121
+
122
+ def __init__(self, config: SkySenseViTConfig):
123
+ super().__init__(config)
124
+
125
+ img_size = to_2tuple(config.img_size)
126
+ self.img_size = img_size
127
+ self.patch_size = config.patch_size
128
+ self.with_cls_token = config.with_cls_token
129
+ self.output_cls_token = config.output_cls_token
130
+ self.interpolate_mode = 'bicubic'
131
+
132
+ # Patch embedding
133
+ self.patch_embed = PatchEmbed(
134
+ in_channels=config.in_channels,
135
+ embed_dims=config.embed_dims,
136
+ kernel_size=config.patch_size,
137
+ stride=config.patch_size,
138
+ norm_layer=nn.LayerNorm if config.patch_norm else None,
139
+ )
140
+
141
+ num_patches = (img_size[0] // config.patch_size) * (
142
+ img_size[1] // config.patch_size
143
+ )
144
+
145
+ self.cls_token = nn.Parameter(torch.zeros(1, 1, config.embed_dims))
146
+ self.pos_embed = nn.Parameter(
147
+ torch.zeros(1, num_patches + 1, config.embed_dims)
148
+ )
149
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
150
+
151
+ # Resolve out_indices
152
+ out_indices = list(config.out_indices)
153
+ resolved = []
154
+ for idx in out_indices:
155
+ if idx < 0:
156
+ idx = config.num_layers + idx
157
+ resolved.append(idx)
158
+ self.out_indices = resolved
159
+
160
+ # Stochastic depth (computed without tensors for meta-device compat)
161
+ num_layers = config.num_layers
162
+ if num_layers > 1:
163
+ dpr = [config.drop_path_rate * i / (num_layers - 1) for i in range(num_layers)]
164
+ else:
165
+ dpr = [0.0]
166
+
167
+ # Transformer encoder layers
168
+ self.layers = nn.ModuleList()
169
+ for i in range(config.num_layers):
170
+ self.layers.append(
171
+ TransformerEncoderLayer(
172
+ embed_dims=config.embed_dims,
173
+ num_heads=config.num_heads,
174
+ feedforward_channels=config.mlp_ratio * config.embed_dims,
175
+ attn_drop_rate=config.attn_drop_rate,
176
+ drop_rate=config.drop_rate,
177
+ drop_path_rate=dpr[i],
178
+ num_fcs=2,
179
+ qkv_bias=config.qkv_bias,
180
+ with_cp=config.with_cp,
181
+ )
182
+ )
183
+
184
+ # Final norm
185
+ self.final_norm = config.final_norm
186
+ if config.final_norm:
187
+ self.norm = nn.LayerNorm(config.embed_dims)
188
+
189
+ self.post_init()
190
+
191
+ @staticmethod
192
+ def resize_pos_embed(pos_embed, input_shape, pos_shape, mode='bicubic'):
193
+ """Resize position embeddings via interpolation.
194
+
195
+ Args:
196
+ pos_embed (torch.Tensor): Position embedding of shape (B, L, C),
197
+ where L = 1 (cls_token) + pos_h * pos_w.
198
+ input_shape (tuple[int, int]): Target spatial size (H, W).
199
+ pos_shape (tuple[int, int]): Original spatial size (pos_h, pos_w).
200
+ mode (str): Interpolation mode. Default: 'bicubic'.
201
+
202
+ Returns:
203
+ torch.Tensor: Resized position embedding of shape (B, 1 + H*W, C).
204
+ """
205
+ assert pos_embed.ndim == 3
206
+ pos_h, pos_w = pos_shape
207
+ cls_token_weight = pos_embed[:, 0:1]
208
+ pos_embed_weight = pos_embed[:, (-1 * pos_h * pos_w):]
209
+ pos_embed_weight = pos_embed_weight.reshape(
210
+ 1, pos_h, pos_w, pos_embed.shape[2]
211
+ ).permute(0, 3, 1, 2)
212
+ pos_embed_weight = F.interpolate(
213
+ pos_embed_weight,
214
+ size=input_shape,
215
+ align_corners=False,
216
+ mode=mode,
217
+ )
218
+ pos_embed_weight = torch.flatten(pos_embed_weight, 2).transpose(1, 2)
219
+ pos_embed = torch.cat((cls_token_weight, pos_embed_weight), dim=1)
220
+ return pos_embed
221
+
222
+ def _pos_embedding(self, patched_img, hw_shape, pos_embed):
223
+ """Apply position embedding with optional interpolation."""
224
+ x_len, pos_len = patched_img.shape[1], pos_embed.shape[1]
225
+ if x_len != pos_len:
226
+ pos_h = self.img_size[0] // self.patch_size
227
+ pos_w = self.img_size[1] // self.patch_size
228
+ pos_embed = self.resize_pos_embed(
229
+ pos_embed, hw_shape, (pos_h, pos_w), self.interpolate_mode
230
+ )
231
+ return self.drop_after_pos(patched_img + pos_embed)
232
+
233
+ def forward(
234
+ self,
235
+ pixel_values: torch.Tensor,
236
+ output_hidden_states: Optional[bool] = None,
237
+ return_dict: Optional[bool] = None,
238
+ ) -> Union[Tuple, BaseModelOutput]:
239
+ """
240
+ Args:
241
+ pixel_values: (B, C, H, W) input tensor.
242
+ output_hidden_states: Return all hidden states.
243
+ return_dict: Return BaseModelOutput.
244
+
245
+ Returns:
246
+ Feature maps or BaseModelOutput.
247
+ """
248
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
249
+ B = pixel_values.shape[0]
250
+
251
+ x, hw_shape = self.patch_embed(pixel_values)
252
+
253
+ # Prepend CLS token
254
+ cls_tokens = self.cls_token.expand(B, -1, -1)
255
+ x = torch.cat((cls_tokens, x), dim=1)
256
+ x = self._pos_embedding(x, hw_shape, self.pos_embed)
257
+
258
+ if not self.with_cls_token:
259
+ x = x[:, 1:]
260
+
261
+ all_hidden_states = () if output_hidden_states else None
262
+ feature_maps = []
263
+
264
+ for i, layer in enumerate(self.layers):
265
+ x = layer(x)
266
+
267
+ if i == len(self.layers) - 1 and self.final_norm:
268
+ x = self.norm(x)
269
+
270
+ if output_hidden_states:
271
+ all_hidden_states = all_hidden_states + (x,)
272
+
273
+ if i in self.out_indices:
274
+ if self.with_cls_token:
275
+ out = x[:, 1:]
276
+ else:
277
+ out = x
278
+ B_, _, C = out.shape
279
+ out = out.reshape(
280
+ B_, hw_shape[0], hw_shape[1], C
281
+ ).permute(0, 3, 1, 2).contiguous()
282
+ if self.output_cls_token:
283
+ out = [out, x[:, 0]]
284
+ feature_maps.append(out)
285
+
286
+ if not return_dict:
287
+ return tuple(feature_maps)
288
+
289
+ return BaseModelOutput(
290
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
291
+ hidden_states=all_hidden_states,
292
+ )
skysense-vit-large-s1/modeling_utils.py ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense: Pure PyTorch + HuggingFace Transformers implementation.
2
+
3
+ Shared utility modules used across SkySense model implementations.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+
13
+
14
+ def to_2tuple(x):
15
+ """Convert to a 2-tuple."""
16
+ if isinstance(x, (list, tuple)):
17
+ return tuple(x)
18
+ return (x, x)
19
+
20
+
21
+ class DropPath(nn.Module):
22
+ """Drop paths (stochastic depth) per sample.
23
+
24
+ Args:
25
+ drop_prob (float): Probability of dropping a path. Default: 0.0.
26
+ """
27
+
28
+ def __init__(self, drop_prob: float = 0.0):
29
+ super().__init__()
30
+ self.drop_prob = drop_prob
31
+
32
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
33
+ if self.drop_prob == 0.0 or not self.training:
34
+ return x
35
+ keep_prob = 1 - self.drop_prob
36
+ shape = (x.shape[0],) + (1,) * (x.ndim - 1)
37
+ random_tensor = torch.rand(shape, dtype=x.dtype, device=x.device)
38
+ random_tensor = torch.floor(random_tensor + keep_prob)
39
+ output = x / keep_prob * random_tensor
40
+ return output
41
+
42
+
43
+ class PatchEmbed(nn.Module):
44
+ """Image to Patch Embedding using Conv2d.
45
+
46
+ Args:
47
+ in_channels (int): Number of input channels. Default: 3.
48
+ embed_dims (int): Embedding dimension. Default: 96.
49
+ kernel_size (int): Kernel size of the projection. Default: 4.
50
+ stride (int): Stride of the projection. Default: 4.
51
+ padding (int): Padding of the projection. Default: 0.
52
+ norm_layer (nn.Module or None): Normalization layer. Default: nn.LayerNorm.
53
+ input_size (int or tuple or None): Input resolution for calculating output size.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ in_channels: int = 3,
59
+ embed_dims: int = 96,
60
+ kernel_size: int = 4,
61
+ stride: int = 4,
62
+ padding: int = 0,
63
+ norm_layer: Optional[type] = nn.LayerNorm,
64
+ input_size: Optional[int] = None,
65
+ ):
66
+ super().__init__()
67
+ self.projection = nn.Conv2d(
68
+ in_channels, embed_dims,
69
+ kernel_size=kernel_size, stride=stride, padding=padding,
70
+ )
71
+ self.norm = norm_layer(embed_dims) if norm_layer else nn.Identity()
72
+
73
+ # Compute init output size if input_size is given
74
+ if input_size is not None:
75
+ input_size = to_2tuple(input_size)
76
+ self.init_out_size = (
77
+ (input_size[0] - kernel_size + 2 * padding) // stride + 1,
78
+ (input_size[1] - kernel_size + 2 * padding) // stride + 1,
79
+ )
80
+ else:
81
+ self.init_out_size = None
82
+
83
+ def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, Tuple[int, int]]:
84
+ x = self.projection(x) # (B, C, H, W)
85
+ out_size = (x.shape[2], x.shape[3])
86
+ x = x.flatten(2).transpose(1, 2) # (B, H*W, C)
87
+ x = self.norm(x)
88
+ return x, out_size
89
+
90
+
91
+ class FFN(nn.Module):
92
+ """Feed-Forward Network.
93
+
94
+ Args:
95
+ embed_dims (int): Input dimension.
96
+ feedforward_channels (int): Hidden dimension.
97
+ num_fcs (int): Number of FC layers. Default: 2.
98
+ ffn_drop (float): Dropout rate. Default: 0.0.
99
+ drop_path (float): Drop path rate. Default: 0.0.
100
+ act_layer (nn.Module): Activation layer class. Default: nn.GELU.
101
+ add_identity (bool): Whether to add identity connection. Default: True.
102
+ """
103
+
104
+ def __init__(
105
+ self,
106
+ embed_dims: int,
107
+ feedforward_channels: int,
108
+ num_fcs: int = 2,
109
+ ffn_drop: float = 0.0,
110
+ drop_path: float = 0.0,
111
+ act_layer: type = nn.GELU,
112
+ add_identity: bool = True,
113
+ ):
114
+ super().__init__()
115
+ assert num_fcs >= 2, f"num_fcs must be >= 2, got {num_fcs}"
116
+ self.embed_dims = embed_dims
117
+ self.feedforward_channels = feedforward_channels
118
+ self.add_identity = add_identity
119
+
120
+ layers = []
121
+ in_channels = embed_dims
122
+ for i in range(num_fcs - 1):
123
+ layers.append(nn.Linear(in_channels, feedforward_channels))
124
+ layers.append(act_layer())
125
+ layers.append(nn.Dropout(ffn_drop))
126
+ in_channels = feedforward_channels
127
+ layers.append(nn.Linear(feedforward_channels, embed_dims))
128
+ layers.append(nn.Dropout(ffn_drop))
129
+ self.layers = nn.Sequential(*layers)
130
+
131
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
132
+
133
+ def forward(self, x: torch.Tensor, identity: Optional[torch.Tensor] = None) -> torch.Tensor:
134
+ out = self.layers(x)
135
+ out = self.drop_path(out)
136
+ if self.add_identity:
137
+ if identity is None:
138
+ identity = x
139
+ out = out + identity
140
+ return out
141
+
142
+
143
+ class WindowMSAV2(nn.Module):
144
+ """Window-based Multi-head Self-Attention for Swin Transformer V2.
145
+
146
+ Uses cosine attention and log-spaced continuous position bias (log-CPB).
147
+
148
+ Args:
149
+ embed_dims (int): Number of input channels.
150
+ num_heads (int): Number of attention heads.
151
+ window_size (tuple[int]): Window size (Wh, Ww).
152
+ pretrained_window_size (tuple[int]): Pretrained window size for CPB. Default: (0, 0).
153
+ qkv_bias (bool): If True, add learnable bias to q, k, v. Default: True.
154
+ attn_drop (float): Attention dropout rate. Default: 0.0.
155
+ proj_drop (float): Output projection dropout rate. Default: 0.0.
156
+ """
157
+
158
+ def __init__(
159
+ self,
160
+ embed_dims: int,
161
+ num_heads: int,
162
+ window_size: Tuple[int, int],
163
+ pretrained_window_size: Tuple[int, int] = (0, 0),
164
+ qkv_bias: bool = True,
165
+ attn_drop: float = 0.0,
166
+ proj_drop: float = 0.0,
167
+ ):
168
+ super().__init__()
169
+ self.embed_dims = embed_dims
170
+ self.num_heads = num_heads
171
+ self.window_size = window_size
172
+ self.pretrained_window_size = pretrained_window_size
173
+
174
+ self.logit_scale = nn.Parameter(
175
+ torch.log(10 * torch.ones((num_heads, 1, 1))))
176
+
177
+ # MLP for continuous relative position bias (log-CPB)
178
+ self.cpb_mlp = nn.Sequential(
179
+ nn.Linear(2, 512, bias=True),
180
+ nn.ReLU(inplace=True),
181
+ nn.Linear(512, num_heads, bias=False),
182
+ )
183
+
184
+ # Build relative coords table
185
+ self._build_relative_coords_table()
186
+ # Build relative position index
187
+ self._build_relative_position_index()
188
+
189
+ self.qkv = nn.Linear(embed_dims, embed_dims * 3, bias=False)
190
+ if qkv_bias:
191
+ self.q_bias = nn.Parameter(torch.zeros(embed_dims))
192
+ self.v_bias = nn.Parameter(torch.zeros(embed_dims))
193
+ else:
194
+ self.q_bias = None
195
+ self.v_bias = None
196
+
197
+ self.attn_drop = nn.Dropout(attn_drop)
198
+ self.proj = nn.Linear(embed_dims, embed_dims)
199
+ self.proj_drop = nn.Dropout(proj_drop)
200
+ self.softmax = nn.Softmax(dim=-1)
201
+
202
+ def _build_relative_coords_table(self):
203
+ """Build the relative coordinates table for log-CPB."""
204
+ Wh, Ww = self.window_size
205
+ # Table of relative coordinates
206
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32)
207
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32)
208
+ coords_table = torch.stack(
209
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
210
+ ).flatten(1).transpose(0, 1).unsqueeze(0) # (1, (2Wh-1)*(2Ww-1), 2)
211
+
212
+ # Normalize to [-1, 1] and apply log-scale
213
+ if self.pretrained_window_size[0] > 0:
214
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
215
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
216
+ else:
217
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
218
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
219
+ coords_table *= 8 # normalize to -8, 8
220
+ coords_table = (
221
+ torch.sign(coords_table)
222
+ * torch.log2(torch.abs(coords_table) + 1.0)
223
+ / math.log2(8)
224
+ )
225
+ self.register_buffer("relative_coords_table", coords_table)
226
+
227
+ def _build_relative_position_index(self):
228
+ """Build the pairwise relative position index for each window token."""
229
+ Wh, Ww = self.window_size
230
+ coords_h = torch.arange(Wh)
231
+ coords_w = torch.arange(Ww)
232
+ coords = torch.stack(torch.meshgrid(coords_h, coords_w, indexing='ij'))
233
+ coords_flatten = coords.view(2, -1)
234
+
235
+ relative_coords = (
236
+ coords_flatten[:, :, None] - coords_flatten[:, None, :]
237
+ ) # (2, Wh*Ww, Wh*Ww)
238
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous()
239
+ relative_coords[:, :, 0] += Wh - 1
240
+ relative_coords[:, :, 1] += Ww - 1
241
+ relative_coords[:, :, 0] *= 2 * Ww - 1
242
+ relative_position_index = relative_coords.sum(-1) # (Wh*Ww, Wh*Ww)
243
+ self.register_buffer("relative_position_index", relative_position_index)
244
+
245
+ def _compute_position_bias(self, N):
246
+ """Compute relative position bias, supporting dynamic window sizes.
247
+
248
+ The log-CPB (Continuous Position Bias) MLP can generalize to any window
249
+ size by computing bias from normalized relative coordinates.
250
+ """
251
+ init_N = self.window_size[0] * self.window_size[1]
252
+ if N == init_N:
253
+ # Use pre-built tables
254
+ relative_position_bias_table = self.cpb_mlp(
255
+ self.relative_coords_table
256
+ ).view(-1, self.num_heads)
257
+ relative_position_bias = relative_position_bias_table[
258
+ self.relative_position_index.view(-1)
259
+ ].view(N, N, -1)
260
+ else:
261
+ # Dynamic: compute for actual window size on-the-fly
262
+ Wh = Ww = int(math.sqrt(N))
263
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32, device=self.logit_scale.device)
264
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32, device=self.logit_scale.device)
265
+ coords_table = torch.stack(
266
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
267
+ ).flatten(1).transpose(0, 1).unsqueeze(0)
268
+ if self.pretrained_window_size[0] > 0:
269
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
270
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
271
+ else:
272
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
273
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
274
+ coords_table *= 8
275
+ coords_table = (
276
+ torch.sign(coords_table)
277
+ * torch.log2(torch.abs(coords_table) + 1.0)
278
+ / math.log2(8)
279
+ )
280
+ # Build position index for actual window size
281
+ ch = torch.arange(Wh, device=self.logit_scale.device)
282
+ cw = torch.arange(Ww, device=self.logit_scale.device)
283
+ coords = torch.stack(torch.meshgrid(ch, cw, indexing='ij'))
284
+ coords_flat = coords.view(2, -1)
285
+ rel = coords_flat[:, :, None] - coords_flat[:, None, :]
286
+ rel = rel.permute(1, 2, 0).contiguous()
287
+ rel[:, :, 0] += Wh - 1
288
+ rel[:, :, 1] += Ww - 1
289
+ rel[:, :, 0] *= 2 * Ww - 1
290
+ pos_index = rel.sum(-1)
291
+
292
+ bias_table = self.cpb_mlp(coords_table).view(-1, self.num_heads)
293
+ relative_position_bias = bias_table[
294
+ pos_index.view(-1)
295
+ ].view(N, N, -1)
296
+
297
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()
298
+ relative_position_bias = 16 * torch.sigmoid(relative_position_bias)
299
+ return relative_position_bias
300
+
301
+ def forward(self, x: torch.Tensor, mask: Optional[torch.Tensor] = None) -> torch.Tensor:
302
+ """
303
+ Args:
304
+ x: (num_windows*B, N, C) where N = Wh*Ww
305
+ mask: (num_windows, N, N) or None
306
+ """
307
+ B_, N, C = x.shape
308
+
309
+ # Compute QKV with bias
310
+ if self.q_bias is not None:
311
+ qkv_bias = torch.cat(
312
+ (self.q_bias,
313
+ torch.zeros_like(self.v_bias, requires_grad=False),
314
+ self.v_bias))
315
+ qkv = F.linear(x, self.qkv.weight, qkv_bias)
316
+ else:
317
+ qkv = self.qkv(x)
318
+
319
+ qkv = qkv.reshape(B_, N, 3, self.num_heads, C // self.num_heads)
320
+ qkv = qkv.permute(2, 0, 3, 1, 4)
321
+ q, k, v = qkv.unbind(0)
322
+
323
+ # Cosine attention
324
+ attn = F.normalize(q, dim=-1) @ F.normalize(k, dim=-1).transpose(-2, -1)
325
+ logit_scale = torch.clamp(
326
+ self.logit_scale, max=math.log(1.0 / 0.01)
327
+ ).exp()
328
+ attn = attn * logit_scale
329
+
330
+ # Log-CPB relative position bias (supports dynamic window sizes)
331
+ relative_position_bias = self._compute_position_bias(N)
332
+ attn = attn + relative_position_bias.unsqueeze(0)
333
+
334
+ if mask is not None:
335
+ nW = mask.shape[0]
336
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N)
337
+ attn = attn + mask.unsqueeze(1).unsqueeze(0)
338
+ attn = attn.view(-1, self.num_heads, N, N)
339
+
340
+ attn = self.softmax(attn)
341
+ attn = self.attn_drop(attn)
342
+
343
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
344
+ x = self.proj(x)
345
+ x = self.proj_drop(x)
346
+ return x
347
+
348
+
349
+ class ShiftWindowMSA(nn.Module):
350
+ """Shifted Window Multi-head Self-Attention.
351
+
352
+ Args:
353
+ embed_dims (int): Number of input channels.
354
+ num_heads (int): Number of attention heads.
355
+ window_size (int): Window size.
356
+ shift_size (int): Shift size for SW-MSA. Default: 0.
357
+ attn_drop (float): Attention dropout rate. Default: 0.0.
358
+ proj_drop (float): Projection dropout rate. Default: 0.0.
359
+ drop_path (float): Drop path rate. Default: 0.0.
360
+ pad_small_map (bool): Pad small feature maps to window size. Default: False.
361
+ pretrained_window_size (int): Pretrained window size. Default: 0.
362
+ """
363
+
364
+ def __init__(
365
+ self,
366
+ embed_dims: int,
367
+ num_heads: int,
368
+ window_size: int,
369
+ shift_size: int = 0,
370
+ attn_drop: float = 0.0,
371
+ proj_drop: float = 0.0,
372
+ drop_path: float = 0.0,
373
+ pad_small_map: bool = False,
374
+ pretrained_window_size: int = 0,
375
+ ):
376
+ super().__init__()
377
+ self.window_size = window_size
378
+ self.shift_size = shift_size
379
+ self.pad_small_map = pad_small_map
380
+
381
+ self.w_msa = WindowMSAV2(
382
+ embed_dims=embed_dims,
383
+ num_heads=num_heads,
384
+ window_size=to_2tuple(window_size),
385
+ pretrained_window_size=to_2tuple(pretrained_window_size),
386
+ attn_drop=attn_drop,
387
+ proj_drop=proj_drop,
388
+ )
389
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
390
+
391
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
392
+ B, L, C = x.shape
393
+ H, W = hw_shape
394
+ assert L == H * W, f"Input length {L} != H*W ({H}*{W})"
395
+
396
+ x = x.view(B, H, W, C)
397
+
398
+ window_size = self.window_size
399
+ shift_size = self.shift_size
400
+
401
+ # Pad or shrink window
402
+ if self.pad_small_map:
403
+ pad_r = (window_size - W % window_size) % window_size
404
+ pad_b = (window_size - H % window_size) % window_size
405
+ x = F.pad(x, (0, 0, 0, pad_r, 0, pad_b))
406
+ _, Hp, Wp, _ = x.shape
407
+ else:
408
+ Hp, Wp = H, W
409
+ if window_size > Hp:
410
+ window_size = Hp
411
+ shift_size = 0
412
+ if window_size > Wp:
413
+ window_size = Wp
414
+ shift_size = 0
415
+
416
+ # Compute attention mask for SW-MSA
417
+ attn_mask = self._compute_attn_mask(Hp, Wp, window_size, shift_size, x.device)
418
+
419
+ # Cyclic shift
420
+ if shift_size > 0:
421
+ x = torch.roll(x, shifts=(-shift_size, -shift_size), dims=(1, 2))
422
+
423
+ # Partition windows
424
+ x_windows = self._window_partition(x, window_size)
425
+ # (num_windows*B, window_size*window_size, C)
426
+
427
+ # W-MSA/SW-MSA
428
+ attn_windows = self.w_msa(x_windows, mask=attn_mask)
429
+
430
+ # Merge windows
431
+ x = self._window_reverse(attn_windows, window_size, Hp, Wp)
432
+
433
+ # Reverse cyclic shift
434
+ if shift_size > 0:
435
+ x = torch.roll(x, shifts=(shift_size, shift_size), dims=(1, 2))
436
+
437
+ if self.pad_small_map and (pad_r > 0 or pad_b > 0):
438
+ x = x[:, :H, :W, :].contiguous()
439
+
440
+ x = x.view(B, H * W, C)
441
+ x = self.drop_path(x)
442
+ return x
443
+
444
+ @staticmethod
445
+ def _window_partition(x: torch.Tensor, window_size: int) -> torch.Tensor:
446
+ """Partition into non-overlapping windows."""
447
+ B, H, W, C = x.shape
448
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
449
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous()
450
+ windows = windows.view(-1, window_size * window_size, C)
451
+ return windows
452
+
453
+ @staticmethod
454
+ def _window_reverse(windows: torch.Tensor, window_size: int, H: int, W: int) -> torch.Tensor:
455
+ """Reverse window partition."""
456
+ B_nW = windows.shape[0]
457
+ nH = H // window_size
458
+ nW = W // window_size
459
+ B = B_nW // (nH * nW)
460
+ x = windows.view(B, nH, nW, window_size, window_size, -1)
461
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous()
462
+ x = x.view(B, H, W, -1)
463
+ return x
464
+
465
+ @staticmethod
466
+ def _compute_attn_mask(H, W, window_size, shift_size, device):
467
+ """Compute attention mask for shifted window attention."""
468
+ if shift_size <= 0:
469
+ return None
470
+ img_mask = torch.zeros((1, H, W, 1), device=device)
471
+ h_slices = (
472
+ slice(0, -window_size),
473
+ slice(-window_size, -shift_size),
474
+ slice(-shift_size, None),
475
+ )
476
+ w_slices = (
477
+ slice(0, -window_size),
478
+ slice(-window_size, -shift_size),
479
+ slice(-shift_size, None),
480
+ )
481
+ cnt = 0
482
+ for h in h_slices:
483
+ for w in w_slices:
484
+ img_mask[:, h, w, :] = cnt
485
+ cnt += 1
486
+
487
+ # Partition mask
488
+ mask_windows = img_mask.view(
489
+ 1, H // window_size, window_size, W // window_size, window_size, 1
490
+ )
491
+ mask_windows = mask_windows.permute(0, 1, 3, 2, 4, 5).contiguous()
492
+ mask_windows = mask_windows.view(-1, window_size * window_size)
493
+
494
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
495
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, -100.0)
496
+ attn_mask = attn_mask.masked_fill(attn_mask == 0, 0.0)
497
+ return attn_mask
498
+
499
+
500
+ class PatchMerging(nn.Module):
501
+ """Patch Merging Layer for downsampling (2x).
502
+
503
+ Args:
504
+ in_channels (int): Input channels.
505
+ out_channels (int): Output channels.
506
+ norm_layer (type): Normalization layer. Default: nn.LayerNorm.
507
+ is_post_norm (bool): Apply norm after linear. Default: True.
508
+ """
509
+
510
+ def __init__(
511
+ self,
512
+ in_channels: int,
513
+ out_channels: int,
514
+ norm_layer: type = nn.LayerNorm,
515
+ is_post_norm: bool = True,
516
+ ):
517
+ super().__init__()
518
+ self.in_channels = in_channels
519
+ self.out_channels = out_channels
520
+ self.is_post_norm = is_post_norm
521
+ self.reduction = nn.Linear(4 * in_channels, out_channels, bias=False)
522
+ if is_post_norm:
523
+ self.norm = norm_layer(out_channels)
524
+ else:
525
+ self.norm = norm_layer(4 * in_channels)
526
+
527
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> Tuple[torch.Tensor, Tuple[int, int]]:
528
+ B, L, C = x.shape
529
+ H, W = hw_shape
530
+ assert L == H * W
531
+
532
+ x = x.view(B, H, W, C)
533
+
534
+ # Pad if needed
535
+ pad_h = H % 2
536
+ pad_w = W % 2
537
+ if pad_h or pad_w:
538
+ x = F.pad(x, (0, 0, 0, pad_w, 0, pad_h))
539
+
540
+ x0 = x[:, 0::2, 0::2, :]
541
+ x1 = x[:, 1::2, 0::2, :]
542
+ x2 = x[:, 0::2, 1::2, :]
543
+ x3 = x[:, 1::2, 1::2, :]
544
+ x = torch.cat([x0, x1, x2, x3], dim=-1)
545
+
546
+ out_h = (H + pad_h) // 2
547
+ out_w = (W + pad_w) // 2
548
+ x = x.view(B, out_h * out_w, 4 * C)
549
+
550
+ if self.is_post_norm:
551
+ x = self.reduction(x)
552
+ x = self.norm(x)
553
+ else:
554
+ x = self.norm(x)
555
+ x = self.reduction(x)
556
+
557
+ return x, (out_h, out_w)
skysense-vit-large-s1/pipeline_skysense.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Custom HuggingFace pipeline for SkySense feature extraction."""
2
+
3
+ from typing import Any, Dict, Optional, Union
4
+
5
+ import numpy as np
6
+ import torch
7
+ from transformers import Pipeline
8
+
9
+
10
+ class SkySenseFeatureExtractionPipeline(Pipeline):
11
+ """Pipeline for SkySense backbone feature extraction.
12
+
13
+ Accepts remote-sensing tensors with arbitrary channel counts
14
+ (e.g. 3-band RGB, 10-band Sentinel-2, 2-band Sentinel-1).
15
+ """
16
+
17
+ def _sanitize_parameters(
18
+ self,
19
+ output_hidden_states=None,
20
+ **kwargs,
21
+ ):
22
+ preprocess_params = {}
23
+ forward_params = {}
24
+ postprocess_params = {}
25
+
26
+ if output_hidden_states is not None:
27
+ forward_params["output_hidden_states"] = output_hidden_states
28
+
29
+ return preprocess_params, forward_params, postprocess_params
30
+
31
+ def preprocess(self, pixel_values: Any, **kwargs) -> Dict[str, torch.Tensor]:
32
+ if isinstance(pixel_values, dict):
33
+ pixel_values = pixel_values.get("pixel_values", pixel_values)
34
+
35
+ if isinstance(pixel_values, np.ndarray):
36
+ pixel_values = torch.from_numpy(pixel_values).float()
37
+ elif isinstance(pixel_values, torch.Tensor):
38
+ pixel_values = pixel_values.float()
39
+ else:
40
+ raise TypeError(
41
+ f"Expected torch.Tensor or numpy.ndarray, got {type(pixel_values)}"
42
+ )
43
+
44
+ if pixel_values.ndim == 3:
45
+ pixel_values = pixel_values.unsqueeze(0)
46
+
47
+ return {"pixel_values": pixel_values}
48
+
49
+ def _forward(self, model_inputs: Dict[str, torch.Tensor], **kwargs) -> Dict[str, Any]:
50
+ with torch.no_grad():
51
+ outputs = self.model(
52
+ pixel_values=model_inputs["pixel_values"],
53
+ output_hidden_states=kwargs.get("output_hidden_states", False),
54
+ return_dict=True,
55
+ )
56
+ return {"outputs": outputs}
57
+
58
+ def postprocess(
59
+ self,
60
+ model_outputs: Dict[str, Any],
61
+ **kwargs,
62
+ ) -> Dict[str, Any]:
63
+ outputs = model_outputs["outputs"]
64
+ result: Dict[str, Union[torch.Tensor, tuple]] = {
65
+ "last_hidden_state": outputs.last_hidden_state,
66
+ }
67
+ if getattr(outputs, "hidden_states", None) is not None:
68
+ result["hidden_states"] = outputs.hidden_states
69
+ return result
skysense-vit-large-s2/config.json ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "return_dict": true,
3
+ "output_hidden_states": false,
4
+ "dtype": "float32",
5
+ "chunk_size_feed_forward": 0,
6
+ "is_encoder_decoder": false,
7
+ "architectures": [
8
+ "SkySenseViTModel"
9
+ ],
10
+ "id2label": {
11
+ "0": "LABEL_0",
12
+ "1": "LABEL_1"
13
+ },
14
+ "label2id": {
15
+ "LABEL_0": 0,
16
+ "LABEL_1": 1
17
+ },
18
+ "problem_type": null,
19
+ "_name_or_path": "",
20
+ "transformers_version": "5.0.0",
21
+ "img_size": 64,
22
+ "patch_size": 4,
23
+ "in_channels": 10,
24
+ "embed_dims": 1024,
25
+ "num_layers": 24,
26
+ "num_heads": 16,
27
+ "mlp_ratio": 4,
28
+ "out_indices": [
29
+ -1
30
+ ],
31
+ "qkv_bias": true,
32
+ "drop_rate": 0.0,
33
+ "attn_drop_rate": 0.0,
34
+ "drop_path_rate": 0.3,
35
+ "with_cls_token": true,
36
+ "output_cls_token": false,
37
+ "patch_norm": false,
38
+ "final_norm": false,
39
+ "with_cp": false,
40
+ "model_type": "skysense_vit",
41
+ "output_attentions": false,
42
+ "auto_map": {
43
+ "AutoConfig": "configuration_skysense.SkySenseViTConfig",
44
+ "AutoModel": "modeling_skysense_vit.SkySenseViTModel"
45
+ },
46
+ "custom_pipelines": {
47
+ "skysense-feature-extraction": {
48
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
49
+ "pt": [
50
+ "AutoModel"
51
+ ]
52
+ },
53
+ "image-feature-extraction": {
54
+ "impl": "pipeline_skysense.SkySenseFeatureExtractionPipeline",
55
+ "pt": [
56
+ "AutoModel"
57
+ ]
58
+ }
59
+ }
60
+ }
skysense-vit-large-s2/configuration_skysense.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration classes for SkySense models."""
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class SkySenseSwinV2Config(PretrainedConfig):
7
+ """Configuration class for SkySense Swin Transformer V2 backbone.
8
+
9
+ This model handles high-resolution optical imagery (RGB/RGBNIR).
10
+
11
+ Args:
12
+ arch (str): Architecture variant. One of 'tiny', 'small', 'base',
13
+ 'large', 'huge', 'giant'. Default: 'huge'.
14
+ img_size (int): Input image size. Default: 224.
15
+ patch_size (int): Patch size. Default: 4.
16
+ in_channels (int): Number of input channels. Default: 3.
17
+ window_size (int or list): Window size for each stage. Default: 8.
18
+ drop_rate (float): Dropout rate after embedding. Default: 0.0.
19
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1.
20
+ out_indices (list): Output indices from stages. Default: [3].
21
+ use_abs_pos_embed (bool): Use absolute position embedding. Default: False.
22
+ with_cp (bool): Use gradient checkpointing. Default: False.
23
+ pad_small_map (bool): Pad small maps to window size. Default: False.
24
+ pretrained_window_sizes (list): Pretrained window sizes. Default: [0, 0, 0, 0].
25
+ is_post_norm_downsample (bool): Use post-norm in downsample. Default: True.
26
+ """
27
+
28
+ model_type = "skysense_swinv2"
29
+
30
+ arch_zoo = {
31
+ 'tiny': {'embed_dims': 96, 'depths': [2, 2, 6, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
32
+ 'small': {'embed_dims': 96, 'depths': [2, 2, 18, 2], 'num_heads': [3, 6, 12, 24], 'extra_norm_every_n_blocks': 0},
33
+ 'base': {'embed_dims': 128, 'depths': [2, 2, 18, 2], 'num_heads': [4, 8, 16, 32], 'extra_norm_every_n_blocks': 0},
34
+ 'large': {'embed_dims': 192, 'depths': [2, 2, 18, 2], 'num_heads': [6, 12, 24, 48], 'extra_norm_every_n_blocks': 0},
35
+ 'huge': {'embed_dims': 352, 'depths': [2, 2, 18, 2], 'num_heads': [8, 16, 32, 64], 'extra_norm_every_n_blocks': 6},
36
+ 'giant': {'embed_dims': 512, 'depths': [2, 2, 42, 4], 'num_heads': [16, 32, 64, 128], 'extra_norm_every_n_blocks': 6},
37
+ }
38
+
39
+ def __init__(
40
+ self,
41
+ arch="huge",
42
+ img_size=224,
43
+ patch_size=4,
44
+ in_channels=3,
45
+ window_size=8,
46
+ drop_rate=0.0,
47
+ drop_path_rate=0.1,
48
+ out_indices=(3,),
49
+ use_abs_pos_embed=False,
50
+ with_cp=False,
51
+ pad_small_map=False,
52
+ pretrained_window_sizes=(0, 0, 0, 0),
53
+ is_post_norm_downsample=True,
54
+ **kwargs,
55
+ ):
56
+ super().__init__(**kwargs)
57
+
58
+ if isinstance(arch, str):
59
+ arch = arch.lower()
60
+ if arch not in self.arch_zoo:
61
+ raise ValueError(f"Unknown arch '{arch}'. Choose from {list(self.arch_zoo.keys())}")
62
+ arch_settings = self.arch_zoo[arch]
63
+ else:
64
+ arch_settings = arch
65
+
66
+ self.arch = arch
67
+ self.embed_dims = arch_settings['embed_dims']
68
+ self.depths = arch_settings['depths']
69
+ self.num_heads = arch_settings['num_heads']
70
+ self.extra_norm_every_n_blocks = arch_settings['extra_norm_every_n_blocks']
71
+
72
+ self.img_size = img_size
73
+ self.patch_size = patch_size
74
+ self.in_channels = in_channels
75
+ self.window_size = window_size
76
+ self.drop_rate = drop_rate
77
+ self.drop_path_rate = drop_path_rate
78
+ self.out_indices = list(out_indices)
79
+ self.use_abs_pos_embed = use_abs_pos_embed
80
+ self.with_cp = with_cp
81
+ self.pad_small_map = pad_small_map
82
+ self.pretrained_window_sizes = list(pretrained_window_sizes)
83
+ self.is_post_norm_downsample = is_post_norm_downsample
84
+
85
+
86
+ class SkySenseViTConfig(PretrainedConfig):
87
+ """Configuration class for SkySense Vision Transformer backbone.
88
+
89
+ This model handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
90
+
91
+ Args:
92
+ img_size (int): Input image size. Default: 64.
93
+ patch_size (int): Patch size. Default: 4.
94
+ in_channels (int): Number of input channels.
95
+ 10 for Sentinel-2, 2 for Sentinel-1. Default: 10.
96
+ embed_dims (int): Embedding dimension. Default: 1024.
97
+ num_layers (int): Number of transformer layers. Default: 24.
98
+ num_heads (int): Number of attention heads. Default: 16.
99
+ mlp_ratio (int): MLP hidden dim ratio. Default: 4.
100
+ out_indices (list): Output indices. Default: [-1].
101
+ qkv_bias (bool): QKV bias. Default: True.
102
+ drop_rate (float): Dropout rate. Default: 0.0.
103
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
104
+ drop_path_rate (float): Stochastic depth rate. Default: 0.3.
105
+ with_cls_token (bool): Use CLS token. Default: True.
106
+ output_cls_token (bool): Output CLS token. Default: False.
107
+ patch_norm (bool): Norm in patch embed. Default: False.
108
+ final_norm (bool): Final layer norm. Default: False.
109
+ with_cp (bool): Use gradient checkpointing. Default: False.
110
+ """
111
+
112
+ model_type = "skysense_vit"
113
+
114
+ def __init__(
115
+ self,
116
+ img_size=64,
117
+ patch_size=4,
118
+ in_channels=10,
119
+ embed_dims=1024,
120
+ num_layers=24,
121
+ num_heads=16,
122
+ mlp_ratio=4,
123
+ out_indices=(-1,),
124
+ qkv_bias=True,
125
+ drop_rate=0.0,
126
+ attn_drop_rate=0.0,
127
+ drop_path_rate=0.3,
128
+ with_cls_token=True,
129
+ output_cls_token=False,
130
+ patch_norm=False,
131
+ final_norm=False,
132
+ with_cp=False,
133
+ **kwargs,
134
+ ):
135
+ super().__init__(**kwargs)
136
+ self.img_size = img_size
137
+ self.patch_size = patch_size
138
+ self.in_channels = in_channels
139
+ self.embed_dims = embed_dims
140
+ self.num_layers = num_layers
141
+ self.num_heads = num_heads
142
+ self.mlp_ratio = mlp_ratio
143
+ self.out_indices = list(out_indices)
144
+ self.qkv_bias = qkv_bias
145
+ self.drop_rate = drop_rate
146
+ self.attn_drop_rate = attn_drop_rate
147
+ self.drop_path_rate = drop_path_rate
148
+ self.with_cls_token = with_cls_token
149
+ self.output_cls_token = output_cls_token
150
+ self.patch_norm = patch_norm
151
+ self.final_norm = final_norm
152
+ self.with_cp = with_cp
skysense-vit-large-s2/conversion_manifest.json ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_checkpoint": "/exstorage/czy/models/raw/skysense_model_backbone_s2.pth",
3
+ "modality": "s2",
4
+ "model_class": "SkySenseViTModel",
5
+ "num_tensors": 292,
6
+ "missing_keys": [],
7
+ "unexpected_keys": [],
8
+ "tensor_names": [
9
+ "cls_token",
10
+ "layers.0.attn.in_proj_bias",
11
+ "layers.0.attn.in_proj_weight",
12
+ "layers.0.attn.out_proj.bias",
13
+ "layers.0.attn.out_proj.weight",
14
+ "layers.0.ffn.layers.0.bias",
15
+ "layers.0.ffn.layers.0.weight",
16
+ "layers.0.ffn.layers.3.bias",
17
+ "layers.0.ffn.layers.3.weight",
18
+ "layers.0.norm1.bias",
19
+ "layers.0.norm1.weight",
20
+ "layers.0.norm2.bias",
21
+ "layers.0.norm2.weight",
22
+ "layers.1.attn.in_proj_bias",
23
+ "layers.1.attn.in_proj_weight",
24
+ "layers.1.attn.out_proj.bias",
25
+ "layers.1.attn.out_proj.weight",
26
+ "layers.1.ffn.layers.0.bias",
27
+ "layers.1.ffn.layers.0.weight",
28
+ "layers.1.ffn.layers.3.bias",
29
+ "layers.1.ffn.layers.3.weight",
30
+ "layers.1.norm1.bias",
31
+ "layers.1.norm1.weight",
32
+ "layers.1.norm2.bias",
33
+ "layers.1.norm2.weight",
34
+ "layers.10.attn.in_proj_bias",
35
+ "layers.10.attn.in_proj_weight",
36
+ "layers.10.attn.out_proj.bias",
37
+ "layers.10.attn.out_proj.weight",
38
+ "layers.10.ffn.layers.0.bias",
39
+ "layers.10.ffn.layers.0.weight",
40
+ "layers.10.ffn.layers.3.bias",
41
+ "layers.10.ffn.layers.3.weight",
42
+ "layers.10.norm1.bias",
43
+ "layers.10.norm1.weight",
44
+ "layers.10.norm2.bias",
45
+ "layers.10.norm2.weight",
46
+ "layers.11.attn.in_proj_bias",
47
+ "layers.11.attn.in_proj_weight",
48
+ "layers.11.attn.out_proj.bias",
49
+ "layers.11.attn.out_proj.weight",
50
+ "layers.11.ffn.layers.0.bias",
51
+ "layers.11.ffn.layers.0.weight",
52
+ "layers.11.ffn.layers.3.bias",
53
+ "layers.11.ffn.layers.3.weight",
54
+ "layers.11.norm1.bias",
55
+ "layers.11.norm1.weight",
56
+ "layers.11.norm2.bias",
57
+ "layers.11.norm2.weight",
58
+ "layers.12.attn.in_proj_bias",
59
+ "layers.12.attn.in_proj_weight",
60
+ "layers.12.attn.out_proj.bias",
61
+ "layers.12.attn.out_proj.weight",
62
+ "layers.12.ffn.layers.0.bias",
63
+ "layers.12.ffn.layers.0.weight",
64
+ "layers.12.ffn.layers.3.bias",
65
+ "layers.12.ffn.layers.3.weight",
66
+ "layers.12.norm1.bias",
67
+ "layers.12.norm1.weight",
68
+ "layers.12.norm2.bias",
69
+ "layers.12.norm2.weight",
70
+ "layers.13.attn.in_proj_bias",
71
+ "layers.13.attn.in_proj_weight",
72
+ "layers.13.attn.out_proj.bias",
73
+ "layers.13.attn.out_proj.weight",
74
+ "layers.13.ffn.layers.0.bias",
75
+ "layers.13.ffn.layers.0.weight",
76
+ "layers.13.ffn.layers.3.bias",
77
+ "layers.13.ffn.layers.3.weight",
78
+ "layers.13.norm1.bias",
79
+ "layers.13.norm1.weight",
80
+ "layers.13.norm2.bias",
81
+ "layers.13.norm2.weight",
82
+ "layers.14.attn.in_proj_bias",
83
+ "layers.14.attn.in_proj_weight",
84
+ "layers.14.attn.out_proj.bias",
85
+ "layers.14.attn.out_proj.weight",
86
+ "layers.14.ffn.layers.0.bias",
87
+ "layers.14.ffn.layers.0.weight",
88
+ "layers.14.ffn.layers.3.bias",
89
+ "layers.14.ffn.layers.3.weight",
90
+ "layers.14.norm1.bias",
91
+ "layers.14.norm1.weight",
92
+ "layers.14.norm2.bias",
93
+ "layers.14.norm2.weight",
94
+ "layers.15.attn.in_proj_bias",
95
+ "layers.15.attn.in_proj_weight",
96
+ "layers.15.attn.out_proj.bias",
97
+ "layers.15.attn.out_proj.weight",
98
+ "layers.15.ffn.layers.0.bias",
99
+ "layers.15.ffn.layers.0.weight",
100
+ "layers.15.ffn.layers.3.bias",
101
+ "layers.15.ffn.layers.3.weight",
102
+ "layers.15.norm1.bias",
103
+ "layers.15.norm1.weight",
104
+ "layers.15.norm2.bias",
105
+ "layers.15.norm2.weight",
106
+ "layers.16.attn.in_proj_bias",
107
+ "layers.16.attn.in_proj_weight",
108
+ "layers.16.attn.out_proj.bias",
109
+ "layers.16.attn.out_proj.weight",
110
+ "layers.16.ffn.layers.0.bias",
111
+ "layers.16.ffn.layers.0.weight",
112
+ "layers.16.ffn.layers.3.bias",
113
+ "layers.16.ffn.layers.3.weight",
114
+ "layers.16.norm1.bias",
115
+ "layers.16.norm1.weight",
116
+ "layers.16.norm2.bias",
117
+ "layers.16.norm2.weight",
118
+ "layers.17.attn.in_proj_bias",
119
+ "layers.17.attn.in_proj_weight",
120
+ "layers.17.attn.out_proj.bias",
121
+ "layers.17.attn.out_proj.weight",
122
+ "layers.17.ffn.layers.0.bias",
123
+ "layers.17.ffn.layers.0.weight",
124
+ "layers.17.ffn.layers.3.bias",
125
+ "layers.17.ffn.layers.3.weight",
126
+ "layers.17.norm1.bias",
127
+ "layers.17.norm1.weight",
128
+ "layers.17.norm2.bias",
129
+ "layers.17.norm2.weight",
130
+ "layers.18.attn.in_proj_bias",
131
+ "layers.18.attn.in_proj_weight",
132
+ "layers.18.attn.out_proj.bias",
133
+ "layers.18.attn.out_proj.weight",
134
+ "layers.18.ffn.layers.0.bias",
135
+ "layers.18.ffn.layers.0.weight",
136
+ "layers.18.ffn.layers.3.bias",
137
+ "layers.18.ffn.layers.3.weight",
138
+ "layers.18.norm1.bias",
139
+ "layers.18.norm1.weight",
140
+ "layers.18.norm2.bias",
141
+ "layers.18.norm2.weight",
142
+ "layers.19.attn.in_proj_bias",
143
+ "layers.19.attn.in_proj_weight",
144
+ "layers.19.attn.out_proj.bias",
145
+ "layers.19.attn.out_proj.weight",
146
+ "layers.19.ffn.layers.0.bias",
147
+ "layers.19.ffn.layers.0.weight",
148
+ "layers.19.ffn.layers.3.bias",
149
+ "layers.19.ffn.layers.3.weight",
150
+ "layers.19.norm1.bias",
151
+ "layers.19.norm1.weight",
152
+ "layers.19.norm2.bias",
153
+ "layers.19.norm2.weight",
154
+ "layers.2.attn.in_proj_bias",
155
+ "layers.2.attn.in_proj_weight",
156
+ "layers.2.attn.out_proj.bias",
157
+ "layers.2.attn.out_proj.weight",
158
+ "layers.2.ffn.layers.0.bias",
159
+ "layers.2.ffn.layers.0.weight",
160
+ "layers.2.ffn.layers.3.bias",
161
+ "layers.2.ffn.layers.3.weight",
162
+ "layers.2.norm1.bias",
163
+ "layers.2.norm1.weight",
164
+ "layers.2.norm2.bias",
165
+ "layers.2.norm2.weight",
166
+ "layers.20.attn.in_proj_bias",
167
+ "layers.20.attn.in_proj_weight",
168
+ "layers.20.attn.out_proj.bias",
169
+ "layers.20.attn.out_proj.weight",
170
+ "layers.20.ffn.layers.0.bias",
171
+ "layers.20.ffn.layers.0.weight",
172
+ "layers.20.ffn.layers.3.bias",
173
+ "layers.20.ffn.layers.3.weight",
174
+ "layers.20.norm1.bias",
175
+ "layers.20.norm1.weight",
176
+ "layers.20.norm2.bias",
177
+ "layers.20.norm2.weight",
178
+ "layers.21.attn.in_proj_bias",
179
+ "layers.21.attn.in_proj_weight",
180
+ "layers.21.attn.out_proj.bias",
181
+ "layers.21.attn.out_proj.weight",
182
+ "layers.21.ffn.layers.0.bias",
183
+ "layers.21.ffn.layers.0.weight",
184
+ "layers.21.ffn.layers.3.bias",
185
+ "layers.21.ffn.layers.3.weight",
186
+ "layers.21.norm1.bias",
187
+ "layers.21.norm1.weight",
188
+ "layers.21.norm2.bias",
189
+ "layers.21.norm2.weight",
190
+ "layers.22.attn.in_proj_bias",
191
+ "layers.22.attn.in_proj_weight",
192
+ "layers.22.attn.out_proj.bias",
193
+ "layers.22.attn.out_proj.weight",
194
+ "layers.22.ffn.layers.0.bias",
195
+ "layers.22.ffn.layers.0.weight",
196
+ "layers.22.ffn.layers.3.bias",
197
+ "layers.22.ffn.layers.3.weight",
198
+ "layers.22.norm1.bias",
199
+ "layers.22.norm1.weight",
200
+ "layers.22.norm2.bias",
201
+ "layers.22.norm2.weight",
202
+ "layers.23.attn.in_proj_bias",
203
+ "layers.23.attn.in_proj_weight",
204
+ "layers.23.attn.out_proj.bias",
205
+ "layers.23.attn.out_proj.weight",
206
+ "layers.23.ffn.layers.0.bias",
207
+ "layers.23.ffn.layers.0.weight",
208
+ "layers.23.ffn.layers.3.bias",
209
+ "layers.23.ffn.layers.3.weight",
210
+ "layers.23.norm1.bias",
211
+ "layers.23.norm1.weight",
212
+ "layers.23.norm2.bias",
213
+ "layers.23.norm2.weight",
214
+ "layers.3.attn.in_proj_bias",
215
+ "layers.3.attn.in_proj_weight",
216
+ "layers.3.attn.out_proj.bias",
217
+ "layers.3.attn.out_proj.weight",
218
+ "layers.3.ffn.layers.0.bias",
219
+ "layers.3.ffn.layers.0.weight",
220
+ "layers.3.ffn.layers.3.bias",
221
+ "layers.3.ffn.layers.3.weight",
222
+ "layers.3.norm1.bias",
223
+ "layers.3.norm1.weight",
224
+ "layers.3.norm2.bias",
225
+ "layers.3.norm2.weight",
226
+ "layers.4.attn.in_proj_bias",
227
+ "layers.4.attn.in_proj_weight",
228
+ "layers.4.attn.out_proj.bias",
229
+ "layers.4.attn.out_proj.weight",
230
+ "layers.4.ffn.layers.0.bias",
231
+ "layers.4.ffn.layers.0.weight",
232
+ "layers.4.ffn.layers.3.bias",
233
+ "layers.4.ffn.layers.3.weight",
234
+ "layers.4.norm1.bias",
235
+ "layers.4.norm1.weight",
236
+ "layers.4.norm2.bias",
237
+ "layers.4.norm2.weight",
238
+ "layers.5.attn.in_proj_bias",
239
+ "layers.5.attn.in_proj_weight",
240
+ "layers.5.attn.out_proj.bias",
241
+ "layers.5.attn.out_proj.weight",
242
+ "layers.5.ffn.layers.0.bias",
243
+ "layers.5.ffn.layers.0.weight",
244
+ "layers.5.ffn.layers.3.bias",
245
+ "layers.5.ffn.layers.3.weight",
246
+ "layers.5.norm1.bias",
247
+ "layers.5.norm1.weight",
248
+ "layers.5.norm2.bias",
249
+ "layers.5.norm2.weight",
250
+ "layers.6.attn.in_proj_bias",
251
+ "layers.6.attn.in_proj_weight",
252
+ "layers.6.attn.out_proj.bias",
253
+ "layers.6.attn.out_proj.weight",
254
+ "layers.6.ffn.layers.0.bias",
255
+ "layers.6.ffn.layers.0.weight",
256
+ "layers.6.ffn.layers.3.bias",
257
+ "layers.6.ffn.layers.3.weight",
258
+ "layers.6.norm1.bias",
259
+ "layers.6.norm1.weight",
260
+ "layers.6.norm2.bias",
261
+ "layers.6.norm2.weight",
262
+ "layers.7.attn.in_proj_bias",
263
+ "layers.7.attn.in_proj_weight",
264
+ "layers.7.attn.out_proj.bias",
265
+ "layers.7.attn.out_proj.weight",
266
+ "layers.7.ffn.layers.0.bias",
267
+ "layers.7.ffn.layers.0.weight",
268
+ "layers.7.ffn.layers.3.bias",
269
+ "layers.7.ffn.layers.3.weight",
270
+ "layers.7.norm1.bias",
271
+ "layers.7.norm1.weight",
272
+ "layers.7.norm2.bias",
273
+ "layers.7.norm2.weight",
274
+ "layers.8.attn.in_proj_bias",
275
+ "layers.8.attn.in_proj_weight",
276
+ "layers.8.attn.out_proj.bias",
277
+ "layers.8.attn.out_proj.weight",
278
+ "layers.8.ffn.layers.0.bias",
279
+ "layers.8.ffn.layers.0.weight",
280
+ "layers.8.ffn.layers.3.bias",
281
+ "layers.8.ffn.layers.3.weight",
282
+ "layers.8.norm1.bias",
283
+ "layers.8.norm1.weight",
284
+ "layers.8.norm2.bias",
285
+ "layers.8.norm2.weight",
286
+ "layers.9.attn.in_proj_bias",
287
+ "layers.9.attn.in_proj_weight",
288
+ "layers.9.attn.out_proj.bias",
289
+ "layers.9.attn.out_proj.weight",
290
+ "layers.9.ffn.layers.0.bias",
291
+ "layers.9.ffn.layers.0.weight",
292
+ "layers.9.ffn.layers.3.bias",
293
+ "layers.9.ffn.layers.3.weight",
294
+ "layers.9.norm1.bias",
295
+ "layers.9.norm1.weight",
296
+ "layers.9.norm2.bias",
297
+ "layers.9.norm2.weight",
298
+ "patch_embed.projection.bias",
299
+ "patch_embed.projection.weight",
300
+ "pos_embed"
301
+ ]
302
+ }
skysense-vit-large-s2/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ca5a973898aa1378040e17447434c368853c0c3d05c9cd96a0a7c4ae7a3e4272
3
+ size 1210982440
skysense-vit-large-s2/modeling_skysense_swinv2.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Swin Transformer V2 backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles high-resolution optical imagery (RGB/RGBNIR).
4
+ """
5
+
6
+ from copy import deepcopy
7
+ from typing import Optional, Sequence, Tuple, Union
8
+
9
+ import numpy as np
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseSwinV2Config
17
+ from .modeling_utils import (
18
+ DropPath,
19
+ FFN,
20
+ PatchEmbed,
21
+ PatchMerging,
22
+ ShiftWindowMSA,
23
+ to_2tuple,
24
+ )
25
+
26
+
27
+ class SwinBlockV2(nn.Module):
28
+ """Swin Transformer V2 block with post-normalization.
29
+
30
+ Args:
31
+ embed_dims (int): Number of input channels.
32
+ num_heads (int): Number of attention heads.
33
+ window_size (int): Window size. Default: 8.
34
+ shift (bool): Shift the attention window. Default: False.
35
+ extra_norm (bool): Extra norm at end of block. Default: False.
36
+ ffn_ratio (float): FFN expansion ratio. Default: 4.0.
37
+ drop_path (float): Drop path rate. Default: 0.0.
38
+ pad_small_map (bool): Pad small maps. Default: False.
39
+ with_cp (bool): Gradient checkpointing. Default: False.
40
+ pretrained_window_size (int): Pretrained window size. Default: 0.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ embed_dims: int,
46
+ num_heads: int,
47
+ window_size: int = 8,
48
+ shift: bool = False,
49
+ extra_norm: bool = False,
50
+ ffn_ratio: float = 4.0,
51
+ drop_path: float = 0.0,
52
+ pad_small_map: bool = False,
53
+ with_cp: bool = False,
54
+ pretrained_window_size: int = 0,
55
+ ):
56
+ super().__init__()
57
+ self.with_cp = with_cp
58
+ self.extra_norm = extra_norm
59
+
60
+ self.attn = ShiftWindowMSA(
61
+ embed_dims=embed_dims,
62
+ num_heads=num_heads,
63
+ window_size=window_size,
64
+ shift_size=window_size // 2 if shift else 0,
65
+ drop_path=drop_path,
66
+ pad_small_map=pad_small_map,
67
+ pretrained_window_size=pretrained_window_size,
68
+ )
69
+ self.norm1 = nn.LayerNorm(embed_dims)
70
+
71
+ self.ffn = FFN(
72
+ embed_dims=embed_dims,
73
+ feedforward_channels=int(embed_dims * ffn_ratio),
74
+ num_fcs=2,
75
+ drop_path=drop_path,
76
+ act_layer=nn.GELU,
77
+ add_identity=False,
78
+ )
79
+ self.norm2 = nn.LayerNorm(embed_dims)
80
+
81
+ if self.extra_norm:
82
+ self.norm3 = nn.LayerNorm(embed_dims)
83
+
84
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
85
+ def _inner_forward(x):
86
+ # Post normalization
87
+ identity = x
88
+ x = self.attn(x, hw_shape)
89
+ x = self.norm1(x)
90
+ x = x + identity
91
+
92
+ identity = x
93
+ x = self.ffn(x)
94
+ x = self.norm2(x)
95
+ x = x + identity
96
+
97
+ if self.extra_norm:
98
+ x = self.norm3(x)
99
+ return x
100
+
101
+ if self.with_cp and x.requires_grad:
102
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
103
+ else:
104
+ x = _inner_forward(x)
105
+ return x
106
+
107
+
108
+ class SwinBlockV2Sequence(nn.Module):
109
+ """Sequence of Swin Transformer V2 blocks with optional downsample.
110
+
111
+ Args:
112
+ embed_dims (int): Number of input channels.
113
+ depth (int): Number of blocks.
114
+ num_heads (int): Number of attention heads.
115
+ window_size (int): Window size. Default: 8.
116
+ downsample (bool): Apply downsample. Default: False.
117
+ drop_paths (list or float): Drop path rates. Default: 0.0.
118
+ with_cp (bool): Gradient checkpointing. Default: False.
119
+ pad_small_map (bool): Pad small maps. Default: False.
120
+ extra_norm_every_n_blocks (int): Extra norm interval. Default: 0.
121
+ pretrained_window_size (int): Pretrained window size. Default: 0.
122
+ is_post_norm_downsample (bool): Post-norm in downsample. Default: True.
123
+ """
124
+
125
+ def __init__(
126
+ self,
127
+ embed_dims: int,
128
+ depth: int,
129
+ num_heads: int,
130
+ window_size: int = 8,
131
+ downsample: bool = False,
132
+ drop_paths: Union[Sequence[float], float] = 0.0,
133
+ with_cp: bool = False,
134
+ pad_small_map: bool = False,
135
+ extra_norm_every_n_blocks: int = 0,
136
+ pretrained_window_size: int = 0,
137
+ is_post_norm_downsample: bool = True,
138
+ ):
139
+ super().__init__()
140
+
141
+ if not isinstance(drop_paths, Sequence):
142
+ drop_paths = [drop_paths] * depth
143
+
144
+ if downsample:
145
+ self.out_channels = 2 * embed_dims
146
+ self.downsample = PatchMerging(
147
+ in_channels=embed_dims,
148
+ out_channels=self.out_channels,
149
+ is_post_norm=is_post_norm_downsample,
150
+ )
151
+ else:
152
+ self.out_channels = embed_dims
153
+ self.downsample = None
154
+
155
+ self.blocks = nn.ModuleList()
156
+ for i in range(depth):
157
+ extra_norm = (
158
+ extra_norm_every_n_blocks > 0
159
+ and (i + 1) % extra_norm_every_n_blocks == 0
160
+ )
161
+ block = SwinBlockV2(
162
+ embed_dims=self.out_channels,
163
+ num_heads=num_heads,
164
+ window_size=window_size,
165
+ shift=(i % 2 == 1),
166
+ extra_norm=extra_norm,
167
+ drop_path=drop_paths[i],
168
+ with_cp=with_cp,
169
+ pad_small_map=pad_small_map,
170
+ pretrained_window_size=pretrained_window_size,
171
+ )
172
+ self.blocks.append(block)
173
+
174
+ def forward(
175
+ self, x: torch.Tensor, in_shape: Tuple[int, int]
176
+ ) -> Tuple[torch.Tensor, Tuple[int, int]]:
177
+ if self.downsample is not None:
178
+ x, out_shape = self.downsample(x, in_shape)
179
+ else:
180
+ out_shape = in_shape
181
+
182
+ for block in self.blocks:
183
+ x = block(x, out_shape)
184
+
185
+ return x, out_shape
186
+
187
+
188
+ class SkySenseSwinV2PreTrainedModel(PreTrainedModel):
189
+ """Base class for SkySense Swin Transformer V2 models."""
190
+
191
+ config_class = SkySenseSwinV2Config
192
+ base_model_prefix = "skysense_swinv2"
193
+ supports_gradient_checkpointing = True
194
+
195
+ def _init_weights(self, module):
196
+ """Initialize weights."""
197
+ if isinstance(module, nn.Linear):
198
+ nn.init.trunc_normal_(module.weight, std=0.02)
199
+ if module.bias is not None:
200
+ nn.init.zeros_(module.bias)
201
+ elif isinstance(module, nn.LayerNorm):
202
+ nn.init.ones_(module.weight)
203
+ nn.init.zeros_(module.bias)
204
+ elif isinstance(module, nn.Conv2d):
205
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
206
+ if module.bias is not None:
207
+ nn.init.zeros_(module.bias)
208
+
209
+
210
+ class SkySenseSwinV2Model(SkySenseSwinV2PreTrainedModel):
211
+ """SkySense Swin Transformer V2 backbone.
212
+
213
+ A pure PyTorch + HuggingFace implementation of the Swin Transformer V2
214
+ used in SkySense for high-resolution optical remote sensing imagery.
215
+ """
216
+
217
+ def __init__(self, config: SkySenseSwinV2Config):
218
+ super().__init__(config)
219
+
220
+ self.num_layers = len(config.depths)
221
+ self.out_indices = config.out_indices
222
+
223
+ # Window sizes per stage
224
+ if isinstance(config.window_size, int):
225
+ window_sizes = [config.window_size] * self.num_layers
226
+ else:
227
+ window_sizes = list(config.window_size)
228
+
229
+ # Patch embedding
230
+ self.patch_embed = PatchEmbed(
231
+ in_channels=config.in_channels,
232
+ embed_dims=config.embed_dims,
233
+ kernel_size=config.patch_size,
234
+ stride=config.patch_size,
235
+ norm_layer=nn.LayerNorm,
236
+ input_size=config.img_size,
237
+ )
238
+
239
+ # Optional absolute position embedding
240
+ self.use_abs_pos_embed = config.use_abs_pos_embed
241
+ if self.use_abs_pos_embed:
242
+ patch_resolution = self.patch_embed.init_out_size
243
+ num_patches = patch_resolution[0] * patch_resolution[1]
244
+ self.absolute_pos_embed = nn.Parameter(
245
+ torch.zeros(1, num_patches, config.embed_dims)
246
+ )
247
+
248
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
249
+
250
+ # Stochastic depth decay (computed without tensors for meta-device compat)
251
+ total_depth = sum(config.depths)
252
+ if total_depth > 1:
253
+ dpr = [config.drop_path_rate * i / (total_depth - 1) for i in range(total_depth)]
254
+ else:
255
+ dpr = [0.0]
256
+
257
+ # Build stages
258
+ self.stages = nn.ModuleList()
259
+ embed_dims_list = [config.embed_dims]
260
+ for i, (depth, num_heads) in enumerate(
261
+ zip(config.depths, config.num_heads)
262
+ ):
263
+ stage = SwinBlockV2Sequence(
264
+ embed_dims=embed_dims_list[-1],
265
+ depth=depth,
266
+ num_heads=num_heads,
267
+ window_size=window_sizes[i],
268
+ downsample=(i > 0),
269
+ drop_paths=dpr[:depth],
270
+ with_cp=config.with_cp,
271
+ pad_small_map=config.pad_small_map,
272
+ extra_norm_every_n_blocks=config.extra_norm_every_n_blocks,
273
+ pretrained_window_size=config.pretrained_window_sizes[i],
274
+ is_post_norm_downsample=config.is_post_norm_downsample,
275
+ )
276
+ self.stages.append(stage)
277
+ dpr = dpr[depth:]
278
+ embed_dims_list.append(stage.out_channels)
279
+
280
+ # Output norms
281
+ for i in self.out_indices:
282
+ norm = nn.LayerNorm(embed_dims_list[i + 1])
283
+ self.add_module(f"norm{i}", norm)
284
+
285
+ self.post_init()
286
+
287
+ def _delete_reinit_params(self, state_dict, prefix, *args, **kwargs):
288
+ """Delete relative_position_index and relative_coords_table from state_dict."""
289
+ keys_to_delete = [
290
+ k for k in state_dict.keys()
291
+ if 'relative_position_index' in k or 'relative_coords_table' in k
292
+ ]
293
+ for k in keys_to_delete:
294
+ del state_dict[k]
295
+
296
+ def forward(
297
+ self,
298
+ pixel_values: torch.Tensor,
299
+ output_hidden_states: Optional[bool] = None,
300
+ return_dict: Optional[bool] = None,
301
+ ) -> Union[Tuple, BaseModelOutput]:
302
+ """
303
+ Args:
304
+ pixel_values: (B, C, H, W) input image tensor.
305
+ output_hidden_states: Whether to return all hidden states.
306
+ return_dict: Whether to return a BaseModelOutput.
307
+
308
+ Returns:
309
+ BaseModelOutput or tuple of feature maps.
310
+ """
311
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
312
+
313
+ x, hw_shape = self.patch_embed(pixel_values)
314
+
315
+ if self.use_abs_pos_embed:
316
+ x = x + self.absolute_pos_embed
317
+ x = self.drop_after_pos(x)
318
+
319
+ all_hidden_states = () if output_hidden_states else None
320
+ feature_maps = []
321
+
322
+ for i, stage in enumerate(self.stages):
323
+ x, hw_shape = stage(x, hw_shape)
324
+ if output_hidden_states:
325
+ all_hidden_states = all_hidden_states + (x,)
326
+ if i in self.out_indices:
327
+ norm_layer = getattr(self, f"norm{i}")
328
+ out = norm_layer(x)
329
+ out = out.view(
330
+ -1, *hw_shape, stage.out_channels
331
+ ).permute(0, 3, 1, 2).contiguous()
332
+ feature_maps.append(out)
333
+
334
+ if not return_dict:
335
+ return tuple(feature_maps)
336
+
337
+ return BaseModelOutput(
338
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
339
+ hidden_states=all_hidden_states,
340
+ )
skysense-vit-large-s2/modeling_skysense_vit.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense Vision Transformer backbone (pure PyTorch + HuggingFace).
2
+
3
+ Handles Sentinel-2 multispectral and Sentinel-1 SAR imagery.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple, Union
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ import torch.utils.checkpoint as cp
13
+ from transformers import PreTrainedModel
14
+ from transformers.modeling_outputs import BaseModelOutput
15
+
16
+ from .configuration_skysense import SkySenseViTConfig
17
+ from .modeling_utils import DropPath, FFN, PatchEmbed, to_2tuple
18
+
19
+
20
+ class TransformerEncoderLayer(nn.Module):
21
+ """Single encoder layer for the Vision Transformer.
22
+
23
+ Args:
24
+ embed_dims (int): Embedding dimension.
25
+ num_heads (int): Number of attention heads.
26
+ feedforward_channels (int): FFN hidden dimension.
27
+ drop_rate (float): Dropout rate. Default: 0.0.
28
+ attn_drop_rate (float): Attention dropout rate. Default: 0.0.
29
+ drop_path_rate (float): Drop path rate. Default: 0.0.
30
+ num_fcs (int): Number of FC layers in FFN. Default: 2.
31
+ qkv_bias (bool): QKV bias. Default: True.
32
+ with_cp (bool): Gradient checkpointing. Default: False.
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ embed_dims: int,
38
+ num_heads: int,
39
+ feedforward_channels: int,
40
+ drop_rate: float = 0.0,
41
+ attn_drop_rate: float = 0.0,
42
+ drop_path_rate: float = 0.0,
43
+ num_fcs: int = 2,
44
+ qkv_bias: bool = True,
45
+ with_cp: bool = False,
46
+ ):
47
+ super().__init__()
48
+ self.with_cp = with_cp
49
+
50
+ self.norm1 = nn.LayerNorm(embed_dims)
51
+ self.attn = nn.MultiheadAttention(
52
+ embed_dim=embed_dims,
53
+ num_heads=num_heads,
54
+ dropout=attn_drop_rate,
55
+ bias=qkv_bias,
56
+ batch_first=True,
57
+ )
58
+ self.proj_drop = nn.Dropout(drop_rate)
59
+
60
+ self.norm2 = nn.LayerNorm(embed_dims)
61
+ self.ffn = FFN(
62
+ embed_dims=embed_dims,
63
+ feedforward_channels=feedforward_channels,
64
+ num_fcs=num_fcs,
65
+ ffn_drop=drop_rate,
66
+ drop_path=drop_path_rate,
67
+ act_layer=nn.GELU,
68
+ add_identity=True,
69
+ )
70
+
71
+ self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
72
+
73
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
74
+ def _inner_forward(x):
75
+ # Pre-norm attention with residual
76
+ residual = x
77
+ x_norm = self.norm1(x)
78
+ attn_out, _ = self.attn(x_norm, x_norm, x_norm)
79
+ attn_out = self.proj_drop(attn_out)
80
+ x = residual + self.drop_path(attn_out)
81
+
82
+ # Pre-norm FFN with residual (FFN handles its own residual)
83
+ x = self.ffn(self.norm2(x), identity=x)
84
+ return x
85
+
86
+ if self.with_cp and x.requires_grad:
87
+ x = cp.checkpoint(_inner_forward, x, use_reentrant=False)
88
+ else:
89
+ x = _inner_forward(x)
90
+ return x
91
+
92
+
93
+ class SkySenseViTPreTrainedModel(PreTrainedModel):
94
+ """Base class for SkySense Vision Transformer models."""
95
+
96
+ config_class = SkySenseViTConfig
97
+ base_model_prefix = "skysense_vit"
98
+ supports_gradient_checkpointing = True
99
+
100
+ def _init_weights(self, module):
101
+ """Initialize weights following jax_impl."""
102
+ if isinstance(module, nn.Linear):
103
+ nn.init.trunc_normal_(module.weight, std=0.02)
104
+ if module.bias is not None:
105
+ nn.init.zeros_(module.bias)
106
+ elif isinstance(module, (nn.LayerNorm, nn.GroupNorm)):
107
+ nn.init.ones_(module.weight)
108
+ nn.init.zeros_(module.bias)
109
+ elif isinstance(module, nn.Conv2d):
110
+ nn.init.kaiming_normal_(module.weight, mode='fan_in')
111
+ if module.bias is not None:
112
+ nn.init.zeros_(module.bias)
113
+
114
+
115
+ class SkySenseViTModel(SkySenseViTPreTrainedModel):
116
+ """SkySense Vision Transformer backbone.
117
+
118
+ A pure PyTorch + HuggingFace implementation of the ViT used in SkySense
119
+ for Sentinel-2 multispectral and Sentinel-1 SAR imagery.
120
+ """
121
+
122
+ def __init__(self, config: SkySenseViTConfig):
123
+ super().__init__(config)
124
+
125
+ img_size = to_2tuple(config.img_size)
126
+ self.img_size = img_size
127
+ self.patch_size = config.patch_size
128
+ self.with_cls_token = config.with_cls_token
129
+ self.output_cls_token = config.output_cls_token
130
+ self.interpolate_mode = 'bicubic'
131
+
132
+ # Patch embedding
133
+ self.patch_embed = PatchEmbed(
134
+ in_channels=config.in_channels,
135
+ embed_dims=config.embed_dims,
136
+ kernel_size=config.patch_size,
137
+ stride=config.patch_size,
138
+ norm_layer=nn.LayerNorm if config.patch_norm else None,
139
+ )
140
+
141
+ num_patches = (img_size[0] // config.patch_size) * (
142
+ img_size[1] // config.patch_size
143
+ )
144
+
145
+ self.cls_token = nn.Parameter(torch.zeros(1, 1, config.embed_dims))
146
+ self.pos_embed = nn.Parameter(
147
+ torch.zeros(1, num_patches + 1, config.embed_dims)
148
+ )
149
+ self.drop_after_pos = nn.Dropout(p=config.drop_rate)
150
+
151
+ # Resolve out_indices
152
+ out_indices = list(config.out_indices)
153
+ resolved = []
154
+ for idx in out_indices:
155
+ if idx < 0:
156
+ idx = config.num_layers + idx
157
+ resolved.append(idx)
158
+ self.out_indices = resolved
159
+
160
+ # Stochastic depth (computed without tensors for meta-device compat)
161
+ num_layers = config.num_layers
162
+ if num_layers > 1:
163
+ dpr = [config.drop_path_rate * i / (num_layers - 1) for i in range(num_layers)]
164
+ else:
165
+ dpr = [0.0]
166
+
167
+ # Transformer encoder layers
168
+ self.layers = nn.ModuleList()
169
+ for i in range(config.num_layers):
170
+ self.layers.append(
171
+ TransformerEncoderLayer(
172
+ embed_dims=config.embed_dims,
173
+ num_heads=config.num_heads,
174
+ feedforward_channels=config.mlp_ratio * config.embed_dims,
175
+ attn_drop_rate=config.attn_drop_rate,
176
+ drop_rate=config.drop_rate,
177
+ drop_path_rate=dpr[i],
178
+ num_fcs=2,
179
+ qkv_bias=config.qkv_bias,
180
+ with_cp=config.with_cp,
181
+ )
182
+ )
183
+
184
+ # Final norm
185
+ self.final_norm = config.final_norm
186
+ if config.final_norm:
187
+ self.norm = nn.LayerNorm(config.embed_dims)
188
+
189
+ self.post_init()
190
+
191
+ @staticmethod
192
+ def resize_pos_embed(pos_embed, input_shape, pos_shape, mode='bicubic'):
193
+ """Resize position embeddings via interpolation.
194
+
195
+ Args:
196
+ pos_embed (torch.Tensor): Position embedding of shape (B, L, C),
197
+ where L = 1 (cls_token) + pos_h * pos_w.
198
+ input_shape (tuple[int, int]): Target spatial size (H, W).
199
+ pos_shape (tuple[int, int]): Original spatial size (pos_h, pos_w).
200
+ mode (str): Interpolation mode. Default: 'bicubic'.
201
+
202
+ Returns:
203
+ torch.Tensor: Resized position embedding of shape (B, 1 + H*W, C).
204
+ """
205
+ assert pos_embed.ndim == 3
206
+ pos_h, pos_w = pos_shape
207
+ cls_token_weight = pos_embed[:, 0:1]
208
+ pos_embed_weight = pos_embed[:, (-1 * pos_h * pos_w):]
209
+ pos_embed_weight = pos_embed_weight.reshape(
210
+ 1, pos_h, pos_w, pos_embed.shape[2]
211
+ ).permute(0, 3, 1, 2)
212
+ pos_embed_weight = F.interpolate(
213
+ pos_embed_weight,
214
+ size=input_shape,
215
+ align_corners=False,
216
+ mode=mode,
217
+ )
218
+ pos_embed_weight = torch.flatten(pos_embed_weight, 2).transpose(1, 2)
219
+ pos_embed = torch.cat((cls_token_weight, pos_embed_weight), dim=1)
220
+ return pos_embed
221
+
222
+ def _pos_embedding(self, patched_img, hw_shape, pos_embed):
223
+ """Apply position embedding with optional interpolation."""
224
+ x_len, pos_len = patched_img.shape[1], pos_embed.shape[1]
225
+ if x_len != pos_len:
226
+ pos_h = self.img_size[0] // self.patch_size
227
+ pos_w = self.img_size[1] // self.patch_size
228
+ pos_embed = self.resize_pos_embed(
229
+ pos_embed, hw_shape, (pos_h, pos_w), self.interpolate_mode
230
+ )
231
+ return self.drop_after_pos(patched_img + pos_embed)
232
+
233
+ def forward(
234
+ self,
235
+ pixel_values: torch.Tensor,
236
+ output_hidden_states: Optional[bool] = None,
237
+ return_dict: Optional[bool] = None,
238
+ ) -> Union[Tuple, BaseModelOutput]:
239
+ """
240
+ Args:
241
+ pixel_values: (B, C, H, W) input tensor.
242
+ output_hidden_states: Return all hidden states.
243
+ return_dict: Return BaseModelOutput.
244
+
245
+ Returns:
246
+ Feature maps or BaseModelOutput.
247
+ """
248
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
249
+ B = pixel_values.shape[0]
250
+
251
+ x, hw_shape = self.patch_embed(pixel_values)
252
+
253
+ # Prepend CLS token
254
+ cls_tokens = self.cls_token.expand(B, -1, -1)
255
+ x = torch.cat((cls_tokens, x), dim=1)
256
+ x = self._pos_embedding(x, hw_shape, self.pos_embed)
257
+
258
+ if not self.with_cls_token:
259
+ x = x[:, 1:]
260
+
261
+ all_hidden_states = () if output_hidden_states else None
262
+ feature_maps = []
263
+
264
+ for i, layer in enumerate(self.layers):
265
+ x = layer(x)
266
+
267
+ if i == len(self.layers) - 1 and self.final_norm:
268
+ x = self.norm(x)
269
+
270
+ if output_hidden_states:
271
+ all_hidden_states = all_hidden_states + (x,)
272
+
273
+ if i in self.out_indices:
274
+ if self.with_cls_token:
275
+ out = x[:, 1:]
276
+ else:
277
+ out = x
278
+ B_, _, C = out.shape
279
+ out = out.reshape(
280
+ B_, hw_shape[0], hw_shape[1], C
281
+ ).permute(0, 3, 1, 2).contiguous()
282
+ if self.output_cls_token:
283
+ out = [out, x[:, 0]]
284
+ feature_maps.append(out)
285
+
286
+ if not return_dict:
287
+ return tuple(feature_maps)
288
+
289
+ return BaseModelOutput(
290
+ last_hidden_state=feature_maps[-1] if feature_maps else x,
291
+ hidden_states=all_hidden_states,
292
+ )
skysense-vit-large-s2/modeling_utils.py ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SkySense: Pure PyTorch + HuggingFace Transformers implementation.
2
+
3
+ Shared utility modules used across SkySense model implementations.
4
+ """
5
+
6
+ import math
7
+ from typing import Optional, Tuple
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+
13
+
14
+ def to_2tuple(x):
15
+ """Convert to a 2-tuple."""
16
+ if isinstance(x, (list, tuple)):
17
+ return tuple(x)
18
+ return (x, x)
19
+
20
+
21
+ class DropPath(nn.Module):
22
+ """Drop paths (stochastic depth) per sample.
23
+
24
+ Args:
25
+ drop_prob (float): Probability of dropping a path. Default: 0.0.
26
+ """
27
+
28
+ def __init__(self, drop_prob: float = 0.0):
29
+ super().__init__()
30
+ self.drop_prob = drop_prob
31
+
32
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
33
+ if self.drop_prob == 0.0 or not self.training:
34
+ return x
35
+ keep_prob = 1 - self.drop_prob
36
+ shape = (x.shape[0],) + (1,) * (x.ndim - 1)
37
+ random_tensor = torch.rand(shape, dtype=x.dtype, device=x.device)
38
+ random_tensor = torch.floor(random_tensor + keep_prob)
39
+ output = x / keep_prob * random_tensor
40
+ return output
41
+
42
+
43
+ class PatchEmbed(nn.Module):
44
+ """Image to Patch Embedding using Conv2d.
45
+
46
+ Args:
47
+ in_channels (int): Number of input channels. Default: 3.
48
+ embed_dims (int): Embedding dimension. Default: 96.
49
+ kernel_size (int): Kernel size of the projection. Default: 4.
50
+ stride (int): Stride of the projection. Default: 4.
51
+ padding (int): Padding of the projection. Default: 0.
52
+ norm_layer (nn.Module or None): Normalization layer. Default: nn.LayerNorm.
53
+ input_size (int or tuple or None): Input resolution for calculating output size.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ in_channels: int = 3,
59
+ embed_dims: int = 96,
60
+ kernel_size: int = 4,
61
+ stride: int = 4,
62
+ padding: int = 0,
63
+ norm_layer: Optional[type] = nn.LayerNorm,
64
+ input_size: Optional[int] = None,
65
+ ):
66
+ super().__init__()
67
+ self.projection = nn.Conv2d(
68
+ in_channels, embed_dims,
69
+ kernel_size=kernel_size, stride=stride, padding=padding,
70
+ )
71
+ self.norm = norm_layer(embed_dims) if norm_layer else nn.Identity()
72
+
73
+ # Compute init output size if input_size is given
74
+ if input_size is not None:
75
+ input_size = to_2tuple(input_size)
76
+ self.init_out_size = (
77
+ (input_size[0] - kernel_size + 2 * padding) // stride + 1,
78
+ (input_size[1] - kernel_size + 2 * padding) // stride + 1,
79
+ )
80
+ else:
81
+ self.init_out_size = None
82
+
83
+ def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, Tuple[int, int]]:
84
+ x = self.projection(x) # (B, C, H, W)
85
+ out_size = (x.shape[2], x.shape[3])
86
+ x = x.flatten(2).transpose(1, 2) # (B, H*W, C)
87
+ x = self.norm(x)
88
+ return x, out_size
89
+
90
+
91
+ class FFN(nn.Module):
92
+ """Feed-Forward Network.
93
+
94
+ Args:
95
+ embed_dims (int): Input dimension.
96
+ feedforward_channels (int): Hidden dimension.
97
+ num_fcs (int): Number of FC layers. Default: 2.
98
+ ffn_drop (float): Dropout rate. Default: 0.0.
99
+ drop_path (float): Drop path rate. Default: 0.0.
100
+ act_layer (nn.Module): Activation layer class. Default: nn.GELU.
101
+ add_identity (bool): Whether to add identity connection. Default: True.
102
+ """
103
+
104
+ def __init__(
105
+ self,
106
+ embed_dims: int,
107
+ feedforward_channels: int,
108
+ num_fcs: int = 2,
109
+ ffn_drop: float = 0.0,
110
+ drop_path: float = 0.0,
111
+ act_layer: type = nn.GELU,
112
+ add_identity: bool = True,
113
+ ):
114
+ super().__init__()
115
+ assert num_fcs >= 2, f"num_fcs must be >= 2, got {num_fcs}"
116
+ self.embed_dims = embed_dims
117
+ self.feedforward_channels = feedforward_channels
118
+ self.add_identity = add_identity
119
+
120
+ layers = []
121
+ in_channels = embed_dims
122
+ for i in range(num_fcs - 1):
123
+ layers.append(nn.Linear(in_channels, feedforward_channels))
124
+ layers.append(act_layer())
125
+ layers.append(nn.Dropout(ffn_drop))
126
+ in_channels = feedforward_channels
127
+ layers.append(nn.Linear(feedforward_channels, embed_dims))
128
+ layers.append(nn.Dropout(ffn_drop))
129
+ self.layers = nn.Sequential(*layers)
130
+
131
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
132
+
133
+ def forward(self, x: torch.Tensor, identity: Optional[torch.Tensor] = None) -> torch.Tensor:
134
+ out = self.layers(x)
135
+ out = self.drop_path(out)
136
+ if self.add_identity:
137
+ if identity is None:
138
+ identity = x
139
+ out = out + identity
140
+ return out
141
+
142
+
143
+ class WindowMSAV2(nn.Module):
144
+ """Window-based Multi-head Self-Attention for Swin Transformer V2.
145
+
146
+ Uses cosine attention and log-spaced continuous position bias (log-CPB).
147
+
148
+ Args:
149
+ embed_dims (int): Number of input channels.
150
+ num_heads (int): Number of attention heads.
151
+ window_size (tuple[int]): Window size (Wh, Ww).
152
+ pretrained_window_size (tuple[int]): Pretrained window size for CPB. Default: (0, 0).
153
+ qkv_bias (bool): If True, add learnable bias to q, k, v. Default: True.
154
+ attn_drop (float): Attention dropout rate. Default: 0.0.
155
+ proj_drop (float): Output projection dropout rate. Default: 0.0.
156
+ """
157
+
158
+ def __init__(
159
+ self,
160
+ embed_dims: int,
161
+ num_heads: int,
162
+ window_size: Tuple[int, int],
163
+ pretrained_window_size: Tuple[int, int] = (0, 0),
164
+ qkv_bias: bool = True,
165
+ attn_drop: float = 0.0,
166
+ proj_drop: float = 0.0,
167
+ ):
168
+ super().__init__()
169
+ self.embed_dims = embed_dims
170
+ self.num_heads = num_heads
171
+ self.window_size = window_size
172
+ self.pretrained_window_size = pretrained_window_size
173
+
174
+ self.logit_scale = nn.Parameter(
175
+ torch.log(10 * torch.ones((num_heads, 1, 1))))
176
+
177
+ # MLP for continuous relative position bias (log-CPB)
178
+ self.cpb_mlp = nn.Sequential(
179
+ nn.Linear(2, 512, bias=True),
180
+ nn.ReLU(inplace=True),
181
+ nn.Linear(512, num_heads, bias=False),
182
+ )
183
+
184
+ # Build relative coords table
185
+ self._build_relative_coords_table()
186
+ # Build relative position index
187
+ self._build_relative_position_index()
188
+
189
+ self.qkv = nn.Linear(embed_dims, embed_dims * 3, bias=False)
190
+ if qkv_bias:
191
+ self.q_bias = nn.Parameter(torch.zeros(embed_dims))
192
+ self.v_bias = nn.Parameter(torch.zeros(embed_dims))
193
+ else:
194
+ self.q_bias = None
195
+ self.v_bias = None
196
+
197
+ self.attn_drop = nn.Dropout(attn_drop)
198
+ self.proj = nn.Linear(embed_dims, embed_dims)
199
+ self.proj_drop = nn.Dropout(proj_drop)
200
+ self.softmax = nn.Softmax(dim=-1)
201
+
202
+ def _build_relative_coords_table(self):
203
+ """Build the relative coordinates table for log-CPB."""
204
+ Wh, Ww = self.window_size
205
+ # Table of relative coordinates
206
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32)
207
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32)
208
+ coords_table = torch.stack(
209
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
210
+ ).flatten(1).transpose(0, 1).unsqueeze(0) # (1, (2Wh-1)*(2Ww-1), 2)
211
+
212
+ # Normalize to [-1, 1] and apply log-scale
213
+ if self.pretrained_window_size[0] > 0:
214
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
215
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
216
+ else:
217
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
218
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
219
+ coords_table *= 8 # normalize to -8, 8
220
+ coords_table = (
221
+ torch.sign(coords_table)
222
+ * torch.log2(torch.abs(coords_table) + 1.0)
223
+ / math.log2(8)
224
+ )
225
+ self.register_buffer("relative_coords_table", coords_table)
226
+
227
+ def _build_relative_position_index(self):
228
+ """Build the pairwise relative position index for each window token."""
229
+ Wh, Ww = self.window_size
230
+ coords_h = torch.arange(Wh)
231
+ coords_w = torch.arange(Ww)
232
+ coords = torch.stack(torch.meshgrid(coords_h, coords_w, indexing='ij'))
233
+ coords_flatten = coords.view(2, -1)
234
+
235
+ relative_coords = (
236
+ coords_flatten[:, :, None] - coords_flatten[:, None, :]
237
+ ) # (2, Wh*Ww, Wh*Ww)
238
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous()
239
+ relative_coords[:, :, 0] += Wh - 1
240
+ relative_coords[:, :, 1] += Ww - 1
241
+ relative_coords[:, :, 0] *= 2 * Ww - 1
242
+ relative_position_index = relative_coords.sum(-1) # (Wh*Ww, Wh*Ww)
243
+ self.register_buffer("relative_position_index", relative_position_index)
244
+
245
+ def _compute_position_bias(self, N):
246
+ """Compute relative position bias, supporting dynamic window sizes.
247
+
248
+ The log-CPB (Continuous Position Bias) MLP can generalize to any window
249
+ size by computing bias from normalized relative coordinates.
250
+ """
251
+ init_N = self.window_size[0] * self.window_size[1]
252
+ if N == init_N:
253
+ # Use pre-built tables
254
+ relative_position_bias_table = self.cpb_mlp(
255
+ self.relative_coords_table
256
+ ).view(-1, self.num_heads)
257
+ relative_position_bias = relative_position_bias_table[
258
+ self.relative_position_index.view(-1)
259
+ ].view(N, N, -1)
260
+ else:
261
+ # Dynamic: compute for actual window size on-the-fly
262
+ Wh = Ww = int(math.sqrt(N))
263
+ coords_h = torch.arange(-(Wh - 1), Wh, dtype=torch.float32, device=self.logit_scale.device)
264
+ coords_w = torch.arange(-(Ww - 1), Ww, dtype=torch.float32, device=self.logit_scale.device)
265
+ coords_table = torch.stack(
266
+ torch.meshgrid(coords_h, coords_w, indexing='ij')
267
+ ).flatten(1).transpose(0, 1).unsqueeze(0)
268
+ if self.pretrained_window_size[0] > 0:
269
+ coords_table[:, :, 0] /= (self.pretrained_window_size[0] - 1)
270
+ coords_table[:, :, 1] /= (self.pretrained_window_size[1] - 1)
271
+ else:
272
+ coords_table[:, :, 0] /= max(Wh - 1, 1)
273
+ coords_table[:, :, 1] /= max(Ww - 1, 1)
274
+ coords_table *= 8
275
+ coords_table = (
276
+ torch.sign(coords_table)
277
+ * torch.log2(torch.abs(coords_table) + 1.0)
278
+ / math.log2(8)
279
+ )
280
+ # Build position index for actual window size
281
+ ch = torch.arange(Wh, device=self.logit_scale.device)
282
+ cw = torch.arange(Ww, device=self.logit_scale.device)
283
+ coords = torch.stack(torch.meshgrid(ch, cw, indexing='ij'))
284
+ coords_flat = coords.view(2, -1)
285
+ rel = coords_flat[:, :, None] - coords_flat[:, None, :]
286
+ rel = rel.permute(1, 2, 0).contiguous()
287
+ rel[:, :, 0] += Wh - 1
288
+ rel[:, :, 1] += Ww - 1
289
+ rel[:, :, 0] *= 2 * Ww - 1
290
+ pos_index = rel.sum(-1)
291
+
292
+ bias_table = self.cpb_mlp(coords_table).view(-1, self.num_heads)
293
+ relative_position_bias = bias_table[
294
+ pos_index.view(-1)
295
+ ].view(N, N, -1)
296
+
297
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()
298
+ relative_position_bias = 16 * torch.sigmoid(relative_position_bias)
299
+ return relative_position_bias
300
+
301
+ def forward(self, x: torch.Tensor, mask: Optional[torch.Tensor] = None) -> torch.Tensor:
302
+ """
303
+ Args:
304
+ x: (num_windows*B, N, C) where N = Wh*Ww
305
+ mask: (num_windows, N, N) or None
306
+ """
307
+ B_, N, C = x.shape
308
+
309
+ # Compute QKV with bias
310
+ if self.q_bias is not None:
311
+ qkv_bias = torch.cat(
312
+ (self.q_bias,
313
+ torch.zeros_like(self.v_bias, requires_grad=False),
314
+ self.v_bias))
315
+ qkv = F.linear(x, self.qkv.weight, qkv_bias)
316
+ else:
317
+ qkv = self.qkv(x)
318
+
319
+ qkv = qkv.reshape(B_, N, 3, self.num_heads, C // self.num_heads)
320
+ qkv = qkv.permute(2, 0, 3, 1, 4)
321
+ q, k, v = qkv.unbind(0)
322
+
323
+ # Cosine attention
324
+ attn = F.normalize(q, dim=-1) @ F.normalize(k, dim=-1).transpose(-2, -1)
325
+ logit_scale = torch.clamp(
326
+ self.logit_scale, max=math.log(1.0 / 0.01)
327
+ ).exp()
328
+ attn = attn * logit_scale
329
+
330
+ # Log-CPB relative position bias (supports dynamic window sizes)
331
+ relative_position_bias = self._compute_position_bias(N)
332
+ attn = attn + relative_position_bias.unsqueeze(0)
333
+
334
+ if mask is not None:
335
+ nW = mask.shape[0]
336
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N)
337
+ attn = attn + mask.unsqueeze(1).unsqueeze(0)
338
+ attn = attn.view(-1, self.num_heads, N, N)
339
+
340
+ attn = self.softmax(attn)
341
+ attn = self.attn_drop(attn)
342
+
343
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
344
+ x = self.proj(x)
345
+ x = self.proj_drop(x)
346
+ return x
347
+
348
+
349
+ class ShiftWindowMSA(nn.Module):
350
+ """Shifted Window Multi-head Self-Attention.
351
+
352
+ Args:
353
+ embed_dims (int): Number of input channels.
354
+ num_heads (int): Number of attention heads.
355
+ window_size (int): Window size.
356
+ shift_size (int): Shift size for SW-MSA. Default: 0.
357
+ attn_drop (float): Attention dropout rate. Default: 0.0.
358
+ proj_drop (float): Projection dropout rate. Default: 0.0.
359
+ drop_path (float): Drop path rate. Default: 0.0.
360
+ pad_small_map (bool): Pad small feature maps to window size. Default: False.
361
+ pretrained_window_size (int): Pretrained window size. Default: 0.
362
+ """
363
+
364
+ def __init__(
365
+ self,
366
+ embed_dims: int,
367
+ num_heads: int,
368
+ window_size: int,
369
+ shift_size: int = 0,
370
+ attn_drop: float = 0.0,
371
+ proj_drop: float = 0.0,
372
+ drop_path: float = 0.0,
373
+ pad_small_map: bool = False,
374
+ pretrained_window_size: int = 0,
375
+ ):
376
+ super().__init__()
377
+ self.window_size = window_size
378
+ self.shift_size = shift_size
379
+ self.pad_small_map = pad_small_map
380
+
381
+ self.w_msa = WindowMSAV2(
382
+ embed_dims=embed_dims,
383
+ num_heads=num_heads,
384
+ window_size=to_2tuple(window_size),
385
+ pretrained_window_size=to_2tuple(pretrained_window_size),
386
+ attn_drop=attn_drop,
387
+ proj_drop=proj_drop,
388
+ )
389
+ self.drop_path = DropPath(drop_path) if drop_path > 0.0 else nn.Identity()
390
+
391
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> torch.Tensor:
392
+ B, L, C = x.shape
393
+ H, W = hw_shape
394
+ assert L == H * W, f"Input length {L} != H*W ({H}*{W})"
395
+
396
+ x = x.view(B, H, W, C)
397
+
398
+ window_size = self.window_size
399
+ shift_size = self.shift_size
400
+
401
+ # Pad or shrink window
402
+ if self.pad_small_map:
403
+ pad_r = (window_size - W % window_size) % window_size
404
+ pad_b = (window_size - H % window_size) % window_size
405
+ x = F.pad(x, (0, 0, 0, pad_r, 0, pad_b))
406
+ _, Hp, Wp, _ = x.shape
407
+ else:
408
+ Hp, Wp = H, W
409
+ if window_size > Hp:
410
+ window_size = Hp
411
+ shift_size = 0
412
+ if window_size > Wp:
413
+ window_size = Wp
414
+ shift_size = 0
415
+
416
+ # Compute attention mask for SW-MSA
417
+ attn_mask = self._compute_attn_mask(Hp, Wp, window_size, shift_size, x.device)
418
+
419
+ # Cyclic shift
420
+ if shift_size > 0:
421
+ x = torch.roll(x, shifts=(-shift_size, -shift_size), dims=(1, 2))
422
+
423
+ # Partition windows
424
+ x_windows = self._window_partition(x, window_size)
425
+ # (num_windows*B, window_size*window_size, C)
426
+
427
+ # W-MSA/SW-MSA
428
+ attn_windows = self.w_msa(x_windows, mask=attn_mask)
429
+
430
+ # Merge windows
431
+ x = self._window_reverse(attn_windows, window_size, Hp, Wp)
432
+
433
+ # Reverse cyclic shift
434
+ if shift_size > 0:
435
+ x = torch.roll(x, shifts=(shift_size, shift_size), dims=(1, 2))
436
+
437
+ if self.pad_small_map and (pad_r > 0 or pad_b > 0):
438
+ x = x[:, :H, :W, :].contiguous()
439
+
440
+ x = x.view(B, H * W, C)
441
+ x = self.drop_path(x)
442
+ return x
443
+
444
+ @staticmethod
445
+ def _window_partition(x: torch.Tensor, window_size: int) -> torch.Tensor:
446
+ """Partition into non-overlapping windows."""
447
+ B, H, W, C = x.shape
448
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
449
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous()
450
+ windows = windows.view(-1, window_size * window_size, C)
451
+ return windows
452
+
453
+ @staticmethod
454
+ def _window_reverse(windows: torch.Tensor, window_size: int, H: int, W: int) -> torch.Tensor:
455
+ """Reverse window partition."""
456
+ B_nW = windows.shape[0]
457
+ nH = H // window_size
458
+ nW = W // window_size
459
+ B = B_nW // (nH * nW)
460
+ x = windows.view(B, nH, nW, window_size, window_size, -1)
461
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous()
462
+ x = x.view(B, H, W, -1)
463
+ return x
464
+
465
+ @staticmethod
466
+ def _compute_attn_mask(H, W, window_size, shift_size, device):
467
+ """Compute attention mask for shifted window attention."""
468
+ if shift_size <= 0:
469
+ return None
470
+ img_mask = torch.zeros((1, H, W, 1), device=device)
471
+ h_slices = (
472
+ slice(0, -window_size),
473
+ slice(-window_size, -shift_size),
474
+ slice(-shift_size, None),
475
+ )
476
+ w_slices = (
477
+ slice(0, -window_size),
478
+ slice(-window_size, -shift_size),
479
+ slice(-shift_size, None),
480
+ )
481
+ cnt = 0
482
+ for h in h_slices:
483
+ for w in w_slices:
484
+ img_mask[:, h, w, :] = cnt
485
+ cnt += 1
486
+
487
+ # Partition mask
488
+ mask_windows = img_mask.view(
489
+ 1, H // window_size, window_size, W // window_size, window_size, 1
490
+ )
491
+ mask_windows = mask_windows.permute(0, 1, 3, 2, 4, 5).contiguous()
492
+ mask_windows = mask_windows.view(-1, window_size * window_size)
493
+
494
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
495
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, -100.0)
496
+ attn_mask = attn_mask.masked_fill(attn_mask == 0, 0.0)
497
+ return attn_mask
498
+
499
+
500
+ class PatchMerging(nn.Module):
501
+ """Patch Merging Layer for downsampling (2x).
502
+
503
+ Args:
504
+ in_channels (int): Input channels.
505
+ out_channels (int): Output channels.
506
+ norm_layer (type): Normalization layer. Default: nn.LayerNorm.
507
+ is_post_norm (bool): Apply norm after linear. Default: True.
508
+ """
509
+
510
+ def __init__(
511
+ self,
512
+ in_channels: int,
513
+ out_channels: int,
514
+ norm_layer: type = nn.LayerNorm,
515
+ is_post_norm: bool = True,
516
+ ):
517
+ super().__init__()
518
+ self.in_channels = in_channels
519
+ self.out_channels = out_channels
520
+ self.is_post_norm = is_post_norm
521
+ self.reduction = nn.Linear(4 * in_channels, out_channels, bias=False)
522
+ if is_post_norm:
523
+ self.norm = norm_layer(out_channels)
524
+ else:
525
+ self.norm = norm_layer(4 * in_channels)
526
+
527
+ def forward(self, x: torch.Tensor, hw_shape: Tuple[int, int]) -> Tuple[torch.Tensor, Tuple[int, int]]:
528
+ B, L, C = x.shape
529
+ H, W = hw_shape
530
+ assert L == H * W
531
+
532
+ x = x.view(B, H, W, C)
533
+
534
+ # Pad if needed
535
+ pad_h = H % 2
536
+ pad_w = W % 2
537
+ if pad_h or pad_w:
538
+ x = F.pad(x, (0, 0, 0, pad_w, 0, pad_h))
539
+
540
+ x0 = x[:, 0::2, 0::2, :]
541
+ x1 = x[:, 1::2, 0::2, :]
542
+ x2 = x[:, 0::2, 1::2, :]
543
+ x3 = x[:, 1::2, 1::2, :]
544
+ x = torch.cat([x0, x1, x2, x3], dim=-1)
545
+
546
+ out_h = (H + pad_h) // 2
547
+ out_w = (W + pad_w) // 2
548
+ x = x.view(B, out_h * out_w, 4 * C)
549
+
550
+ if self.is_post_norm:
551
+ x = self.reduction(x)
552
+ x = self.norm(x)
553
+ else:
554
+ x = self.norm(x)
555
+ x = self.reduction(x)
556
+
557
+ return x, (out_h, out_w)
skysense-vit-large-s2/pipeline_skysense.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Custom HuggingFace pipeline for SkySense feature extraction."""
2
+
3
+ from typing import Any, Dict, Optional, Union
4
+
5
+ import numpy as np
6
+ import torch
7
+ from transformers import Pipeline
8
+
9
+
10
+ class SkySenseFeatureExtractionPipeline(Pipeline):
11
+ """Pipeline for SkySense backbone feature extraction.
12
+
13
+ Accepts remote-sensing tensors with arbitrary channel counts
14
+ (e.g. 3-band RGB, 10-band Sentinel-2, 2-band Sentinel-1).
15
+ """
16
+
17
+ def _sanitize_parameters(
18
+ self,
19
+ output_hidden_states=None,
20
+ **kwargs,
21
+ ):
22
+ preprocess_params = {}
23
+ forward_params = {}
24
+ postprocess_params = {}
25
+
26
+ if output_hidden_states is not None:
27
+ forward_params["output_hidden_states"] = output_hidden_states
28
+
29
+ return preprocess_params, forward_params, postprocess_params
30
+
31
+ def preprocess(self, pixel_values: Any, **kwargs) -> Dict[str, torch.Tensor]:
32
+ if isinstance(pixel_values, dict):
33
+ pixel_values = pixel_values.get("pixel_values", pixel_values)
34
+
35
+ if isinstance(pixel_values, np.ndarray):
36
+ pixel_values = torch.from_numpy(pixel_values).float()
37
+ elif isinstance(pixel_values, torch.Tensor):
38
+ pixel_values = pixel_values.float()
39
+ else:
40
+ raise TypeError(
41
+ f"Expected torch.Tensor or numpy.ndarray, got {type(pixel_values)}"
42
+ )
43
+
44
+ if pixel_values.ndim == 3:
45
+ pixel_values = pixel_values.unsqueeze(0)
46
+
47
+ return {"pixel_values": pixel_values}
48
+
49
+ def _forward(self, model_inputs: Dict[str, torch.Tensor], **kwargs) -> Dict[str, Any]:
50
+ with torch.no_grad():
51
+ outputs = self.model(
52
+ pixel_values=model_inputs["pixel_values"],
53
+ output_hidden_states=kwargs.get("output_hidden_states", False),
54
+ return_dict=True,
55
+ )
56
+ return {"outputs": outputs}
57
+
58
+ def postprocess(
59
+ self,
60
+ model_outputs: Dict[str, Any],
61
+ **kwargs,
62
+ ) -> Dict[str, Any]:
63
+ outputs = model_outputs["outputs"]
64
+ result: Dict[str, Union[torch.Tensor, tuple]] = {
65
+ "last_hidden_state": outputs.last_hidden_state,
66
+ }
67
+ if getattr(outputs, "hidden_states", None) is not None:
68
+ result["hidden_states"] = outputs.hidden_states
69
+ return result