Upload SkySense Transformers checkpoints
Browse files- README.md +98 -0
- skysense-swinv2-huge-rgb/config.json +75 -0
- skysense-swinv2-huge-rgb/configuration_skysense.py +152 -0
- skysense-swinv2-huge-rgb/conversion_manifest.json +488 -0
- skysense-swinv2-huge-rgb/model.safetensors +3 -0
- skysense-swinv2-huge-rgb/modeling_skysense_swinv2.py +340 -0
- skysense-swinv2-huge-rgb/modeling_skysense_vit.py +292 -0
- skysense-swinv2-huge-rgb/modeling_utils.py +557 -0
- skysense-swinv2-huge-rgb/pipeline_skysense.py +69 -0
- skysense-vit-large-s1/config.json +60 -0
- skysense-vit-large-s1/configuration_skysense.py +152 -0
- skysense-vit-large-s1/conversion_manifest.json +302 -0
- skysense-vit-large-s1/model.safetensors +3 -0
- skysense-vit-large-s1/modeling_skysense_swinv2.py +340 -0
- skysense-vit-large-s1/modeling_skysense_vit.py +292 -0
- skysense-vit-large-s1/modeling_utils.py +557 -0
- skysense-vit-large-s1/pipeline_skysense.py +69 -0
- skysense-vit-large-s2/config.json +60 -0
- skysense-vit-large-s2/configuration_skysense.py +152 -0
- skysense-vit-large-s2/conversion_manifest.json +302 -0
- skysense-vit-large-s2/model.safetensors +3 -0
- skysense-vit-large-s2/modeling_skysense_swinv2.py +340 -0
- skysense-vit-large-s2/modeling_skysense_vit.py +292 -0
- skysense-vit-large-s2/modeling_utils.py +557 -0
- skysense-vit-large-s2/pipeline_skysense.py +69 -0
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
|