tensor-ee 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tensor_ee/__init__.py +28 -0
- tensor_ee/_swin_parameters.py +304 -0
- tensor_ee/blocks/__init__.py +0 -0
- tensor_ee/blocks/raster/__init__.py +36 -0
- tensor_ee/blocks/raster/activations.py +183 -0
- tensor_ee/blocks/raster/conv.py +183 -0
- tensor_ee/blocks/raster/merge.py +66 -0
- tensor_ee/blocks/raster/outputs.py +211 -0
- tensor_ee/blocks/raster/pooling.py +182 -0
- tensor_ee/blocks/raster/resample.py +64 -0
- tensor_ee/blocks/window/__init__.py +44 -0
- tensor_ee/blocks/window/activations.py +54 -0
- tensor_ee/blocks/window/attention.py +366 -0
- tensor_ee/blocks/window/conv.py +323 -0
- tensor_ee/blocks/window/linear.py +129 -0
- tensor_ee/blocks/window/merge.py +67 -0
- tensor_ee/blocks/window/normalization.py +197 -0
- tensor_ee/blocks/window/patch.py +362 -0
- tensor_ee/blocks/window/pooling.py +275 -0
- tensor_ee/blocks/window/resample.py +286 -0
- tensor_ee/blocks/window/segformer.py +718 -0
- tensor_ee/blocks/window/swin.py +602 -0
- tensor_ee/blocks/window/swin_upernet_config.py +361 -0
- tensor_ee/blocks/window/upernet.py +1016 -0
- tensor_ee/comparison.py +213 -0
- tensor_ee/compatibility.py +180 -0
- tensor_ee/compiler.py +356 -0
- tensor_ee/converter/__init__.py +72 -0
- tensor_ee/converter/build.py +120 -0
- tensor_ee/converter/convert.py +388 -0
- tensor_ee/converter/export.py +846 -0
- tensor_ee/converter/graph.py +417 -0
- tensor_ee/converter/operations.py +790 -0
- tensor_ee/converter/plan.py +675 -0
- tensor_ee/converter/recognizers.py +1273 -0
- tensor_ee/converter/request.py +146 -0
- tensor_ee/converter/run.py +950 -0
- tensor_ee/core/__init__.py +8 -0
- tensor_ee/core/errors.py +25 -0
- tensor_ee/core/grid.py +323 -0
- tensor_ee/core/metadata.py +398 -0
- tensor_ee/core/ops.py +336 -0
- tensor_ee/core/precision.py +133 -0
- tensor_ee/core/tensor.py +129 -0
- tensor_ee/examples/__init__.py +1 -0
- tensor_ee/examples/nonwater.py +251 -0
- tensor_ee/layouts/__init__.py +17 -0
- tensor_ee/layouts/boundaries.py +103 -0
- tensor_ee/layouts/raster.py +117 -0
- tensor_ee/layouts/shift.py +226 -0
- tensor_ee/layouts/window.py +201 -0
- tensor_ee/models/__init__.py +16 -0
- tensor_ee/models/fixtures.py +119 -0
- tensor_ee/models/segformer_b0/__init__.py +9 -0
- tensor_ee/models/segformer_b0/configuration.py +209 -0
- tensor_ee/models/segformer_b0/decoder.py +130 -0
- tensor_ee/models/segformer_b0/encoder.py +90 -0
- tensor_ee/models/swin_t224/__init__.py +30 -0
- tensor_ee/models/swin_t224/configuration.py +103 -0
- tensor_ee/models/swin_t224/decoder.py +53 -0
- tensor_ee/models/swin_t224/encoder.py +50 -0
- tensor_ee/onnx_import.py +431 -0
- tensor_ee/outputs.py +16 -0
- tensor_ee/primitives.py +110 -0
- tensor_ee/receptive_field.py +257 -0
- tensor_ee/resnet_models.py +185 -0
- tensor_ee/segwater_inference.py +235 -0
- tensor_ee/segwater_preprocessing.py +182 -0
- tensor_ee/segwater_pytorch.py +249 -0
- tensor_ee/semantics.py +389 -0
- tensor_ee/smp.py +155 -0
- tensor_ee/swin.py +197 -0
- tensor_ee/swin_workflow.py +470 -0
- tensor_ee/tiling.py +287 -0
- tensor_ee/weight_assets.py +371 -0
- tensor_ee/weight_mapping.py +51 -0
- tensor_ee/weights/__init__.py +14 -0
- tensor_ee/weights/assets.py +160 -0
- tensor_ee/weights/constants.py +156 -0
- tensor_ee-0.1.0.dist-info/METADATA +172 -0
- tensor_ee-0.1.0.dist-info/RECORD +84 -0
- tensor_ee-0.1.0.dist-info/WHEEL +5 -0
- tensor_ee-0.1.0.dist-info/licenses/LICENSE +21 -0
- tensor_ee-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
"""The Swin encoder's composites in window layout: the MLP branch, the W-MSA and SW-MSA blocks,
|
|
2
|
+
the stage, the patch embedding at a configuration, the encoder grids and the encoder, with
|
|
3
|
+
their constants builders.
|
|
4
|
+
|
|
5
|
+
Moved from ``tensor_ee/models/swin_t224/encoder.py``, renamed here where the model's
|
|
6
|
+
name does not say Swin: ``BlockConstants`` -> ``SwinBlockConstants``, ``block_constants`` ->
|
|
7
|
+
``swin_block_constants``, ``mlp_branch`` -> ``swin_mlp_branch``, ``stage_blocks`` ->
|
|
8
|
+
``swin_stage_blocks``, ``merge_constants`` -> ``swin_merge_constants``,
|
|
9
|
+
``patch_embedding_constants`` -> ``swin_patch_embedding_constants``, ``patch_embedding`` ->
|
|
10
|
+
``swin_patch_embedding``, ``EncoderConstants`` -> ``SwinEncoderConstants``, ``EncoderGrids``
|
|
11
|
+
-> ``SwinEncoderGrids``, ``encoder_grids`` -> ``swin_encoder_grids`` and ``encoder`` ->
|
|
12
|
+
``swin_encoder``; ``swin_block``, ``shifted_swin_block``, ``swin_stage``, ``DIM``, ``HEADS``
|
|
13
|
+
and ``EXTENSION_MODES`` keep their names. The Swin-T224 model re-exports these objects under
|
|
14
|
+
its former names; there is one implementation.
|
|
15
|
+
|
|
16
|
+
Every tensor is in window layout: one [w^2, dim] float32 array per w x w window ([49, dim]
|
|
17
|
+
at Swin-T224's window 7), on the coarse grid of its stage. A W-MSA block is per token
|
|
18
|
+
(LayerNorm, the projections, GELU, residuals) or within one window (attention), so it runs
|
|
19
|
+
on that raster with no layout conversion; an SW-MSA block re-partitions with the exact cyclic shift
|
|
20
|
+
(``tensor_ee.layouts.shift``) and adds Swin's shifted-window mask. Patch Merging is the
|
|
21
|
+
library's ``patch_merge``. Parameters are timm state_dict names (NumPy arrays embedded
|
|
22
|
+
inline, or asset-backed ``ServerArray``s).
|
|
23
|
+
|
|
24
|
+
**Configuration.** The composites take a ``SwinUPerNetConfig`` (``swin_upernet_config``;
|
|
25
|
+
default ``SWIN_T224``): ``swin_stage_blocks``, ``swin_merge_constants``,
|
|
26
|
+
``swin_patch_embedding_constants``, ``swin_patch_embedding``, ``swin_encoder_grids`` and
|
|
27
|
+
``SwinEncoderConstants`` take it as ``config``, and ``swin_encoder`` reads it from its constants
|
|
28
|
+
and grids, refusing a pair built for different configurations. A ``SwinBlockConstants`` records
|
|
29
|
+
its window, and the blocks run at that window, with the stage's shift (w // 2) in the SW-MSA
|
|
30
|
+
blocks. Parameters whose shapes break the configuration's channel contract are refused
|
|
31
|
+
(client-side; the graph is unchanged).
|
|
32
|
+
|
|
33
|
+
**Layouts.** ``swin_block_constants`` builds every per-channel constant for its ``layout``
|
|
34
|
+
(``WINDOW_LAYOUT``, ``WindowLayout(7)``: 49 rows, by default; the configuration's layout
|
|
35
|
+
through ``swin_stage_blocks``), recording the rows: the LayerNorm gamma and beta as
|
|
36
|
+
``RowConstant``s and the projections' biases in ``LinearConstants``. The blocks run in that
|
|
37
|
+
layout and pass it to ``layer_norm`` and ``linear``, which refuse constants built for
|
|
38
|
+
another row count (client-side; the graph is unchanged). ``window_attention`` reads the
|
|
39
|
+
``SwinBlockConstants`` shape (``qkv``, ``relative_bias``, ``dim``, ``heads``, ``head_dim``)
|
|
40
|
+
and its window.
|
|
41
|
+
|
|
42
|
+
**Policy** ``composite``: the blocks are called with their defaults: LayerNorm, Linear and
|
|
43
|
+
GELU in ``double_round_once``, the attention core in ``round_each_op``; residual additions are
|
|
44
|
+
one float32 rounding.
|
|
45
|
+
|
|
46
|
+
**Extension.** ``extension_mode="per_block"``, what the adapter runs and the only mode, extends
|
|
47
|
+
each SW-MSA block's input by one window (``periodic_extension``) before the block. The research
|
|
48
|
+
variants (the ``per_stage`` and ``propagated`` modes with their halo registry
|
|
49
|
+
``EXTENSION_HALOS``, the fine-grid merge gather, the shifted block's ablations and the extra
|
|
50
|
+
materialization points) were removed when the research code was archived; they are in the research code archived at the
|
|
51
|
+
tag ``research-archive-2026-10-12``.
|
|
52
|
+
|
|
53
|
+
**Locality.** The MLP branch is per token and the W-MSA block reads its own window. The
|
|
54
|
+
SW-MSA block reads a ring of w - w // 2 tokens of its neighbours (the shifted windows straddle
|
|
55
|
+
them), and its mask marks the chip's last window row and column, so it is chip-edge
|
|
56
|
+
dependent. The stage and the encoder extend each SW-MSA block's input periodically, so an
|
|
57
|
+
edge window reads the opposite edge of the chip: ``EXTENT``, chip-edge dependent. The patch
|
|
58
|
+
embedding reads each token's patch (radius patch // 2).
|
|
59
|
+
|
|
60
|
+
**Cost.** ``METADATA``'s cost functions sum the parts' (``layer_norm``, ``linear``,
|
|
61
|
+
``window_attention``, ``shifted_window_mask``, ``patch_merge``, ``patch_embed``).
|
|
62
|
+
|
|
63
|
+
**Validated.** Live only inside two whole models: Swin-T224 (window 7, shift 3, Swin-T
|
|
64
|
+
depths, heads and widths; 224 x 224, two bands) in the trained-model rehearsal against PyTorch
|
|
65
|
+
(docs/evidence/t06-rehearsal.json) and in the trained model's parity check
|
|
66
|
+
(docs/history/upernet/notes/milestone12_findings.md), and the window-8 Swin-UPerNet validation model (window 8, shift 4,
|
|
67
|
+
widths 48 to 384, heads 2 to 16, depths 2; 256 x 256, three bands;
|
|
68
|
+
docs/evidence/c1-capstone.json). Neither model runs the encoder's final norm; full Swin-encoder validation
|
|
69
|
+
validated the research encoder these came from, final norm included, at Swin-T's settings
|
|
70
|
+
(docs/history/swin_encoder/notes/milestone5_findings.md). Other configurations are validated
|
|
71
|
+
only where the blocks' statuses cover them (docs/building-blocks.md); the builders accept
|
|
72
|
+
more, such as other widths, which is not evidence that they work.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
from __future__ import annotations
|
|
76
|
+
|
|
77
|
+
from dataclasses import dataclass
|
|
78
|
+
|
|
79
|
+
import numpy as np
|
|
80
|
+
|
|
81
|
+
from ...core.grid import TokenGrid
|
|
82
|
+
from ...core.metadata import COMPOSITE, BlockMetadata, Locality, Validated, validate_metadata
|
|
83
|
+
from ...layouts.shift import _resolve_shift, materialize, periodic_extension, shift_windows, unshift_windows
|
|
84
|
+
from ...weights.constants import ServerArray, WindowLayout, row_constant
|
|
85
|
+
from .activations import gelu
|
|
86
|
+
from .attention import METADATA as ATTENTION_METADATA
|
|
87
|
+
from .attention import relative_position_bias, shifted_window_mask, window_attention
|
|
88
|
+
from .linear import METADATA as LINEAR_METADATA
|
|
89
|
+
from .linear import WINDOW_LAYOUT, LinearConstants, linear
|
|
90
|
+
from .normalization import METADATA as NORM_METADATA
|
|
91
|
+
from .normalization import layer_norm
|
|
92
|
+
from .patch import METADATA as PATCH_METADATA
|
|
93
|
+
from .patch import (PatchEmbedConstants, PatchMergeConstants, patch_embed, patch_embed_constants, patch_embed_values,
|
|
94
|
+
patch_locality, patch_merge, patch_merge_constants, stage2_coarse)
|
|
95
|
+
from .swin_upernet_config import MLP_RATIO, SWIN_T224, SwinUPerNetConfig, check_shapes, stage_shifted
|
|
96
|
+
|
|
97
|
+
DIM, HEADS = SWIN_T224.stage_dims[0], SWIN_T224.num_heads[0]
|
|
98
|
+
"""``SwinBlockConstants`` defaults: Swin-T stage 1 (96 channels, 3 heads)."""
|
|
99
|
+
|
|
100
|
+
EXTENSION_MODES = ("per_block",)
|
|
101
|
+
"""The encoder's extension modes: per_block, the production mode (the only one)."""
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# ---------------------------------------------------------------------------
|
|
105
|
+
# One Swin block (W-MSA) and its constants
|
|
106
|
+
# ---------------------------------------------------------------------------
|
|
107
|
+
@dataclass
|
|
108
|
+
class SwinBlockConstants:
|
|
109
|
+
"""The block's parameters as EE constants of one path (value or image),
|
|
110
|
+
with the block's width and head count."""
|
|
111
|
+
|
|
112
|
+
norm1_weight: object
|
|
113
|
+
norm1_bias: object
|
|
114
|
+
qkv: LinearConstants
|
|
115
|
+
relative_bias: list
|
|
116
|
+
proj: LinearConstants
|
|
117
|
+
norm2_weight: object
|
|
118
|
+
norm2_bias: object
|
|
119
|
+
fc1: LinearConstants
|
|
120
|
+
fc2: LinearConstants
|
|
121
|
+
dim: int = DIM
|
|
122
|
+
heads: int = HEADS
|
|
123
|
+
window: int = SWIN_T224.window
|
|
124
|
+
"""The window the constants serve (``layout.window`` in ``swin_block_constants``): the
|
|
125
|
+
blocks run at it."""
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def head_dim(self) -> int:
|
|
129
|
+
return self.dim // self.heads
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def layout(self) -> WindowLayout:
|
|
133
|
+
return WindowLayout(self.window)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _shape(value) -> tuple:
|
|
137
|
+
return value.shape if isinstance(value, ServerArray) else np.shape(value)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def swin_block_constants(ops, parameters: dict, *, layout=WINDOW_LAYOUT) -> SwinBlockConstants:
|
|
141
|
+
"""parameters: timm state_dict names -> float32 NumPy arrays or ServerArrays.
|
|
142
|
+
|
|
143
|
+
``layout``: the window layout the block runs in (``WINDOW_LAYOUT``, window 7 and 49
|
|
144
|
+
rows, by default; ``swin_stage_blocks`` passes the configuration's). The LayerNorm
|
|
145
|
+
constants are ``RowConstant``s and the biases are repeated to its rows; the
|
|
146
|
+
relative-position bias uses its window, which the constants record
|
|
147
|
+
(``SwinBlockConstants.window``)."""
|
|
148
|
+
p = parameters
|
|
149
|
+
dim = _shape(p["norm1.weight"])[0]
|
|
150
|
+
heads = _shape(p["attn.relative_position_bias_table"])[1]
|
|
151
|
+
if dim % heads:
|
|
152
|
+
raise ValueError("dim must be a multiple of the head count")
|
|
153
|
+
return SwinBlockConstants(
|
|
154
|
+
norm1_weight=row_constant(ops, p["norm1.weight"], layout),
|
|
155
|
+
norm1_bias=row_constant(ops, p["norm1.bias"], layout),
|
|
156
|
+
qkv=LinearConstants(ops, p["attn.qkv.weight"], p["attn.qkv.bias"], layout),
|
|
157
|
+
relative_bias=[ops.wrap(b) for b in relative_position_bias(
|
|
158
|
+
ops.ee, p["attn.relative_position_bias_table"], layout.window)],
|
|
159
|
+
proj=LinearConstants(ops, p["attn.proj.weight"], p["attn.proj.bias"], layout),
|
|
160
|
+
norm2_weight=row_constant(ops, p["norm2.weight"], layout),
|
|
161
|
+
norm2_bias=row_constant(ops, p["norm2.bias"], layout),
|
|
162
|
+
fc1=LinearConstants(ops, p["mlp.fc1.weight"], p["mlp.fc1.bias"], layout),
|
|
163
|
+
fc2=LinearConstants(ops, p["mlp.fc2.weight"], p["mlp.fc2.bias"], layout),
|
|
164
|
+
dim=dim, heads=heads, window=layout.window,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def swin_mlp_branch(ops, x1, c: SwinBlockConstants) -> dict:
|
|
169
|
+
"""The block's second residual: x1 + fc2(GELU(fc1(LN2(x1)))), with every intermediate."""
|
|
170
|
+
t = {"ln2": layer_norm(ops, x1, c.norm2_weight, c.norm2_bias, dim=c.dim, layout=c.layout)}
|
|
171
|
+
t["fc1"] = linear(ops, t["ln2"], c.fc1, layout=c.layout)
|
|
172
|
+
t["act"] = gelu(ops, t["fc1"])
|
|
173
|
+
t["fc2"] = linear(ops, t["act"], c.fc2, layout=c.layout)
|
|
174
|
+
t["out"] = x1.add(t["fc2"]) # float32 + float32 -> float32
|
|
175
|
+
return t
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def swin_block(ops, x, c: SwinBlockConstants) -> dict:
|
|
179
|
+
"""Every named intermediate of the block for x: float32 [w^2, dim] per window (w =
|
|
180
|
+
``c.window``; 49 rows at window 7).
|
|
181
|
+
|
|
182
|
+
EE graphs are lazy: requesting one entry evaluates only what it needs, so
|
|
183
|
+
prefixes of the block (e.g. "qkv") are measured by requesting that entry.
|
|
184
|
+
"""
|
|
185
|
+
t = {"ln1": layer_norm(ops, x, c.norm1_weight, c.norm1_bias, dim=c.dim, layout=c.layout)}
|
|
186
|
+
t.update(window_attention(ops, t["ln1"], c, window=c.window))
|
|
187
|
+
t["proj"] = linear(ops, t["concat"], c.proj, layout=c.layout)
|
|
188
|
+
t["x1"] = x.add(t["proj"]) # float32 + float32 -> float32
|
|
189
|
+
t.update(swin_mlp_branch(ops, t["x1"], c))
|
|
190
|
+
return t
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# ---------------------------------------------------------------------------
|
|
194
|
+
# One shifted-window Swin block (SW-MSA)
|
|
195
|
+
# ---------------------------------------------------------------------------
|
|
196
|
+
def shifted_swin_block(ops, x, c: SwinBlockConstants, coarse, *, mask=None, shift: int | None = None) -> dict:
|
|
197
|
+
"""Every named intermediate of the SW-MSA block for x: float32 [w^2, dim] per window
|
|
198
|
+
(window layout of the full raster's coarse grid `coarse`; w = c.window, dim = c.dim).
|
|
199
|
+
|
|
200
|
+
Keys: the Swin block's per-head names (q_h0, logits_h0, ...) in shifted
|
|
201
|
+
layout, plus "logits_biased_h{h}", "mask", "shifted", "reverse" and
|
|
202
|
+
"unshifted". x is materialized on the coarse grid first, and the shift
|
|
203
|
+
materializes its input (``shift.roll_windows``). mask: Swin's shifted-window
|
|
204
|
+
mask, built for `coarse`, the window and the shift when not given. shift: timm's
|
|
205
|
+
stage shift, ``c.window // 2`` (3 at window 7) when not given; it must satisfy
|
|
206
|
+
0 < shift < window. The cyclic shift, the mask and the attention all run at
|
|
207
|
+
``c.window``.
|
|
208
|
+
"""
|
|
209
|
+
ee = ops.ee
|
|
210
|
+
window = c.window
|
|
211
|
+
shift = _resolve_shift(shift, window)
|
|
212
|
+
x = materialize(ee, x, coarse)
|
|
213
|
+
if mask is None:
|
|
214
|
+
mask = shifted_window_mask(ee, coarse, window=window, shift=shift)
|
|
215
|
+
t = {"x": x, "ln1": layer_norm(ops, x, c.norm1_weight, c.norm1_bias, dim=c.dim, layout=c.layout)}
|
|
216
|
+
t["shifted"] = shift_windows(ee, t["ln1"], coarse, c.dim, shift, window)
|
|
217
|
+
t.update(window_attention(ops, t["shifted"], c, mask, window=window))
|
|
218
|
+
t["mask"] = mask
|
|
219
|
+
t["proj"] = linear(ops, t["concat"], c.proj, layout=c.layout)
|
|
220
|
+
t["reverse"] = t["proj"]
|
|
221
|
+
t["unshifted"] = unshift_windows(ee, t["proj"], coarse, c.dim, shift, window)
|
|
222
|
+
t["x1"] = x.add(t["unshifted"]) # float32 + float32 -> float32
|
|
223
|
+
t.update(swin_mlp_branch(ops, t["x1"], c))
|
|
224
|
+
return t
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
# One stage
|
|
229
|
+
# ---------------------------------------------------------------------------
|
|
230
|
+
def swin_stage(ops, x, blocks: list, coarse, *, shifted: bool = True, shift: int | None = None) -> dict:
|
|
231
|
+
"""Every named intermediate of the blocks (keys b{i}_<name>) and "out".
|
|
232
|
+
|
|
233
|
+
x: the stage input in window layout on the full raster's coarse grid
|
|
234
|
+
`coarse` ([w^2, dim] per window). Each SW-MSA block's input is first extended
|
|
235
|
+
by one window (``periodic_extension``: the per_block mode). shift: the SW-MSA
|
|
236
|
+
blocks' shift (``shifted_swin_block``: w // 2 when not given).
|
|
237
|
+
"""
|
|
238
|
+
ee = ops.ee
|
|
239
|
+
t = {}
|
|
240
|
+
for i, c in enumerate(blocks):
|
|
241
|
+
if shifted and i % 2:
|
|
242
|
+
x = periodic_extension(ee, x, coarse, 1)
|
|
243
|
+
result = shifted_swin_block(ops, x, c, coarse, shift=shift)
|
|
244
|
+
else:
|
|
245
|
+
result = swin_block(ops, x, c)
|
|
246
|
+
t.update({f"b{i}_{name}": value for name, value in result.items()})
|
|
247
|
+
x = result["out"]
|
|
248
|
+
t["out"] = x
|
|
249
|
+
return t
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# ---------------------------------------------------------------------------
|
|
253
|
+
# Encoder constants and grids
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
@dataclass
|
|
256
|
+
class SwinEncoderConstants:
|
|
257
|
+
blocks: list # [stage][block] SwinBlockConstants
|
|
258
|
+
merges: list # PatchMergeConstants pm1, pm2, pm3
|
|
259
|
+
norm_weight: object # [w^2, C4] (rows repeated)
|
|
260
|
+
norm_bias: object
|
|
261
|
+
config: SwinUPerNetConfig = SWIN_T224
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _group_shapes(config: SwinUPerNetConfig, group: str) -> dict:
|
|
265
|
+
return config.parameter_shapes()[0][group]
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def swin_stage_blocks(ops, parameters: dict, s: int, count: int | None = None, *,
|
|
269
|
+
config: SwinUPerNetConfig = SWIN_T224) -> list:
|
|
270
|
+
"""SwinBlockConstants of the first `count` blocks of stage s (``config.depths[s - 1]``
|
|
271
|
+
when not given), built for the configuration's window layout. Parameters whose shapes
|
|
272
|
+
differ from the configuration's (stage width, heads, window) are refused."""
|
|
273
|
+
depth = config.depths[s - 1]
|
|
274
|
+
count = depth if count is None else count
|
|
275
|
+
if not 0 <= count <= depth:
|
|
276
|
+
raise ValueError(f"stage {s} has {depth} blocks; received count {count}")
|
|
277
|
+
blocks = []
|
|
278
|
+
for b in range(count):
|
|
279
|
+
group = f"s{s}b{b}"
|
|
280
|
+
check_shapes(parameters[group], _group_shapes(config, group), group)
|
|
281
|
+
blocks.append(swin_block_constants(ops, parameters[group], layout=config.layout))
|
|
282
|
+
return blocks
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def swin_merge_constants(ops, parameters: dict, n: int, *,
|
|
286
|
+
config: SwinUPerNetConfig = SWIN_T224) -> PatchMergeConstants:
|
|
287
|
+
"""Patch Merging n (stage n -> n + 1) for the configuration's window layout; parameters
|
|
288
|
+
whose shapes differ from the configuration's are refused."""
|
|
289
|
+
group = f"pm{n}"
|
|
290
|
+
check_shapes(parameters[group], _group_shapes(config, group), group)
|
|
291
|
+
return patch_merge_constants(ops, parameters[group], config.layout)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def swin_patch_embedding_constants(ops, parameters: dict, *,
|
|
295
|
+
config: SwinUPerNetConfig = SWIN_T224) -> PatchEmbedConstants:
|
|
296
|
+
"""The patch embedding's constants (timm ``patch_embed.*``: ``proj.weight`` [embed_dim,
|
|
297
|
+
bands x patch^2] flattened (c, ky, kx), ``proj.bias``, ``norm.weight``, ``norm.bias``) for
|
|
298
|
+
the configuration's window layout; other shapes are refused."""
|
|
299
|
+
check_shapes(parameters, config.parameter_shapes()[1], "patch_embed")
|
|
300
|
+
return patch_embed_constants(ops, parameters, rows=config.layout)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def swin_patch_embedding(ops, x, grid, c: PatchEmbedConstants, *, config: SwinUPerNetConfig = SWIN_T224) -> dict:
|
|
304
|
+
"""The library's ``patch_embed`` at the configuration's patch, bands and window: x (the
|
|
305
|
+
bands, by name, on the model input grid ``grid``) -> {"pe_columns", "pe_patches",
|
|
306
|
+
"pe_proj", "x"}, "x" being the stage-1 input in window layout. ``grid`` must be the
|
|
307
|
+
configuration's model grid (``SwinUPerNetConfig.model_grid``), whose patches are the
|
|
308
|
+
encoder's stage-1 tokens; another grid is refused."""
|
|
309
|
+
expected = config.model_grid(grid.height, grid.width)
|
|
310
|
+
if grid != expected:
|
|
311
|
+
raise ValueError(f"{grid} is not the configuration's model grid {expected}")
|
|
312
|
+
return patch_embed(ops, x, grid, c, patch=config.patch, bands=config.bands, window=config.window)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@dataclass(frozen=True)
|
|
316
|
+
class SwinEncoderGrids:
|
|
317
|
+
"""Token and window grids of every stage for rows x cols stage-1 windows."""
|
|
318
|
+
|
|
319
|
+
tokens: tuple # stage s token grid: 2^(s-1) x coarser than stage-1 tokens
|
|
320
|
+
coarse: tuple # stage s window grid (one [w^2, dim] window per pixel)
|
|
321
|
+
config: SwinUPerNetConfig = SWIN_T224
|
|
322
|
+
|
|
323
|
+
def shifted(self, s: int) -> bool:
|
|
324
|
+
return stage_shifted(self.coarse[s - 1].height, self.coarse[s - 1].width)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def swin_encoder_grids(rows: int, cols: int, *, config: SwinUPerNetConfig = SWIN_T224) -> SwinEncoderGrids:
|
|
328
|
+
"""The grids of rows x cols stage-1 windows of ``config.window`` tokens (stage-1 tokens on
|
|
329
|
+
the default ``TokenGrid``: 10 m, EPSG:3857, origin (0, 0); ``swin_upernet_config.TOKEN_SCALE``)."""
|
|
330
|
+
config.check_windows(rows, cols)
|
|
331
|
+
window = config.window
|
|
332
|
+
first = TokenGrid(rows * window, cols * window)
|
|
333
|
+
tokens = tuple(first.coarse(2 ** s) if s else first for s in range(config.stages))
|
|
334
|
+
coarse = tuple(grid.coarse(window) for grid in tokens)
|
|
335
|
+
for s in range(1, config.stages):
|
|
336
|
+
if coarse[s] != stage2_coarse(coarse[s - 1]):
|
|
337
|
+
raise AssertionError("stage grids disagree")
|
|
338
|
+
return SwinEncoderGrids(tokens, coarse, config)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
# ---------------------------------------------------------------------------
|
|
342
|
+
# The encoder
|
|
343
|
+
# ---------------------------------------------------------------------------
|
|
344
|
+
def _check_config(c: SwinEncoderConstants, g: SwinEncoderGrids, start: int, stop: int) -> SwinUPerNetConfig:
|
|
345
|
+
"""The configuration ``c`` and ``g`` share, after refusing constants built for another one:
|
|
346
|
+
every block run must serve the configuration's window, width and heads, and every merge
|
|
347
|
+
its stage's width (client-side; the graph is unchanged)."""
|
|
348
|
+
config = c.config
|
|
349
|
+
if g.config != config:
|
|
350
|
+
raise ValueError(f"the encoder grids were built for {g.config}; the constants for {config}")
|
|
351
|
+
for s in range(start, stop + 1):
|
|
352
|
+
for b, block in enumerate(c.blocks[s - 1]):
|
|
353
|
+
if (block.window, block.dim, block.heads) != (config.window, config.stage_dims[s - 1],
|
|
354
|
+
config.num_heads[s - 1]):
|
|
355
|
+
raise ValueError(f"block s{s}b{b} was built for window {block.window}, width {block.dim} and "
|
|
356
|
+
f"{block.heads} heads; the configuration's stage {s} runs window {config.window}, "
|
|
357
|
+
f"width {config.stage_dims[s - 1]} and {config.num_heads[s - 1]} heads")
|
|
358
|
+
if s > 1 and c.merges[s - 2].in_dim != config.stage_dims[s - 2]:
|
|
359
|
+
raise ValueError(f"merge pm{s - 1} reads {c.merges[s - 2].in_dim} channels; the configuration's "
|
|
360
|
+
f"stage {s - 1} has {config.stage_dims[s - 2]}")
|
|
361
|
+
return config
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def swin_encoder(ops, x, c: SwinEncoderConstants, g: SwinEncoderGrids, *, start: int = 1,
|
|
365
|
+
stop: int = SWIN_T224.stages, extension_mode: str = "per_block") -> dict:
|
|
366
|
+
"""Every named intermediate (keys as encoder_reference): x, s{s}b{b}_*,
|
|
367
|
+
s{s}_out, pm{n}_*, norm. EE evaluates only what a requested tensor needs.
|
|
368
|
+
|
|
369
|
+
start, stop: the stages to run. start > 1 takes x as the output of stage
|
|
370
|
+
start - 1 (window layout on that stage's grid, e.g. read back from an
|
|
371
|
+
asset; key s{start-1}_out); the final norm follows stage 4.
|
|
372
|
+
extension_mode: "per_block" (the default and only mode: see the module
|
|
373
|
+
docstring).
|
|
374
|
+
|
|
375
|
+
The configuration is the constants' and the grids' (``SwinEncoderConstants.config``,
|
|
376
|
+
``SwinEncoderGrids.config``); it is refused when they differ, or when a block or merge
|
|
377
|
+
was built for another window, width or head count. Patch Merging, the blocks and the
|
|
378
|
+
final norm run at its window, and the SW-MSA blocks with its shift (w // 2).
|
|
379
|
+
"""
|
|
380
|
+
if extension_mode not in EXTENSION_MODES:
|
|
381
|
+
raise ValueError(f"extension_mode must be one of {EXTENSION_MODES}")
|
|
382
|
+
config = _check_config(c, g, start, stop)
|
|
383
|
+
t = {"x": x} if start == 1 else {f"s{start - 1}_out": x}
|
|
384
|
+
for s in range(start, stop + 1):
|
|
385
|
+
coarse, shifted = g.coarse[s - 1], g.shifted(s)
|
|
386
|
+
if s > 1:
|
|
387
|
+
pm = patch_merge(ops, x, c.merges[s - 2], g.coarse[s - 2], window=config.window)
|
|
388
|
+
t.update({f"pm{s - 1}_{k}": v for k, v in pm.items()})
|
|
389
|
+
x = pm["out"]
|
|
390
|
+
result = swin_stage(ops, x, c.blocks[s - 1], coarse, shifted=shifted, shift=config.shift)
|
|
391
|
+
t.update({f"s{s}{k}": v for k, v in result.items() if k != "out"})
|
|
392
|
+
x = result["out"]
|
|
393
|
+
t[f"s{s}_out"] = x
|
|
394
|
+
if stop == config.stages and c.norm_weight is not None:
|
|
395
|
+
# (a model without the final norm, e.g. UPerNet's FeatureListNet, passes None)
|
|
396
|
+
t["norm"] = layer_norm(ops, x, c.norm_weight, c.norm_bias, dim=config.norm_dim, layout=config.layout)
|
|
397
|
+
return t
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
# ---------------------------------------------------------------------------
|
|
401
|
+
# Cost functions (contract section 9): sums of the parts' METADATA cost functions
|
|
402
|
+
# ---------------------------------------------------------------------------
|
|
403
|
+
_PARTS = {**LINEAR_METADATA, **NORM_METADATA, **ATTENTION_METADATA, **PATCH_METADATA}
|
|
404
|
+
"""The parts' entries by block name: a composite's cost is the sum of its parts' costs."""
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def swin_mlp_branch_values(dim: int, *, layout=WINDOW_LAYOUT) -> int:
|
|
408
|
+
"""norm2's gamma and beta rows, and fc1 [dim, 4 dim] and fc2 [4 dim, dim] with their bias
|
|
409
|
+
rows (timm's ``MLP_RATIO``); GELU and the residual addition embed nothing."""
|
|
410
|
+
hidden = MLP_RATIO * dim
|
|
411
|
+
linear_values = _PARTS["linear"].embedded_constants
|
|
412
|
+
return (_PARTS["layer_norm"].embedded_constants(dim, layout=layout)
|
|
413
|
+
+ linear_values(dim, hidden, layout=layout) + linear_values(hidden, dim, layout=layout))
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def swin_mlp_branch_arrays() -> int:
|
|
417
|
+
"""Server arrays read: norm2's weight and bias, and fc1's and fc2's weights and biases."""
|
|
418
|
+
return _PARTS["layer_norm"].asset_arrays() + 2 * _PARTS["linear"].asset_arrays(bias=True)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def swin_block_values(dim: int, heads: int, *, window: int = SWIN_T224.window) -> int:
|
|
422
|
+
"""norm1, the window attention (the QKV projection and the relative-position table), the
|
|
423
|
+
output projection and the MLP branch, each per-channel constant at the window's w^2 rows."""
|
|
424
|
+
layout = WindowLayout(window)
|
|
425
|
+
return (_PARTS["layer_norm"].embedded_constants(dim, layout=layout)
|
|
426
|
+
+ _PARTS["window_attention"].embedded_constants(dim, heads, window=window)
|
|
427
|
+
+ _PARTS["linear"].embedded_constants(dim, dim, layout=layout)
|
|
428
|
+
+ swin_mlp_branch_values(dim, layout=layout))
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def swin_block_arrays() -> int:
|
|
432
|
+
"""Server arrays read: the block's 13 timm parameters (norm1, the attention's QKV and
|
|
433
|
+
relative-position table, the projection, and the MLP branch's)."""
|
|
434
|
+
return (_PARTS["layer_norm"].asset_arrays() + _PARTS["window_attention"].asset_arrays()
|
|
435
|
+
+ _PARTS["linear"].asset_arrays(bias=True) + swin_mlp_branch_arrays())
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def shifted_swin_block_values(dim: int, heads: int, *, window: int = SWIN_T224.window) -> int:
|
|
439
|
+
"""The W-MSA block's constants and the shifted-window mask's, which embeds none (it is built
|
|
440
|
+
on the server from the grid)."""
|
|
441
|
+
return swin_block_values(dim, heads, window=window) + _PARTS["shifted_window_mask"].embedded_constants()
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def shifted_swin_block_arrays() -> int:
|
|
445
|
+
"""Server arrays read: the W-MSA block's; the mask reads none."""
|
|
446
|
+
return swin_block_arrays() + _PARTS["shifted_window_mask"].asset_arrays()
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def swin_stage_values(dim: int, heads: int, depth: int, *, window: int = SWIN_T224.window) -> int:
|
|
450
|
+
"""``depth`` blocks, W-MSA and SW-MSA alternating (the periodic extension embeds nothing)."""
|
|
451
|
+
return sum((shifted_swin_block_values if b % 2 else swin_block_values)(dim, heads, window=window)
|
|
452
|
+
for b in range(depth))
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def swin_stage_arrays(*, depth: int) -> int:
|
|
456
|
+
"""Server arrays read: ``depth`` blocks'."""
|
|
457
|
+
return sum(shifted_swin_block_arrays() if b % 2 else swin_block_arrays() for b in range(depth))
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def swin_patch_embedding_values(*, config: SwinUPerNetConfig = SWIN_T224) -> int:
|
|
461
|
+
"""``patch_embed``'s at the configuration's width, patch, bands and window layout."""
|
|
462
|
+
return _PARTS["patch_embed"].embedded_constants(config.embed_dim, patch=config.patch, channels=config.in_chans,
|
|
463
|
+
layout=config.layout)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def swin_patch_embedding_arrays() -> int:
|
|
467
|
+
"""Server arrays read: ``patch_embed``'s."""
|
|
468
|
+
return _PARTS["patch_embed"].asset_arrays()
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def swin_encoder_values(*, config: SwinUPerNetConfig = SWIN_T224, start: int = 1, stop: int | None = None,
|
|
472
|
+
norm: bool = True) -> int:
|
|
473
|
+
"""Stages ``start`` to ``stop`` (the last when not given) of the configuration, each from
|
|
474
|
+
stage 2 with the Patch Merging before it, and the final norm after the last stage when
|
|
475
|
+
``norm`` (UPerNet's encoder runs without it).
|
|
476
|
+
|
|
477
|
+
``norm`` defaults to True, as ``swin_encoder`` runs the final norm whenever its constants
|
|
478
|
+
carry one: the default counts the encoder as built with it. The validated models run
|
|
479
|
+
without it (``METADATA["swin_encoder"].validated``: ``norm`` False), so their count is
|
|
480
|
+
``norm=False``. The default stays: defaults are not changed (``AGENTS.md``), and callers
|
|
481
|
+
rely on it (tests/test_x01b_swin_upernet_composites.py counts the norm as the difference)."""
|
|
482
|
+
stop = config.stages if stop is None else stop
|
|
483
|
+
total = 0
|
|
484
|
+
for s in range(start, stop + 1):
|
|
485
|
+
if s > 1:
|
|
486
|
+
total += _PARTS["patch_merge"].embedded_constants(config.stage_dims[s - 2], layout=config.layout)
|
|
487
|
+
total += swin_stage_values(config.stage_dims[s - 1], config.num_heads[s - 1], config.depths[s - 1],
|
|
488
|
+
window=config.window)
|
|
489
|
+
if norm and stop == config.stages:
|
|
490
|
+
total += _PARTS["layer_norm"].embedded_constants(config.norm_dim, layout=config.layout)
|
|
491
|
+
return total
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def swin_encoder_arrays(*, config: SwinUPerNetConfig = SWIN_T224, start: int = 1, stop: int | None = None,
|
|
495
|
+
norm: bool = True) -> int:
|
|
496
|
+
"""Server arrays read: the stages', the Patch Mergings' and, when ``norm``, the final norm's.
|
|
497
|
+
``norm`` defaults to True for the reason ``swin_encoder_values`` gives; the validated models
|
|
498
|
+
run without the final norm (``norm=False``)."""
|
|
499
|
+
stop = config.stages if stop is None else stop
|
|
500
|
+
total = sum(swin_stage_arrays(depth=config.depths[s - 1])
|
|
501
|
+
+ (_PARTS["patch_merge"].asset_arrays() if s > 1 else 0) for s in range(start, stop + 1))
|
|
502
|
+
if norm and stop == config.stages:
|
|
503
|
+
total += _PARTS["layer_norm"].asset_arrays()
|
|
504
|
+
return total
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
# ---------------------------------------------------------------------------
|
|
508
|
+
# Metadata
|
|
509
|
+
# ---------------------------------------------------------------------------
|
|
510
|
+
# Validated live only inside two whole models: Swin-T224 (trained-model rehearsal against PyTorch, trained Swin-UPerNet validation
|
|
511
|
+
# against ONNX Runtime) and the window-8 Swin-UPerNet validation model.
|
|
512
|
+
_STATUS = "Fixed — Swin-T224 and the capstone: "
|
|
513
|
+
_WIDTHS = ("widths 96, 192, 384, 768, heads 3, 6, 12, 24 at window 7; "
|
|
514
|
+
"widths 48, 96, 192, 384, heads 2, 4, 8, 16 at window 8")
|
|
515
|
+
_EVIDENCE = ("docs/evidence/t06-rehearsal.json", "docs/history/upernet/notes/milestone12_findings.md",
|
|
516
|
+
"docs/evidence/c1-capstone.json")
|
|
517
|
+
|
|
518
|
+
# Validated settings: the two models' settings, named by the cost functions' parameters
|
|
519
|
+
# (dim, heads, depth, window) and SwinUPerNetConfig's fields, and joined per stage. The window-8 Swin-UPerNet validation model
|
|
520
|
+
# is tools/capstone.py's CONFIG (docs/evidence/c1-capstone.json).
|
|
521
|
+
_MODELS = ({"window": 7, "stage_dims": (96, 192, 384, 768), "num_heads": (3, 6, 12, 24), "depths": (2, 2, 6, 2),
|
|
522
|
+
"embed_dim": 96, "channels": 2},
|
|
523
|
+
{"window": 8, "stage_dims": (48, 96, 192, 384), "num_heads": (2, 4, 8, 16), "depths": (2, 2, 2, 2),
|
|
524
|
+
"embed_dim": 48, "channels": 3})
|
|
525
|
+
_STAGES = tuple({"dim": (dim,), "heads": (heads,), "depth": (depth,), "window": (model["window"],),
|
|
526
|
+
"shift": (model["window"] // 2, None), "shifted": (s < 3,)}
|
|
527
|
+
for model in _MODELS
|
|
528
|
+
for s, (dim, heads, depth) in enumerate(zip(model["stage_dims"], model["num_heads"], model["depths"])))
|
|
529
|
+
"""Stage 4 is one window in both models (7 x 7 and 8 x 8 tokens), so timm's rule runs it unshifted."""
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def _pick(*names, shifted=None):
|
|
533
|
+
"""The stages' configurations reduced to ``names`` (only the shifted stages when asked)."""
|
|
534
|
+
return tuple({name: stage[name] for name in names} for stage in _STAGES
|
|
535
|
+
if shifted is None or stage["shifted"] == (shifted,))
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
METADATA = validate_metadata({
|
|
539
|
+
"swin_mlp_branch": BlockMetadata(
|
|
540
|
+
name="swin_mlp_branch", layout_in="W", layout_out="W", locality=Locality.POINTWISE,
|
|
541
|
+
policy=COMPOSITE, embedded_constants=swin_mlp_branch_values, asset_arrays=swin_mlp_branch_arrays,
|
|
542
|
+
status=_STATUS + "widths 96, 192, 384, 768 at window 7 and 48, 96, 192, 384 at window 8; hidden 4 × width",
|
|
543
|
+
evidence=_EVIDENCE + ("docs/history/swin_block/notes/findings.md",
|
|
544
|
+
"parts: layer_norm, linear and gelu (double_round_once), a float32 addition"),
|
|
545
|
+
validated=Validated(tuple({"dim": model["stage_dims"], "window": (model["window"],)} for model in _MODELS))),
|
|
546
|
+
"swin_block": BlockMetadata(
|
|
547
|
+
name="swin_block", layout_in="W", layout_out="W", locality=Locality.WINDOW,
|
|
548
|
+
policy=COMPOSITE, embedded_constants=swin_block_values, asset_arrays=swin_block_arrays,
|
|
549
|
+
status=_STATUS + _WIDTHS,
|
|
550
|
+
evidence=_EVIDENCE + ("docs/history/swin_block/notes/findings.md",
|
|
551
|
+
"parts: layer_norm, window_attention, linear, swin_mlp_branch"),
|
|
552
|
+
validated=Validated(_pick("dim", "heads", "window"))),
|
|
553
|
+
"shifted_swin_block": BlockMetadata(
|
|
554
|
+
# The shifted windows straddle their neighbours: after the roll by w // 2 and the
|
|
555
|
+
# unroll, an output window reads w - w // 2 tokens into them (4 at windows 7 and 8).
|
|
556
|
+
# Validated at stages 1-3 only: stage 4 is one window in both models (224 / 32 = 7 and
|
|
557
|
+
# 256 / 32 = 8 tokens), so timm never shifts it.
|
|
558
|
+
name="shifted_swin_block", layout_in="W", layout_out="W", locality=Locality.WINDOW_RING, radius=4,
|
|
559
|
+
policy=COMPOSITE, embedded_constants=shifted_swin_block_values, asset_arrays=shifted_swin_block_arrays,
|
|
560
|
+
chip_edge_dependent=True,
|
|
561
|
+
status=_STATUS + ("widths 96, 192, 384, heads 3, 6, 12 at window 7; widths 48, 96, 192, heads 2, 4, 8 "
|
|
562
|
+
"at window 8; shift ⌊w/2⌋; not stage 4 (one window, unshifted)"),
|
|
563
|
+
evidence=_EVIDENCE + ("docs/history/swin_pair/notes/findings.md",
|
|
564
|
+
"parts: layer_norm, shift_windows (none), window_attention with shifted_window_mask, "
|
|
565
|
+
"linear, swin_mlp_branch"),
|
|
566
|
+
validated=Validated(_pick("dim", "heads", "window", "shift", shifted=True))),
|
|
567
|
+
"swin_stage": BlockMetadata(
|
|
568
|
+
name="swin_stage", layout_in="W", layout_out="W", locality=Locality.EXTENT,
|
|
569
|
+
policy=COMPOSITE, embedded_constants=swin_stage_values, asset_arrays=swin_stage_arrays,
|
|
570
|
+
chip_edge_dependent=True, status=_STATUS + _WIDTHS + "; depths 2, 2, 6, 2 and 2, 2, 2, 2",
|
|
571
|
+
evidence=_EVIDENCE + ("docs/history/swin_encoder/notes/milestone5_findings.md",
|
|
572
|
+
"parts: swin_block, periodic_extension (none), shifted_swin_block"),
|
|
573
|
+
validated=Validated(_pick("dim", "heads", "depth", "window", "shift", "shifted"))),
|
|
574
|
+
"swin_patch_embedding": BlockMetadata(
|
|
575
|
+
# patch // 2 at the validated patch 4 (patch_embed's own radius 4 covers the validated patch size 8)
|
|
576
|
+
name="swin_patch_embedding", layout_in="R", layout_out="W", locality=Locality.KERNEL, radius=2,
|
|
577
|
+
policy=COMPOSITE, embedded_constants=swin_patch_embedding_values, asset_arrays=swin_patch_embedding_arrays,
|
|
578
|
+
status=_STATUS + "patch 4; 2 bands → width 96 at window 7, 3 bands → width 48 at window 8",
|
|
579
|
+
evidence=_EVIDENCE + ("docs/history/swin_image_encoder/notes/milestone6_findings.md",
|
|
580
|
+
"parts: patch_embed (double_round_once)"),
|
|
581
|
+
# channels: the number of bands (patch_embed_values'; config.in_chans), the names being labels.
|
|
582
|
+
validated=Validated(tuple({"patch": (4,), "channels": (model["channels"],), "embed_dim": (model["embed_dim"],),
|
|
583
|
+
"window": (model["window"],)} for model in _MODELS),
|
|
584
|
+
sources=(SwinUPerNetConfig, patch_embed_values)),
|
|
585
|
+
per_setting=patch_locality),
|
|
586
|
+
"swin_encoder": BlockMetadata(
|
|
587
|
+
name="swin_encoder", layout_in="W", layout_out="W", locality=Locality.EXTENT,
|
|
588
|
+
policy=COMPOSITE, embedded_constants=swin_encoder_values, asset_arrays=swin_encoder_arrays,
|
|
589
|
+
chip_edge_dependent=True,
|
|
590
|
+
status=_STATUS + "8 × 8 stage-1 windows of 7 (stages 1–3, then 4) and of 8 (stages 1–4), "
|
|
591
|
+
"without the final norm",
|
|
592
|
+
evidence=_EVIDENCE + ("docs/history/swin_encoder/notes/milestone5_findings.md",
|
|
593
|
+
"parts: patch_merge, swin_stage, layer_norm"),
|
|
594
|
+
# rows x cols stage-1 windows (swin_encoder_grids); norm=False: the cost functions' name for
|
|
595
|
+
# constants without the final norm (UPerNet's FeatureListNet), which both models run.
|
|
596
|
+
validated=Validated(tuple(
|
|
597
|
+
{"window": (model["window"],), "stage_dims": (model["stage_dims"],), "num_heads": (model["num_heads"],),
|
|
598
|
+
"depths": (model["depths"],), "rows": (8,), "cols": (8,), "start": (start,), "stop": (stop,),
|
|
599
|
+
"norm": (False,)}
|
|
600
|
+
for model, start, stop in ((_MODELS[0], 1, 3), (_MODELS[0], 4, 4), (_MODELS[1], 1, 4))),
|
|
601
|
+
sources=(SwinUPerNetConfig, swin_encoder_grids))),
|
|
602
|
+
})
|