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.
Files changed (84) hide show
  1. tensor_ee/__init__.py +28 -0
  2. tensor_ee/_swin_parameters.py +304 -0
  3. tensor_ee/blocks/__init__.py +0 -0
  4. tensor_ee/blocks/raster/__init__.py +36 -0
  5. tensor_ee/blocks/raster/activations.py +183 -0
  6. tensor_ee/blocks/raster/conv.py +183 -0
  7. tensor_ee/blocks/raster/merge.py +66 -0
  8. tensor_ee/blocks/raster/outputs.py +211 -0
  9. tensor_ee/blocks/raster/pooling.py +182 -0
  10. tensor_ee/blocks/raster/resample.py +64 -0
  11. tensor_ee/blocks/window/__init__.py +44 -0
  12. tensor_ee/blocks/window/activations.py +54 -0
  13. tensor_ee/blocks/window/attention.py +366 -0
  14. tensor_ee/blocks/window/conv.py +323 -0
  15. tensor_ee/blocks/window/linear.py +129 -0
  16. tensor_ee/blocks/window/merge.py +67 -0
  17. tensor_ee/blocks/window/normalization.py +197 -0
  18. tensor_ee/blocks/window/patch.py +362 -0
  19. tensor_ee/blocks/window/pooling.py +275 -0
  20. tensor_ee/blocks/window/resample.py +286 -0
  21. tensor_ee/blocks/window/segformer.py +718 -0
  22. tensor_ee/blocks/window/swin.py +602 -0
  23. tensor_ee/blocks/window/swin_upernet_config.py +361 -0
  24. tensor_ee/blocks/window/upernet.py +1016 -0
  25. tensor_ee/comparison.py +213 -0
  26. tensor_ee/compatibility.py +180 -0
  27. tensor_ee/compiler.py +356 -0
  28. tensor_ee/converter/__init__.py +72 -0
  29. tensor_ee/converter/build.py +120 -0
  30. tensor_ee/converter/convert.py +388 -0
  31. tensor_ee/converter/export.py +846 -0
  32. tensor_ee/converter/graph.py +417 -0
  33. tensor_ee/converter/operations.py +790 -0
  34. tensor_ee/converter/plan.py +675 -0
  35. tensor_ee/converter/recognizers.py +1273 -0
  36. tensor_ee/converter/request.py +146 -0
  37. tensor_ee/converter/run.py +950 -0
  38. tensor_ee/core/__init__.py +8 -0
  39. tensor_ee/core/errors.py +25 -0
  40. tensor_ee/core/grid.py +323 -0
  41. tensor_ee/core/metadata.py +398 -0
  42. tensor_ee/core/ops.py +336 -0
  43. tensor_ee/core/precision.py +133 -0
  44. tensor_ee/core/tensor.py +129 -0
  45. tensor_ee/examples/__init__.py +1 -0
  46. tensor_ee/examples/nonwater.py +251 -0
  47. tensor_ee/layouts/__init__.py +17 -0
  48. tensor_ee/layouts/boundaries.py +103 -0
  49. tensor_ee/layouts/raster.py +117 -0
  50. tensor_ee/layouts/shift.py +226 -0
  51. tensor_ee/layouts/window.py +201 -0
  52. tensor_ee/models/__init__.py +16 -0
  53. tensor_ee/models/fixtures.py +119 -0
  54. tensor_ee/models/segformer_b0/__init__.py +9 -0
  55. tensor_ee/models/segformer_b0/configuration.py +209 -0
  56. tensor_ee/models/segformer_b0/decoder.py +130 -0
  57. tensor_ee/models/segformer_b0/encoder.py +90 -0
  58. tensor_ee/models/swin_t224/__init__.py +30 -0
  59. tensor_ee/models/swin_t224/configuration.py +103 -0
  60. tensor_ee/models/swin_t224/decoder.py +53 -0
  61. tensor_ee/models/swin_t224/encoder.py +50 -0
  62. tensor_ee/onnx_import.py +431 -0
  63. tensor_ee/outputs.py +16 -0
  64. tensor_ee/primitives.py +110 -0
  65. tensor_ee/receptive_field.py +257 -0
  66. tensor_ee/resnet_models.py +185 -0
  67. tensor_ee/segwater_inference.py +235 -0
  68. tensor_ee/segwater_preprocessing.py +182 -0
  69. tensor_ee/segwater_pytorch.py +249 -0
  70. tensor_ee/semantics.py +389 -0
  71. tensor_ee/smp.py +155 -0
  72. tensor_ee/swin.py +197 -0
  73. tensor_ee/swin_workflow.py +470 -0
  74. tensor_ee/tiling.py +287 -0
  75. tensor_ee/weight_assets.py +371 -0
  76. tensor_ee/weight_mapping.py +51 -0
  77. tensor_ee/weights/__init__.py +14 -0
  78. tensor_ee/weights/assets.py +160 -0
  79. tensor_ee/weights/constants.py +156 -0
  80. tensor_ee-0.1.0.dist-info/METADATA +172 -0
  81. tensor_ee-0.1.0.dist-info/RECORD +84 -0
  82. tensor_ee-0.1.0.dist-info/WHEEL +5 -0
  83. tensor_ee-0.1.0.dist-info/licenses/LICENSE +21 -0
  84. tensor_ee-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,718 @@
