Skip to content

Commit bce7c8b

Browse files
[BugFix] pre-commit
1 parent 5c74bf0 commit bce7c8b

2 files changed

Lines changed: 36 additions & 31 deletions

File tree

stable_pretraining/backbone/video/recurrent_vit.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
spatial stack uses an additive learned pos embed.
1717
- Per-frame CLS token prepended; the full ``(1+P, D)`` sequence goes through
1818
``spatial_depth`` :class:`~stable_pretraining.backbone.vit.TransformerBlock`
19-
layers (``self_attn=True, use_rope=None, use_qk_norm=True, mlp_type='gelu'``).
19+
layers (``self_attn=True, use_rope=None, mlp_type='gelu'``). QK-norm is
20+
off by default and only enabled on the ``huge`` preset.
2021
- ``LayerNorm`` (``norm_s``) then split: CLS → ``(B, T, D)``, patches →
2122
``(B, T, P, D)``.
2223
- ``nn.GRU(D, D, num_layers=gru_layers, batch_first=True)`` walks the CLS
@@ -47,8 +48,8 @@
4748
x = torch.randn(2, 3, 8, 64, 64)
4849
out = enc(x)
4950
out.feature_map.shape # (2, 192, 8, 8, 8)
50-
out.pooled.shape # (2, 192)
51-
out.tokens.shape # (2, 8, 192)
51+
out.pooled.shape # (2, 192)
52+
out.tokens.shape # (2, 8, 192)
5253
"""
5354

5455
from __future__ import annotations
@@ -244,8 +245,10 @@ def forward(
244245
# (B, 1, D) -> broadcast to (B*T, 1, D) so each frame of clip i
245246
# carries clip i's cam embedding.
246247
ce = self.cam_embed[cam_id]
247-
ce = ce.unsqueeze(1).expand(B, T, 1, self.embed_dim).reshape(
248-
B * T, 1, self.embed_dim
248+
ce = (
249+
ce.unsqueeze(1)
250+
.expand(B, T, 1, self.embed_dim)
251+
.reshape(B * T, 1, self.embed_dim)
249252
)
250253
x = x + ce
251254

@@ -270,13 +273,9 @@ def forward(
270273
.permute(0, 4, 1, 2, 3)
271274
.contiguous()
272275
)
273-
pooled = (
274-
feature_map.mean(dim=(2, 3, 4)) if self.global_pool == "avg" else None
275-
)
276+
pooled = feature_map.mean(dim=(2, 3, 4)) if self.global_pool == "avg" else None
276277

277-
return RecurrentViTOutput(
278-
feature_map=feature_map, pooled=pooled, tokens=tokens
279-
)
278+
return RecurrentViTOutput(feature_map=feature_map, pooled=pooled, tokens=tokens)
280279

281280

282281
# -----------------------------------------------------------------------------

stable_pretraining/tests/unit/test_recurrent_vit.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ class TestRecurrentViTShapes:
2222
"""Output shape and dataclass contract."""
2323

2424
def test_recurrent_vit_shapes(self):
25-
"""Default tiny on a (2, 3, 8, 64, 64) clip produces the documented
26-
``feature_map`` / ``pooled`` / ``tokens`` shapes."""
25+
"""Default tiny produces the documented output shapes.
26+
27+
Input ``(2, 3, 8, 64, 64)`` → ``feature_map=(2, 192, 8, 8, 8)``,
28+
``pooled=(2, 192)``, ``tokens=(2, 8, 192)``.
29+
"""
2730
torch.manual_seed(0)
2831
enc = recurrent_vit_tiny()
2932
enc.eval()
@@ -37,8 +40,7 @@ def test_recurrent_vit_shapes(self):
3740
assert out.tokens.shape == (2, 8, 192)
3841

3942
def test_no_pool(self):
40-
"""``global_pool=''`` zeroes the pooled slot but keeps feature_map and
41-
tokens populated."""
43+
"""``global_pool=''`` drops the pooled slot but keeps feature_map and tokens."""
4244
m = RecurrentViT(
4345
img_size=32,
4446
patch_size=8,
@@ -70,9 +72,12 @@ def test_rejects_wrong_spatial_size(self):
7072

7173
@pytest.mark.unit
7274
class TestNoFutureLeakage:
73-
"""The GRU on the pooled CLS sequence makes the model causal in time;
74-
the per-frame ViT can't leak future info either because frames are
75-
encoded independently."""
75+
"""Causality of feature_map and tokens.
76+
77+
The GRU on the pooled CLS sequence makes ``tokens`` causal in time;
78+
the per-frame ViT can't leak future info into ``feature_map`` either,
79+
because frames are encoded independently.
80+
"""
7681

7782
def test_no_future_leakage(self):
7883
torch.manual_seed(0)
@@ -92,21 +97,19 @@ def test_no_future_leakage(self):
9297
out_a.feature_map[:, :, 4:], out_b.feature_map[:, :, 4:], atol=1e-5
9398
)
9499
# tokens are GRU output: causal by construction.
95-
assert torch.allclose(
96-
out_a.tokens[:, :4], out_b.tokens[:, :4], atol=1e-5
97-
)
98-
assert not torch.allclose(
99-
out_a.tokens[:, 4:], out_b.tokens[:, 4:], atol=1e-5
100-
)
100+
assert torch.allclose(out_a.tokens[:, :4], out_b.tokens[:, :4], atol=1e-5)
101+
assert not torch.allclose(out_a.tokens[:, 4:], out_b.tokens[:, 4:], atol=1e-5)
101102

102103

103104
@pytest.mark.unit
104105
class TestFactoryParamCounts:
105-
"""Each preset's total parameter count must be in the documented
106-
ViT-family budget ballpark. Tolerance is ±20%: the targets are
107-
standard-ViT-shaped approximations, and the GRU + patch embed + QK-norm
108-
each shift the count by a few percent, so a single fixed target won't
109-
sit at the center of every preset."""
106+
"""Each preset lands in the documented ViT-family param budget.
107+
108+
Tolerance is ±20%: the targets are standard-ViT-shaped approximations,
109+
and the GRU + patch embed + QK-norm each shift the count by a few
110+
percent, so a single fixed target won't sit at the center of every
111+
preset.
112+
"""
110113

111114
@pytest.mark.parametrize(
112115
"factory,target",
@@ -133,8 +136,11 @@ def test_factory_param_counts(self, factory, target):
133136

134137
@pytest.mark.unit
135138
class TestSmallerPresetsForward:
136-
"""Smoke-forward the smaller presets so we cover the GRU path on a real
137-
tensor without paying the large preset's memory cost."""
139+
"""Real-tensor smoke forward for the smaller presets.
140+
141+
Exercises the GRU path on a real tensor without paying the large
142+
preset's memory cost.
143+
"""
138144

139145
@pytest.mark.parametrize("factory", [recurrent_vit_tiny, recurrent_vit_small])
140146
def test_forward_runs(self, factory):

0 commit comments

Comments
 (0)