1
+ """SegFormer's composites in window layout: the channel norm, the overlapping patch
2
+ embedding, efficient attention with global keys and values, the Mix-FFN, the MiT block, and
3
+ the all-MLP decoder's pyramid projection and fused head.
4
+
5
+ Moved from ``tensor_ee/models/segformer_b0/encoder.py`` (``NormConstants``,
6
+ ``norm_constants``, ``channel_norm``, ``OverlapConstants``, ``overlap_constants``,
7
+ ``decimate``, ``overlap_embedding``, ``AttentionConstants``, ``attention_constants``,
8
+ ``spatial_reduction``, ``shared_key_attention``, ``global_attention``, ``MixFFNConstants``,
9
+ ``mix_ffn_constants``, ``mix_ffn``, and the MiT block ``BlockConstants``, ``block_constants``
10
+ and ``block``, renamed here ``MiTBlockConstants``, ``mit_block_constants`` and ``mit_block``,
11
+ with their helpers) and ``decoder.py`` (``project_pyramid``, and the fuse, BatchNorm, ReLU and
12
+ head sequence of ``decoder()``, now ``fuse_head``). The fixed SegFormer-B0 model keeps its
13
+ configuration and checks there and re-exports these objects under their former names; there
14
+ is one implementation. The decoder composites' constants builders, ``project_pyramid_constants``
15
+ and ``fuse_head_constants``, are shared with ``decoder_constants``, so that the model and the
16
+ block-graph builder (``tensor_ee/converter/``) share them.
17
+
18
+ Parameters keep SMP 0.5.0 state_dict names under a ``prefix``: NumPy float32 arrays of the
19
+ original shapes, or ``ServerArray``s, a convolution's as [out, in k k] in PyTorch's (c, ky, kx)
20
+ flatten order. Every spatial feature is W7: one [49, C] float32 array per 7 x 7 window
21
+ (``WindowTensor``, window 7) of a ``TokenGrid`` divisible by seven. A token is a pixel of
22
+ that grid. In PyTorch's terms (``mit_b0``, ``SegformerDecoder``)::
23
+
24
+ channel_norm LayerNorm over channels, eps 1e-5 (layer_norm) or 1e-6 (layer_norm2d)
25
+ overlap_embedding LN(Conv2d(x; k, stride s, padding k // 2)), (k, s) = (7, 4) or (3, 2)
26
+ spatial_reduction LN(Conv2d(x; r, stride r)) for r > 1; x itself for r = 1
27
+ shared_key_attention per head h of width d: softmax(q_h k_h^T * d^-0.5) v_h, concatenated
28
+ global_attention proj(shared_key_attention(q(x), kv(spatial_reduction(x))))
29
+ mix_ffn fc2(GELU(DWConv3x3(fc1(x)))), hidden width 4 C
30
+ mit_block x1 = x + attn(LN1(x)); out = x1 + mlp(LN2(x1))
31
+ project_pyramid cat(up(Linear(C4)), up(Linear(C3)), up(Linear(C2)), Linear(C1))
32
+ fuse_head up4(Conv1x1_head(ReLU(BN(Conv1x1_fuse(x)))))
33
+
34
+ The overlap embedding convolves at stride 1 on the fine grid (k 7: a ring-3 halo, im2col and
35
+ ``linear``; k 3: ``conv3x3_window``), then ``decimate`` samples phase (0, 0): pixel (i, j) of
36
+ the result is pixel (s i, s j) of the stride-1 map, exactly PyTorch's strided output. The
37
+ reduction's grid must be exactly one 7 x 7 window (a 7 r x 7 r chip): its 49 keys and values
38
+ are gathered once (``gather``) and shared by every query window, so the attention is global
39
+ without a per-window key or value. The pyramid's resizes are bilinear with
40
+ ``align_corners=False`` (factors 8, 4, 2; C1 unchanged), the head's is four-times bilinear
41
+ with ``align_corners=True``.
42
+
43
+ **Policy** ``composite``: the norms, projections, convolutions, GELU, BatchNorm, residual
44
+ additions and resizes run in ``double_round_once``, the attention core in ``round_each_op``
45
+ with SMP's post-QK scale (``score_scale``), ReLU and concatenation without arithmetic.
46
+ ``decimate`` has no arithmetic (``none``).
47
+
48
+ **Locality.** The global attention, its shared-key core and the MiT block read the whole chip
49
+ (``EXTENT``), and tiling with halos cannot reproduce them (chip-edge dependent); the
50
+ reduction makes the whole chip one window (``EXTENT``). The head's ``align_corners=True``
51
+ weights depend on the map's size (they are not shift-invariant), so ``fuse_head`` is
52
+ chip-edge dependent too, though it reads only a ring of one window.
53
+
54
+ **Rows.** Constants are built ahead for a layout (``LAYOUT``, ``WindowLayout(7)``: 49 rows),
55
+ pre-repeated to its rows because Earth Engine arrays do not broadcast, and the blocks refuse
56
+ constants built for another row count (client-side).
57
+
58
+ **Refused** (``reject``): a feature that is not W7 on a grid divisible by seven; norm epsilons
59
+ other than 1e-5 and 1e-6; overlap kernel and stride other than 7/4 and 3/2; decimation
60
+ factors other than 2 and 4; heads that do not divide the width; reduction ratios other than 1,
61
+ 2, 4 and 8; a reduced map that is not exactly one 7 x 7 window; a pyramid that is not four
62
+ levels at C1, C1/2, C1/4 and C1/8; head constants of other widths than ``channels`` and
63
+ ``classes``.
64
+
65
+ **Validated.** Live only inside the fixed SegFormer-B0 (``mit_b0``) at 224 x 224, two bands
66
+ and two classes: widths 32, 64, 160, 256, heads 1, 2, 5, 8, reduction ratios 8, 4, 2, 1,
67
+ window 7 and decoder width 256, by staged agreement on one seeded chip and state under the
68
+ 1e-4 absolute target (docs/evidence/segformer_b0-fullmodel-live.json), and as small
69
+ compositions (docs/evidence/segformer_b0-live.json). Other settings the builders accept,
70
+ such as the small fixture widths, are not validated.
71
+ """
72
+
73
+ from __future__ import annotations
74
+
75
+ from dataclasses import dataclass
76
+
77
+ import numpy as np
78
+
79
+ from ...core.errors import reject
80
+ from ...core.grid import TokenGrid, to_feature_grid, to_token_grid
81
+ from ...core.metadata import COMPOSITE, NO_ARITHMETIC, BlockMetadata, Locality, Validated, validate_metadata
82
+ from ...core.ops import ValueOps
83
+ from ...core.precision import DOUBLE_ROUND_ONCE, ROUND_EACH_OP
84
+ from ...core.tensor import WindowTensor, band_names
85
+ from ...layouts.raster import stride_sample_phase
86
+ from ...layouts.window import from_dense, halo, im2col, to_dense, to_windows
87
+ from ...weights.constants import ServerArray, WindowLayout, row_constant
88
+ from .activations import gelu, relu
89
+ from .attention import naive_attention
90
+ from .conv import METADATA as CONV_METADATA
91
+ from .conv import Conv3x3Constants, DepthwiseConv3x3Constants, conv3x3_window, depthwise_conv3x3_window
92
+ from .linear import METADATA as LINEAR_METADATA
93
+ from .linear import LinearConstants, conv1x1, conv1x1_constants, linear, no_constants
94
+ from .merge import add, concat
95
+ from .normalization import METADATA as NORM_METADATA
96
+ from .normalization import BatchNormConstants, batch_norm, layer_norm, layer_norm2d
97
+ from .patch import stride_columns
98
+ from .pooling import gather
99
+ from .resample import METADATA as RESIZE_METADATA
100
+ from .resample import window_resize
101
+
102
+ LAYOUT = WindowLayout(7)
103
+ """The layout every SegFormer composite runs in: window 7, 49 rows per constant."""
104
+
105
+
106
+ def _server_shape(value, name):
107
+ if not isinstance(value.shape, (tuple, list)):
108
+ reject(f"{name}: ServerArray shape must be a tuple or list of dimensions")
109
+ if any(isinstance(d, (bool, np.bool_)) or not isinstance(d, (int, np.integer)) or d < 1
110
+ for d in value.shape):
111
+ reject(f"{name}: ServerArray dimensions must be positive non-bool integers")
112
+ return tuple(int(d) for d in value.shape)
113
+
114
+
115
+ def _parameter(parameters, name, shape):
116
+ value = parameters[name]
117
+ if isinstance(value, ServerArray):
118
+ expected = (shape[0], int(np.prod(shape[1:]))) if len(shape) == 4 else shape
119
+ if _server_shape(value, name) != expected:
120
+ reject(f"{name}: ServerArray shape {value.shape}, expected {expected}")
121
+ elif (not isinstance(value, np.ndarray) or value.shape != shape or
122
+ value.dtype != np.float32 or not np.isfinite(value).all()):
123
+ reject(f"{name}: expected finite float32 NumPy shape {shape}")
124
+ return value
125
+
126
+
127
+ def _linear_constants(ops, p, name, cin, cout, layout):
128
+ return LinearConstants(ops, _parameter(p, f"{name}.weight", (cout, cin)),
129
+ _parameter(p, f"{name}.bias", (cout,)), layout)
130
+
131
+
132
+ def _conv_columns(ops, weight, cin, cout, kernel, *, tap_major):
133
+ """OIHW -> Linear [out,columns], moving coefficients without arithmetic.
134
+
135
+ halo/im2col has (ky,kx,c) columns; stride_columns has (c,ky,kx).
136
+ Server convolution weights arrive flattened in the latter PyTorch order.
137
+ """
138
+ if isinstance(weight, ServerArray):
139
+ if not tap_major:
140
+ return weight
141
+ arr = ValueOps(ops.ee)
142
+ w = arr.reshape(weight.array, [cout, cin, kernel * kernel])
143
+ w = arr.reshape(arr.transpose(w, 1, 2), [cout, kernel * kernel * cin])
144
+ return ServerArray(w, (cout, kernel * kernel * cin))
145
+ if tap_major:
146
+ return weight.transpose(0, 2, 3, 1).reshape(cout, kernel * kernel * cin)
147
+ return weight.reshape(cout, kernel * kernel * cin)
148
+
149
+
150
+ def _check_feature(x, *, channels=None, grid=None):
151
+ if not isinstance(x, WindowTensor) or x.window != 7 or getattr(x, "layout", "window") != "window":
152
+ reject("SegFormer compositions require W7 spatial features")
153
+ if not isinstance(x.grid, TokenGrid) or x.grid.height % 7 or x.grid.width % 7:
154
+ reject("features require a TokenGrid divisible by seven")
155
+ if channels is not None and x.channels != channels:
156
+ reject(f"feature has {x.channels} channels; expected {channels}")
157
+ if grid is not None and x.grid != grid:
158
+ reject(f"feature grid {x.grid} differs from expected {grid}")
159
+
160
+
161
+ # ---------------------------------------------------------------------------
162
+ # Channel norm
163
+ # ---------------------------------------------------------------------------
164
+ @dataclass
165
+ class NormConstants:
166
+ gamma: object
167
+ beta: object
168
+ channels: int
169
+ eps: float
170
+
171
+
172
+ def norm_constants(ops, parameters, prefix, channels, *, eps, layout=LAYOUT):
173
+ """Affine channel constants pre-repeated to the spatial layout's rows."""
174
+ if eps not in (1e-5, 1e-6):
175
+ reject("SegFormer norms use epsilon 1e-5 or 1e-6")
176
+ return NormConstants(row_constant(ops, _parameter(parameters, f"{prefix}.weight", (channels,)), layout),
177
+ row_constant(ops, _parameter(parameters, f"{prefix}.bias", (channels,)), layout),
178
+ channels, eps)
179
+
180
+
181
+ def channel_norm(ops, x, c: NormConstants):
182
+ """LayerNorm over the channels of a W7 feature: ``layer_norm`` at eps 1e-5 (the
183
+ embedding and reduction norms), ``layer_norm2d`` at eps 1e-6 (the block and stage norms)."""
184
+ _check_feature(x, channels=c.channels)
185
+ if c.eps == 1e-5:
186
+ image = layer_norm(ops, x.image, c.gamma, c.beta, dim=c.channels,
187
+ layout=x, eps=1e-5, policy=DOUBLE_ROUND_ONCE)
188
+ elif c.eps == 1e-6:
189
+ image = layer_norm2d(ops, x.image, c.gamma, c.beta, dim=c.channels,
190
+ rows=x, eps=1e-6, policy=DOUBLE_ROUND_ONCE)
191
+ else:
192
+ reject("malformed SegFormer norm epsilon")
193
+ return x.like(image)
194
+
195
+
196
+ # ---------------------------------------------------------------------------
197
+ # Overlapping patch embedding
198
+ # ---------------------------------------------------------------------------
199
+ @dataclass
200
+ class OverlapConstants:
201
+ projection: object
202
+ norm: NormConstants
203
+ cin: int
204
+ cout: int
205
+ kernel: int
206
+ stride: int
207
+
208
+
209
+ def overlap_constants(ops, parameters, prefix, cin, cout, *, kernel, stride, layout=LAYOUT):
210
+ """Biased overlapping embedding: supported k7/s4/p3 and k3/s2/p1 only.
211
+
212
+ This composition builder can use small fixture widths; the fixed model
213
+ constructor separately enforces every full-model state shape.
214
+ """
215
+ if (any(isinstance(v, (bool, np.bool_)) or not isinstance(v, (int, np.integer)) for v in (kernel, stride))
216
+ or (kernel, stride) not in ((7, 4), (3, 2))):
217
+ reject("overlap embeddings support k7/s4/p3 or k3/s2/p1 only")
218
+ weight = _parameter(parameters, f"{prefix}.proj.weight", (cout, cin, kernel, kernel))
219
+ bias = _parameter(parameters, f"{prefix}.proj.bias", (cout,))
220
+ projection = (LinearConstants(ops, _conv_columns(ops, weight, cin, cout, kernel, tap_major=True), bias, layout)
221
+ if kernel == 7 else Conv3x3Constants(ops, weight, bias, layout))
222
+ return OverlapConstants(projection, norm_constants(ops, parameters, f"{prefix}.norm", cout,
223
+ eps=1e-5, layout=layout), cin, cout, kernel, stride)
224
+
225
+
226
+ def decimate(ee, x, factor):
227
+ """Exact phase-(0,0) sample and explicit canonical relabel, with no arithmetic.
228
+
229
+ FeatureGrid supplies x0/y0 to stride_sample_phase; TokenGrid is never passed
230
+ directly to that sampler. Its pixel (i,j) is source (factor*i,factor*j).
231
+ """
232
+ _check_feature(x)
233
+ if isinstance(factor, (bool, np.bool_)) or not isinstance(factor, (int, np.integer)) or factor not in (2, 4):
234
+ reject("SegFormer decimation factors are two and four")
235
+ destination = x.grid.coarse(factor)
236
+ if destination.height % 7 or destination.width % 7:
237
+ reject("decimated map must partition into complete W7 windows")
238
+ fine = to_feature_grid(x.grid)
239
+ coarse = fine.coarse(factor)
240
+ canonical = to_token_grid(coarse)
241
+ dense = to_dense(ee, x.grid, x.image, x.channels, window=7)
242
+ sampled = stride_sample_phase(ee, dense, fine, factor, a=0, b=0)
243
+ relabeled = sampled.changeProj(coarse.projection(ee), canonical.projection(ee))
244
+ image = from_dense(ee, canonical, relabeled, x.channels, window=7)
245
+ return WindowTensor(image, canonical, x.channels, 7)
246
+
247
+
248
+ def overlap_embedding(ops, x, c: OverlapConstants) -> dict:
249
+ """The stride-1 convolution, ``decimate`` at the stride, then ``channel_norm`` (eps 1e-5)."""
250
+ _check_feature(x, channels=c.cin)
251
+ coarse = x.grid.coarse(7)
252
+ if c.kernel == 7 and c.stride == 4:
253
+ columns = im2col(ops.ee, halo(ops.ee, x.image, coarse, c.cin, window=7, ring=3),
254
+ c.cin, 7, window=7)
255
+ dense = linear(ops, columns, c.projection, layout=x, policy=DOUBLE_ROUND_ONCE)
256
+ elif c.kernel == 3 and c.stride == 2:
257
+ columns = None
258
+ dense = conv3x3_window(ops, x.image, c.projection, coarse, window=7, policy=DOUBLE_ROUND_ONCE)
259
+ else:
260
+ reject("malformed overlap constants")
261
+ dense = x.like(dense, c.cout)
262
+ projected = decimate(ops.ee, dense, c.stride)
263
+ return {"columns": columns, "dense_projection": dense, "projection": projected,
264
+ "out": channel_norm(ops, projected, c.norm)}
265
+
266
+
267
+ # ---------------------------------------------------------------------------
268
+ # Efficient attention: spatial reduction and global keys and values
269
+ # ---------------------------------------------------------------------------
270
+ @dataclass
271
+ class AttentionConstants:
272
+ q: LinearConstants
273
+ kv: LinearConstants
274
+ projection: LinearConstants
275
+ sr: object
276
+ sr_norm: object
277
+ dim: int
278
+ heads: int
279
+ ratio: int
280
+
281
+
282
+ def attention_constants(ops, parameters, prefix, dim, heads, ratio, *, layout=LAYOUT):
283
+ if (isinstance(heads, (bool, np.bool_)) or not isinstance(heads, (int, np.integer)) or heads < 1 or dim % heads or
284
+ isinstance(ratio, (bool, np.bool_)) or not isinstance(ratio, (int, np.integer)) or ratio not in (1, 2, 4, 8)):
285
+ reject("attention needs positive dividing heads and SR ratio 1/2/4/8")
286
+ sr, norm = None, None
287
+ if ratio > 1:
288
+ weight = _parameter(parameters, f"{prefix}.sr.weight", (dim, dim, ratio, ratio))
289
+ sr = LinearConstants(ops, _conv_columns(ops, weight, dim, dim, ratio, tap_major=False),
290
+ _parameter(parameters, f"{prefix}.sr.bias", (dim,)), layout)
291
+ norm = norm_constants(ops, parameters, f"{prefix}.norm", dim, eps=1e-5, layout=layout)
292
+ return AttentionConstants(_linear_constants(ops, parameters, f"{prefix}.q", dim, dim, layout),
293
+ _linear_constants(ops, parameters, f"{prefix}.kv", dim, 2 * dim, layout),
294
+ _linear_constants(ops, parameters, f"{prefix}.proj", dim, dim, layout),
295
+ sr, norm, dim, heads, ratio)
296
+
297
+
298
+ def spatial_reduction(ops, x, c: AttentionConstants) -> dict:
299
+ """Learned unpadded full-channel convolution of the normalized query input."""
300
+ _check_feature(x, channels=c.dim)
301
+ reduced_grid = x.grid.coarse(c.ratio)
302
+ if (reduced_grid.height, reduced_grid.width) != (7, 7):
303
+ reject("global reduced keys must cover exactly one 7 x 7 window")
304
+ if c.ratio == 1:
305
+ if c.sr is not None or c.sr_norm is not None:
306
+ reject("ratio-one attention has no SR convolution or normalization")
307
+ return {"columns": None, "projection": x, "out": x}
308
+ dense = to_dense(ops.ee, x.grid, x.image, x.channels, window=7)
309
+ # Keep Python's ordinary EE serialization recursion limit meaningful. Each
310
+ # existing stride_columns call gathers a bounded channel group; concatenating
311
+ # its value-only rows preserves (c,ky,kx) order and changes no arithmetic.
312
+ names = band_names(x.channels)
313
+ group = max(1, 128 // (c.ratio * c.ratio))
314
+ parts = [stride_columns(ops.ee, dense, x.grid, patch=c.ratio, bands=names[first:first + group])
315
+ for first in range(0, x.channels, group)]
316
+ columns = ops.cat_cols(parts)
317
+ windows = to_windows(ops.ee, columns, reduced_grid, window=7, mask=True)
318
+ projection = linear(ops, windows, c.sr, layout=x, policy=DOUBLE_ROUND_ONCE)
319
+ feature = WindowTensor(projection, reduced_grid, x.channels, 7)
320
+ return {"columns": columns, "projection": feature, "out": channel_norm(ops, feature, c.sr_norm)}
321
+
322
+
323
+ def shared_key_attention(ops, q, kv, heads: int) -> dict:
324
+ """Global V49 K/V shared dynamically by all W7 query windows.
325
+
326
+ q is W7 C channels; kv is the single reduced W7 window with 2C channels.
327
+ Each head computes [49,49] temporary scores, never a spatial tensor whose
328
+ channels or rows misrepresent the layout. Result images are pinned to q.
329
+ """
330
+ _check_feature(q)
331
+ _check_feature(kv, channels=2 * q.channels)
332
+ if ((kv.grid.height, kv.grid.width) != (7, 7) or isinstance(heads, (bool, np.bool_)) or
333
+ not isinstance(heads, (int, np.integer)) or heads < 1 or q.channels % heads):
334
+ reject("shared keys need one W7 window and heads dividing the query width")
335
+ arr = ValueOps(ops.ee)
336
+ global_kv = arr.reshape(gather(ops.ee, kv.image, kv.grid.coarse(7)), [49, kv.channels])
337
+ dim = q.channels // heads
338
+ result, outputs = {"kv_global": global_kv}, []
339
+ for h in range(heads):
340
+ query = ops.slice_cols(q.image, h * dim, (h + 1) * dim)
341
+ key = ops.wrap(arr.slice_cols(global_kv, h * dim, (h + 1) * dim))
342
+ value = ops.wrap(arr.slice_cols(global_kv, q.channels + h * dim, q.channels + (h + 1) * dim))
343
+ key = key.reproject(q.grid.coarse(7).projection(ops.ee))
344
+ value = value.reproject(q.grid.coarse(7).projection(ops.ee))
345
+ head = naive_attention(ops, query, key, value, tokens=49, dim=dim,
346
+ score_scale=dim ** -0.5, policy=ROUND_EACH_OP)
347
+ result.update({f"h{h}_{name}": tensor for name, tensor in head.items()})
348
+ outputs.append(head["output"])
349
+ combined = ops.cat_cols(outputs).reproject(q.grid.coarse(7).projection(ops.ee))
350
+ result["out"] = q.like(combined)
351
+ return result
352
+
353
+
354
+ def global_attention(ops, x, c: AttentionConstants) -> dict:
355
+ """SMP's efficient self-attention: the query projection, ``spatial_reduction``, the key and
356
+ value projection, ``shared_key_attention`` and the output projection."""
357
+ _check_feature(x, channels=c.dim)
358
+ q = x.like(linear(ops, x.image, c.q, layout=x, policy=DOUBLE_ROUND_ONCE))
359
+ reduction = spatial_reduction(ops, x, c)
360
+ reduced = reduction["out"]
361
+ kv = reduced.like(linear(ops, reduced.image, c.kv, layout=reduced, policy=DOUBLE_ROUND_ONCE), 2 * c.dim)
362
+ result = shared_key_attention(ops, q, kv, c.heads)
363
+ combined = result["out"]
364
+ projected = x.like(linear(ops, combined.image, c.projection, layout=x, policy=DOUBLE_ROUND_ONCE))
365
+ result.update({"q": q, "sr_projection": reduction["projection"], "sr_norm": reduced,
366
+ "kv": kv, "concat": combined, "out": projected})
367
+ return result
368
+
369
+
370
+ # ---------------------------------------------------------------------------
371
+ # Mix-FFN and the MiT block
372
+ # ---------------------------------------------------------------------------
373
+ @dataclass
374
+ class MixFFNConstants:
375
+ fc1: LinearConstants
376
+ depthwise: DepthwiseConv3x3Constants
377
+ fc2: LinearConstants
378
+ dim: int
379
+
380
+
381
+ def mix_ffn_constants(ops, parameters, prefix, dim, *, layout=LAYOUT):
382
+ width = 4 * dim
383
+ dw = f"{prefix}.dwconv.dwconv"
384
+ depthwise = DepthwiseConv3x3Constants(ops, _parameter(parameters, f"{dw}.weight", (width, 1, 3, 3)),
385
+ _parameter(parameters, f"{dw}.bias", (width,)), rows=layout,
386
+ policy=DOUBLE_ROUND_ONCE)
387
+ return MixFFNConstants(_linear_constants(ops, parameters, f"{prefix}.fc1", dim, width, layout),
388
+ depthwise, _linear_constants(ops, parameters, f"{prefix}.fc2", width, dim, layout), dim)
389
+
390
+
391
+ def mix_ffn(ops, x, c: MixFFNConstants) -> dict:
392
+ """fc1, the depthwise 3 x 3 convolution (zero padded at the chip edge), exact GELU, fc2."""
393
+ _check_feature(x, channels=c.dim)
394
+ first = x.like(linear(ops, x.image, c.fc1, layout=x, policy=DOUBLE_ROUND_ONCE), 4 * c.dim)
395
+ depthwise = first.like(depthwise_conv3x3_window(ops, first.image, c.depthwise, first.grid.coarse(7),
396
+ window=7, policy=DOUBLE_ROUND_ONCE))
397
+ activated = depthwise.like(gelu(ops, depthwise.image, policy=DOUBLE_ROUND_ONCE))
398
+ out = x.like(linear(ops, activated.image, c.fc2, layout=activated, policy=DOUBLE_ROUND_ONCE))
399
+ return {"fc1": first, "depthwise": depthwise, "gelu": activated, "out": out}
400
+
401
+
402
+ @dataclass
403
+ class MiTBlockConstants:
404
+ norm1: NormConstants
405
+ attention: AttentionConstants
406
+ norm2: NormConstants
407
+ mlp: MixFFNConstants
408
+
409
+
410
+ def mit_block_constants(ops, parameters, prefix, dim, heads, ratio):
411
+ return MiTBlockConstants(norm_constants(ops, parameters, f"{prefix}.norm1", dim, eps=1e-6),
412
+ attention_constants(ops, parameters, f"{prefix}.attn", dim, heads, ratio),
413
+ norm_constants(ops, parameters, f"{prefix}.norm2", dim, eps=1e-6),
414
+ mix_ffn_constants(ops, parameters, f"{prefix}.mlp", dim))
415
+
416
+
417
+ def mit_block(ops, x, c: MiTBlockConstants) -> dict:
418
+ """One MiT block: ``channel_norm``, ``global_attention`` and a residual addition, then
419
+ ``channel_norm``, ``mix_ffn`` and a residual addition."""
420
+ norm1 = channel_norm(ops, x, c.norm1)
421
+ attention = global_attention(ops, norm1, c.attention)
422
+ first = add(x, attention["out"], policy=DOUBLE_ROUND_ONCE)
423
+ norm2 = channel_norm(ops, first, c.norm2)
424
+ mlp = mix_ffn(ops, norm2, c.mlp)
425
+ return {"norm1": norm1, "attention": attention, "first_residual": first,
426
+ "norm2": norm2, "mlp": mlp, "out": add(first, mlp["out"], policy=DOUBLE_ROUND_ONCE)}
427
+
428
+
429
+ # ---------------------------------------------------------------------------
430
+ # All-MLP decoder
431
+ # ---------------------------------------------------------------------------
432
+ def project_pyramid_constants(ops, parameters, prefixes, in_channels, channels: int, *, layout=LAYOUT) -> tuple:
433
+ """``project_pyramid``'s four biased projections, deepest first as it takes them: projection
434
+ ``i`` is the [``channels``, ``in_channels[i]``] ``weight`` and the ``bias`` under ``prefixes[i]``
435
+ (SMP: ``decoder.mlp_stage.{i}.linear``, C4 first)."""
436
+ if isinstance(prefixes, str) or len(prefixes) != 4 or len(in_channels) != 4:
437
+ reject("SegFormer pyramid requires four levels and four projections")
438
+ return tuple(_linear_constants(ops, parameters, prefix, cin, channels, layout)
439
+ for prefix, cin in zip(prefixes, in_channels))
440
+
441
+
442
+ def project_pyramid(ops, features, projections) -> dict:
443
+ """Project/resize/concat four W7 levels; projections are deepest-first.
444
+
445
+ Small fixture widths are permitted here; decoder() separately enforces the
446
+ fixed full-model shape contract. Equal-size interpolation is an identity.
447
+ """
448
+ if len(features) != 4 or len(projections) != 4:
449
+ reject("SegFormer pyramid requires four levels and four projections")
450
+ target = features[0].grid
451
+ result, parts = {}, []
452
+ for i, (feature, projection) in enumerate(zip(reversed(features), projections)):
453
+ _check_feature(feature, channels=projection.in_features)
454
+ factor = 2 ** (3 - i)
455
+ if feature.grid.fine(factor) != target:
456
+ reject("pyramid feature grids must be C1, C1/2, C1/4, C1/8")
457
+ image = linear(ops, feature.image, projection, layout=feature, policy=DOUBLE_ROUND_ONCE)
458
+ projected = feature.like(image, projection.out_features)
459
+ result[f"C{4 - i}_projected"] = projected
460
+ if factor > 1:
461
+ image, fine = window_resize(ops.ee, image, feature.grid, projected.channels, factor,
462
+ align_corners=False, window=7, policy=DOUBLE_ROUND_ONCE)
463
+ else:
464
+ fine = feature.grid
465
+ resized = WindowTensor(image, fine, projected.channels, 7)
466
+ result[f"C{4 - i}_to_C1"] = resized
467
+ parts.append(resized)
468
+ result["out"] = concat(parts)
469
+ return result
470
+
471
+
472
+ def fuse_head_constants(ops, parameters, prefixes, in_channels: int, channels: int, classes: int, *,
473
+ eps: float, layout=LAYOUT) -> tuple:
474
+ """``fuse_head``'s constants ``(fusion, norm, head)`` from the three layers ``prefixes`` names
475
+ (SMP: ``decoder.fuse_stage.0``, ``decoder.fuse_stage.1``, ``segmentation_head.0``): the bias-free
476
+ fuse ``weight`` [``channels``, ``in_channels``, 1, 1]; the BatchNorm's ``weight``, ``bias``,
477
+ ``running_mean`` and ``running_var`` with ``eps``; the head ``weight`` [``classes``, ``channels``,
478
+ 1, 1] and its ``bias``."""
479
+ if isinstance(prefixes, str) or len(prefixes) != 3:
480
+ reject("the fused head reads three layers: the fusion, the BatchNorm and the head")
481
+ fusion, norm, head = prefixes
482
+ return (conv1x1_constants(ops, _parameter(parameters, f"{fusion}.weight", (channels, in_channels, 1, 1)),
483
+ None, layout),
484
+ BatchNormConstants(ops, *(_parameter(parameters, f"{norm}.{name}", (channels,))
485
+ for name in ("weight", "bias", "running_mean", "running_var")),
486
+ rows=layout, eps=eps),
487
+ conv1x1_constants(ops, _parameter(parameters, f"{head}.weight", (classes, channels, 1, 1)),
488
+ _parameter(parameters, f"{head}.bias", (classes,)), layout))
489
+
490
+
491
+ def fuse_head(ops, x, fusion, norm, head, *, channels: int, classes: int) -> dict:
492
+ """The fused pyramid ``x`` -> W7 logits four times finer: the bias-free fuse ``conv1x1``
493
+ (``fusion``, to ``channels``), inference ``batch_norm`` (``norm``), ``relu``, the biased head
494
+ ``conv1x1`` (``head``, to ``classes``) and four-times ``window_resize`` with
495
+ ``align_corners=True``. Graph construction only; constants of other widths are refused."""
496
+ if fusion.out_features != channels or head.out_features != classes:
497
+ reject(f"fuse and head constants must have {channels} and {classes} outputs")
498
+ fused = x.like(conv1x1(ops, x.image, fusion, layout=x, policy=DOUBLE_ROUND_ONCE), channels)
499
+ normalized = fused.like(batch_norm(ops, fused.image, norm, layout=fused, policy=DOUBLE_ROUND_ONCE))
500
+ activated = normalized.like(relu(ops, normalized.image))
501
+ logits = activated.like(conv1x1(ops, activated.image, head, layout=activated, policy=DOUBLE_ROUND_ONCE),
502
+ classes)
503
+ image, grid = window_resize(ops.ee, logits.image, logits.grid, classes, 4, align_corners=True,
504
+ window=7, policy=DOUBLE_ROUND_ONCE)
505
+ return {"fusion": fused, "batch_norm": normalized, "relu": activated, "head": logits,
506
+ "out": WindowTensor(image, grid, classes, 7)}
507
+
508
+
509
+ # ---------------------------------------------------------------------------
510
+ # Cost functions (contract section 9): sums of the parts' METADATA cost functions
511
+ # ---------------------------------------------------------------------------
512
+ _PARTS = {**LINEAR_METADATA, **NORM_METADATA, **CONV_METADATA, **RESIZE_METADATA}
513
+ """The parts' entries by block name: a composite's cost is the sum of its parts' costs."""
514
+
515
+
516
+ def channel_norm_values(channels: int, *, layout=LAYOUT) -> int:
517
+ """gamma and beta [rows, C] (``layer_norm`` and ``layer_norm2d`` count alike)."""
518
+ return _PARTS["layer_norm"].embedded_constants(channels, layout=layout)
519
+
520
+
521
+ def channel_norm_arrays() -> int:
522
+ """Server arrays read: gamma and beta."""
523
+ return _PARTS["layer_norm"].asset_arrays()
524
+
525
+
526
+ def overlap_embedding_values(cin: int, cout: int, *, kernel: int, layout=LAYOUT) -> int:
527
+ """The k x k projection with its bias rows (``linear`` on k k Cin columns at k 7,
528
+ ``conv3x3_window`` at k 3), and the norm."""
529
+ if kernel not in (7, 3):
530
+ reject("overlap embeddings support k7/s4/p3 or k3/s2/p1 only")
531
+ projection = (_PARTS["linear"].embedded_constants(kernel * kernel * cin, cout, bias=True, layout=layout)
532
+ if kernel == 7 else
533
+ _PARTS["conv3x3_window"].embedded_constants(cin, cout, bias=True, layout=layout))
534
+ return projection + channel_norm_values(cout, layout=layout)
535
+
536
+
537
+ def overlap_embedding_arrays() -> int:
538
+ """Server arrays read: the projection's weight and bias, and the norm's gamma and beta."""
539
+ return _PARTS["linear"].asset_arrays(bias=True) + channel_norm_arrays()
540
+
541
+
542
+ def spatial_reduction_values(dim: int, ratio: int, *, layout=LAYOUT) -> int:
543
+ """The r x r reduction as a ``linear`` on r r C columns with its bias rows, and its norm;
544
+ nothing at ratio 1."""
545
+ if ratio == 1:
546
+ return 0
547
+ return (_PARTS["linear"].embedded_constants(ratio * ratio * dim, dim, bias=True, layout=layout)
548
+ + channel_norm_values(dim, layout=layout))
549
+
550
+
551
+ def spatial_reduction_arrays(*, ratio: int) -> int:
552
+ """Server arrays read: the reduction's weight and bias and its norm's; none at ratio 1."""
553
+ return 0 if ratio == 1 else _PARTS["linear"].asset_arrays(bias=True) + channel_norm_arrays()
554
+
555
+
556
+ def global_attention_values(dim: int, ratio: int, *, layout=LAYOUT) -> int:
557
+ """The q [C, C], kv [C, 2C] and output [C, C] projections with their bias rows, and the
558
+ spatial reduction (``shared_key_attention`` embeds nothing; the heads cost nothing)."""
559
+ linear_values = _PARTS["linear"].embedded_constants
560
+ return (linear_values(dim, dim, layout=layout) + linear_values(dim, 2 * dim, layout=layout)
561
+ + linear_values(dim, dim, layout=layout) + spatial_reduction_values(dim, ratio, layout=layout))
562
+
563
+
564
+ def global_attention_arrays(*, ratio: int) -> int:
565
+ """Server arrays read: the three projections' weights and biases, and the reduction's."""
566
+ return 3 * _PARTS["linear"].asset_arrays(bias=True) + spatial_reduction_arrays(ratio=ratio)
567
+
568
+
569
+ def mix_ffn_values(dim: int, *, layout=LAYOUT) -> int:
570
+ """fc1 [C, 4C], the biased depthwise convolution of width 4C, and fc2 [4C, C]."""
571
+ linear_values = _PARTS["linear"].embedded_constants
572
+ return (linear_values(dim, 4 * dim, layout=layout)
573
+ + _PARTS["depthwise_conv3x3_window"].embedded_constants(4 * dim, bias=True, layout=layout)
574
+ + linear_values(4 * dim, dim, layout=layout))
575
+
576
+
577
+ def mix_ffn_arrays() -> int:
578
+ """Server arrays read: fc1, the depthwise convolution and fc2, each a weight and a bias."""
579
+ return (2 * _PARTS["linear"].asset_arrays(bias=True)
580
+ + _PARTS["depthwise_conv3x3_window"].asset_arrays(bias=True))
581
+
582
+
583
+ def mit_block_values(dim: int, ratio: int, *, layout=LAYOUT) -> int:
584
+ """Two channel norms, the global attention and the Mix-FFN (the additions embed nothing)."""
585
+ return (2 * channel_norm_values(dim, layout=layout) + global_attention_values(dim, ratio, layout=layout)
586
+ + mix_ffn_values(dim, layout=layout))
587
+
588
+
589
+ def mit_block_arrays(*, ratio: int) -> int:
590
+ """Server arrays read: two norms, the global attention and the Mix-FFN."""
591
+ return 2 * channel_norm_arrays() + global_attention_arrays(ratio=ratio) + mix_ffn_arrays()
592
+
593
+
594
+ def project_pyramid_values(in_channels, channels: int, height: int, width: int, *, layout=LAYOUT) -> int:
595
+ """Four projections, ``in_channels`` (the C1, C2, C3, C4 widths) to ``channels``, with their
596
+ bias rows, and the ``align_corners=False`` resize tables of C2, C3 and C4 (height / 2^k by
597
+ width / 2^k tokens, factor 2^k) onto C1's ``height`` x ``width`` tokens."""
598
+ if len(in_channels) != 4:
599
+ reject("SegFormer pyramid requires four levels and four projections")
600
+ projections = sum(_PARTS["linear"].embedded_constants(c, channels, layout=layout) for c in in_channels)
601
+ return projections + sum(_PARTS["window_resize"].embedded_constants(height // 2 ** k, width // 2 ** k, 2 ** k,
602
+ align_corners=False, window=7)
603
+ for k in (1, 2, 3))
604
+
605
+
606
+ def project_pyramid_arrays() -> int:
607
+ """Server arrays read: the four projections' weights and biases (resize tables are inline)."""
608
+ return 4 * _PARTS["linear"].asset_arrays(bias=True)
609
+
610
+
611
+ def fuse_head_values(in_channels: int, channels: int, classes: int, height: int, width: int, *,
612
+ layout=LAYOUT) -> int:
613
+ """The bias-free fuse [in, channels], the BatchNorm rows, the biased head [channels, classes]
614
+ and the four-times ``align_corners=True`` resize table of a ``height`` x ``width`` token map."""
615
+ return (_PARTS["conv1x1"].embedded_constants(in_channels, channels, bias=False, layout=layout)
616
+ + _PARTS["batch_norm"].embedded_constants(channels, layout=layout)
617
+ + _PARTS["conv1x1"].embedded_constants(channels, classes, bias=True, layout=layout)
618
+ + _PARTS["window_resize"].embedded_constants(height, width, 4, align_corners=True, window=7))
619
+
620
+
621
+ def fuse_head_arrays() -> int:
622
+ """Server arrays read: the fuse weight, the four BatchNorm vectors, the head weight and bias."""
623
+ return (_PARTS["conv1x1"].asset_arrays(bias=False) + _PARTS["batch_norm"].asset_arrays()
624
+ + _PARTS["conv1x1"].asset_arrays(bias=True))
625
+
626
+
627
+ # ---------------------------------------------------------------------------
628
+ # Metadata
629
+ # ---------------------------------------------------------------------------
630
+ # Validated live only inside the fixed SegFormer-B0: the whole model's staged agreement, and
631
+ # small compositions (overlap, reduction, global keys, norms, Mix-FFN, pyramid, head).
632
+ _STATUS = "Fixed — SegFormer-B0 (mit_b0) at 224 × 224: "
633
+ _MODEL = "widths 32, 64, 160, 256; heads 1, 2, 5, 8; reduction ratios 8, 4, 2, 1; window 7"
634
+ _EVIDENCE = ("docs/evidence/segformer_b0-fullmodel-live.json", "docs/evidence/segformer_b0-live.json")
635
+
636
+ # Validated settings: SegFormer-B0's, named by the constants builders' parameters (the
637
+ # block graph's settings, tensor_ee/converter/operations.py) and joined per stage.
638
+ _WIDTHS = (32, 64, 160, 256)
639
+ _STAGES = tuple({"dim": (dim,), "heads": (heads,), "ratio": (ratio,), "window": (7,)}
640
+ for dim, heads, ratio in zip(_WIDTHS, (1, 2, 5, 8), (8, 4, 2, 1)))
641
+ _EMBEDDINGS = tuple({"cin": (cin,), "cout": (cout,), "kernel": (kernel,), "stride": (stride,), "window": (7,)}
642
+ for cin, cout, kernel, stride in ((2, 32, 7, 4), (32, 64, 3, 2), (64, 160, 3, 2), (160, 256, 3, 2)))
643
+
644
+ METADATA = validate_metadata({
645
+ "channel_norm": BlockMetadata(
646
+ name="channel_norm", layout_in="W", layout_out="W", locality=Locality.POINTWISE,
647
+ policy=COMPOSITE, embedded_constants=channel_norm_values, asset_arrays=channel_norm_arrays,
648
+ status=_STATUS + "widths 32, 64, 160, 256; eps 1e-5, 1e-6; window 7",
649
+ evidence=_EVIDENCE + ("parts: layer_norm (eps 1e-5) or layer_norm2d (eps 1e-6), double_round_once",),
650
+ validated=Validated(({"channels": _WIDTHS, "eps": (1e-5, 1e-6), "window": (7,)},), sources=(norm_constants,))),
651
+ "decimate": BlockMetadata(
652
+ # A stride-f sample reads within each output token's f x f footprint: k x k, radius
653
+ # f // 2 at the largest factor (4), as stride_columns counts its patch.
654
+ name="decimate", layout_in="W", layout_out="W", locality=Locality.KERNEL, radius=2,
655
+ policy=NO_ARITHMETIC, embedded_constants=no_constants, asset_arrays=no_constants,
656
+ status=_STATUS + "factor 4 at width 32, factor 2 at widths 64, 160, 256; window 7",
657
+ evidence=_EVIDENCE,
658
+ # decimate moves values and takes no width: the widths say where the model ran each factor.
659
+ validated=Validated(({"factor": (2, 4), "window": (7,)},))),
660
+ "overlap_embedding": BlockMetadata(
661
+ name="overlap_embedding", layout_in="W", layout_out="W", locality=Locality.KERNEL, radius=3,
662
+ policy=COMPOSITE, embedded_constants=overlap_embedding_values, asset_arrays=overlap_embedding_arrays,
663
+ status=_STATUS + "k7/s4 2 → 32; k3/s2 32 → 64, 64 → 160, 160 → 256; window 7",
664
+ evidence=_EVIDENCE + ("parts: linear or conv3x3_window and layer_norm (double_round_once), decimate (none)",),
665
+ validated=Validated(_EMBEDDINGS, sources=(overlap_constants,))),
666
+ "spatial_reduction": BlockMetadata(
667
+ name="spatial_reduction", layout_in="W", layout_out="W", locality=Locality.EXTENT,
668
+ policy=COMPOSITE, embedded_constants=spatial_reduction_values, asset_arrays=spatial_reduction_arrays,
669
+ status=_STATUS + "widths 32, 64, 160, 256 at reduction ratios 8, 4, 2, 1; window 7",
670
+ evidence=_EVIDENCE + ("parts: stride_columns (none), linear and layer_norm (double_round_once)",),
671
+ validated=Validated(tuple({name: stage[name] for name in ("dim", "ratio", "window")} for stage in _STAGES),
672
+ sources=(attention_constants,))),
673
+ "shared_key_attention": BlockMetadata(
674
+ name="shared_key_attention", layout_in="W", layout_out="W", locality=Locality.EXTENT,
675
+ policy=COMPOSITE, embedded_constants=no_constants, asset_arrays=no_constants,
676
+ chip_edge_dependent=True,
677
+ status=_STATUS + "widths 32, 64, 160, 256; heads 1, 2, 5, 8; one 7 × 7 key window",
678
+ evidence=_EVIDENCE + ("parts: gather (none), naive_attention (round_each_op)",),
679
+ validated=Validated(tuple({name: stage[name] for name in ("dim", "heads", "window")} for stage in _STAGES),
680
+ sources=(attention_constants,))),
681
+ "global_attention": BlockMetadata(
682
+ name="global_attention", layout_in="W", layout_out="W", locality=Locality.EXTENT,
683
+ policy=COMPOSITE, embedded_constants=global_attention_values, asset_arrays=global_attention_arrays,
684
+ chip_edge_dependent=True, status=_STATUS + _MODEL,
685
+ evidence=_EVIDENCE + ("parts: linear (double_round_once), spatial_reduction, shared_key_attention",),
686
+ validated=Validated(_STAGES, sources=(attention_constants,))),
687
+ "mix_ffn": BlockMetadata(
688
+ name="mix_ffn", layout_in="W", layout_out="W", locality=Locality.WINDOW_RING, radius=1,
689
+ policy=COMPOSITE, embedded_constants=mix_ffn_values, asset_arrays=mix_ffn_arrays,
690
+ status=_STATUS + "widths 32, 64, 160, 256, hidden 4 × width; window 7",
691
+ evidence=_EVIDENCE + ("parts: linear, depthwise_conv3x3_window, gelu (double_round_once)",),
692
+ validated=Validated(({"dim": _WIDTHS, "window": (7,)},), sources=(mix_ffn_constants,))),
693
+ "mit_block": BlockMetadata(
694
+ name="mit_block", layout_in="W", layout_out="W", locality=Locality.EXTENT,
695
+ policy=COMPOSITE, embedded_constants=mit_block_values, asset_arrays=mit_block_arrays,
696
+ chip_edge_dependent=True, status=_STATUS + _MODEL,
697
+ evidence=_EVIDENCE + ("parts: channel_norm, global_attention, mix_ffn, add (double_round_once)",),
698
+ validated=Validated(_STAGES, sources=(mit_block_constants,))),
699
+ "project_pyramid": BlockMetadata(
700
+ name="project_pyramid", layout_in="W", layout_out="W", locality=Locality.WINDOW_RING, radius=1,
701
+ policy=COMPOSITE, embedded_constants=project_pyramid_values, asset_arrays=project_pyramid_arrays,
702
+ status=_STATUS + "widths 32, 64, 160, 256 to 256 on C1 56 × 56; window 7",
703
+ evidence=_EVIDENCE + ("parts: linear and window_resize (double_round_once), concat (none)",),
704
+ # in_channels deepest first, as project_pyramid_constants takes them; height x width is C1's.
705
+ validated=Validated(({"in_channels": (_WIDTHS[::-1],), "channels": (256,), "height": (56,), "width": (56,),
706
+ "window": (7,)},), sources=(project_pyramid_constants,))),
707
+ "fuse_head": BlockMetadata(
708
+ # Chip-edge dependent: the four-times resize's align_corners=True weights depend on the
709
+ # map's size and are not shift-invariant, so tiling with halos cannot reproduce them.
710
+ name="fuse_head", layout_in="W", layout_out="W", locality=Locality.WINDOW_RING, radius=1,
711
+ policy=COMPOSITE, embedded_constants=fuse_head_values, asset_arrays=fuse_head_arrays,
712
+ chip_edge_dependent=True,
713
+ status=_STATUS + "1024 → 256 channels → 2 classes, 56 × 56 to 224 × 224; window 7",
714
+ evidence=_EVIDENCE + ("parts: conv1x1, batch_norm and window_resize (double_round_once), relu (none)",),
715
+ # The BatchNorm's eps 1e-5 never varied; height x width is the input's (C1).
716
+ validated=Validated(({"in_channels": (1024,), "channels": (256,), "classes": (2,), "eps": (1e-5,),
717
+ "height": (56,), "width": (56,), "window": (7,)},), sources=(fuse_head_constants,))),
718
+ })