Equimo 0.2.0__tar.gz → 0.2.1__tar.gz

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 (39) hide show
  1. {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/PKG-INFO +10 -1
  2. {equimo-0.2.0 → equimo-0.2.1}/PKG-INFO +10 -1
  3. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/attention.py +50 -0
  4. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/ffn.py +56 -2
  5. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/norm.py +24 -0
  6. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/vit.py +17 -6
  7. {equimo-0.2.0 → equimo-0.2.1}/equimo/utils.py +1 -0
  8. {equimo-0.2.0 → equimo-0.2.1}/pyproject.toml +16 -1
  9. {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/SOURCES.txt +0 -0
  10. {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/dependency_links.txt +0 -0
  11. {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/requires.txt +0 -0
  12. {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/top_level.txt +0 -0
  13. {equimo-0.2.0 → equimo-0.2.1}/LICENSE.md +0 -0
  14. {equimo-0.2.0 → equimo-0.2.1}/README.md +0 -0
  15. {equimo-0.2.0 → equimo-0.2.1}/equimo/__init__.py +0 -0
  16. {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/__init__.py +0 -0
  17. {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/dinov2.py +0 -0
  18. {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/utils.py +0 -0
  19. {equimo-0.2.0 → equimo-0.2.1}/equimo/io.py +0 -0
  20. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/__init__.py +0 -0
  21. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/convolution.py +0 -0
  22. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/downsample.py +0 -0
  23. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/dropout.py +0 -0
  24. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/generic.py +0 -0
  25. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/mamba.py +0 -0
  26. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/patch.py +0 -0
  27. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/posemb.py +0 -0
  28. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/sharing.py +0 -0
  29. {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/squeeze_excite.py +0 -0
  30. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/__init__.py +0 -0
  31. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/emamodel.py +0 -0
  32. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/fastervit.py +0 -0
  33. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/mlla.py +0 -0
  34. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/partialformer.py +0 -0
  35. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/shvit.py +0 -0
  36. {equimo-0.2.0 → equimo-0.2.1}/equimo/models/vssd.py +0 -0
  37. {equimo-0.2.0 → equimo-0.2.1}/equimo/ops/scan.py +0 -0
  38. {equimo-0.2.0 → equimo-0.2.1}/setup.cfg +0 -0
  39. {equimo-0.2.0 → equimo-0.2.1}/tests/test_models.py +0 -0
@@ -1,7 +1,16 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: Equimo
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Implementation of popular vision models in Jax
5
+ Classifier: Development Status :: 4 - Beta
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
5
14
  Requires-Python: >=3.11
6
15
  Description-Content-Type: text/markdown
7
16
  Requires-Dist: einops>=0.8.0
@@ -1,7 +1,16 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: Equimo
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Implementation of popular vision models in Jax
5
+ Classifier: Development Status :: 4 - Beta
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
5
14
  Requires-Python: >=3.11
6
15
  Description-Content-Type: text/markdown
7
16
  Requires-Dist: einops>=0.8.0
@@ -1552,3 +1552,53 @@ class LinearAngularAttention(eqx.Module):
1552
1552
  x = self.proj_drop(x, inference=inference, key=key2)
1553
1553
 
1554
1554
  return x
1555
+
1556
+
1557
+ def get_attention(module: str | eqx.Module) -> eqx.Module:
1558
+ """Get an `eqx.Module` from its common name.
1559
+
1560
+ This is necessary because configs have to be stringified and stored as
1561
+ json files to allow (de)serialization.
1562
+ """
1563
+ if not isinstance(module, str):
1564
+ return module
1565
+
1566
+ match module:
1567
+ case "attention":
1568
+ return Attention
1569
+ case "windowedattention":
1570
+ return WindowedAttention
1571
+ case "shsa":
1572
+ return SHSA
1573
+ case "linearattention":
1574
+ return LinearAttention
1575
+ case "mmsa":
1576
+ return MMSA
1577
+ case "sqa":
1578
+ return SQA
1579
+ case "linearangularattention":
1580
+ return LinearAngularAttention
1581
+ case _:
1582
+ raise ValueError(f"Got an unknown module string: {module}")
1583
+
1584
+
1585
+ def get_attention_block(module: str | eqx.Module) -> eqx.Module:
1586
+ """Get an `eqx.Module` from its common name.
1587
+
1588
+ This is necessary because configs have to be stringified and stored as
1589
+ json files to allow (de)serialization.
1590
+ """
1591
+ if not isinstance(module, str):
1592
+ return module
1593
+
1594
+ match module:
1595
+ case "attentionblock":
1596
+ return AttentionBlock
1597
+ case "hatblock":
1598
+ return HATBlock
1599
+ case "mllablock":
1600
+ return MllaBlock
1601
+ case "partialformerblock":
1602
+ return PartialFormerBlock
1603
+ case _:
1604
+ raise ValueError(f"Got an unknown module string: {module}")
@@ -285,10 +285,10 @@ class SwiGlu(eqx.Module):
285
285
  out_features = out_features or in_features
286
286
 
287
287
  self.w12 = eqx.nn.Linear(
288
- in_features, hidden_features, use_bias=bias, key=key_fc1
288
+ in_features, 2 * hidden_features, use_bias=bias, key=key_fc1
289
289
  )
290
290
  self.w3 = eqx.nn.Linear(
291
- hidden_features // 2, out_features, use_bias=bias, key=key_fc2
291
+ hidden_features, out_features, use_bias=bias, key=key_fc2
292
292
  )
293
293
 
294
294
  self.drop1 = eqx.nn.Dropout(dropout_rate)
@@ -317,3 +317,57 @@ class SwiGlu(eqx.Module):
317
317
  )
318
318
 
319
319
  return x
320
+
321
+
322
+ class SwiGluFused(SwiGlu):
323
+ def __init__(
324
+ self,
325
+ in_features: int,
326
+ *,
327
+ key: PRNGKeyArray,
328
+ out_features: int | None = None,
329
+ hidden_features: int | None = None,
330
+ dropout_rate: float = 0,
331
+ bias: bool = True,
332
+ **kwargs,
333
+ ):
334
+ """This matches the implementation of Dinov2 giant at
335
+ https://github.com/facebookresearch/dinov2/blob/e1277af2ba9496fbadf7aec6eba56e8d882d1e35/dinov2/layers/swiglu_ffn.py#L54
336
+ """
337
+ out_features = out_features or in_features
338
+ hidden_features = hidden_features or in_features
339
+ hidden_features = (int(hidden_features * 2 / 3) + 7) // 8 * 8
340
+
341
+ super().__init__(
342
+ in_features,
343
+ key=key,
344
+ out_features=out_features,
345
+ hidden_features=hidden_features,
346
+ dropout_rate=dropout_rate,
347
+ bias=bias,
348
+ **kwargs,
349
+ )
350
+
351
+
352
+ def get_ffn(module: str | eqx.Module) -> eqx.Module:
353
+ """Get an `eqx.Module` from its common name.
354
+
355
+ This is necessary because configs have to be stringified and stored as
356
+ json files to allow (de)serialization.
357
+ """
358
+ if not isinstance(module, str):
359
+ return module
360
+
361
+ match module:
362
+ case "mlp":
363
+ return Mlp
364
+ case "swiglu":
365
+ return SwiGlu
366
+ case "swiglufused":
367
+ return SwiGluFused
368
+ case "dinohead":
369
+ return DINOHead
370
+ case "weightnormlinear":
371
+ return WeightNormLinear
372
+ case _:
373
+ raise ValueError(f"Got an unknown module string: {module}")
@@ -85,3 +85,27 @@ class LayerScale(eqx.Module):
85
85
  Scaled tensor of same shape as input
86
86
  """
87
87
  return x * self.gamma
88
+
89
+
90
+ def get_norm(module: str | eqx.Module) -> eqx.Module:
91
+ """Get an `eqx.Module` from its common name.
92
+
93
+ This is necessary because configs have to be stringified and stored as
94
+ json files to allow (de)serialization.
95
+ """
96
+ if not isinstance(module, str):
97
+ return module
98
+
99
+ match module:
100
+ case "layernorm":
101
+ return eqx.nn.LayerNorm
102
+ case "rmsnorm":
103
+ return eqx.nn.RMSNorm
104
+ case "groupnorm":
105
+ return eqx.nn.GroupNorm
106
+ case "rmsnormgated":
107
+ return RMSNormGated
108
+ case "layerscale":
109
+ return LayerScale
110
+ case _:
111
+ raise ValueError(f"Got an unknown module string: {module}")
@@ -8,8 +8,14 @@ import jax.random as jr
8
8
  from einops import rearrange
9
9
  from jaxtyping import Array, Float, Int, PRNGKeyArray
10
10
 
11
- from equimo.layers.attention import Attention, AttentionBlock
12
- from equimo.layers.ffn import Mlp
11
+ from equimo.layers.attention import (
12
+ Attention,
13
+ AttentionBlock,
14
+ get_attention,
15
+ get_attention_block,
16
+ )
17
+ from equimo.layers.ffn import Mlp, get_ffn
18
+ from equimo.layers.norm import get_norm
13
19
  from equimo.layers.patch import PatchEmbedding
14
20
  from equimo.layers.posemb import PosCNN
15
21
  from equimo.utils import pool_sd, to_list
@@ -177,7 +183,7 @@ class VisionTransformer(eqx.Module):
177
183
  pos_drop_rate: float = 0.0,
178
184
  drop_path_rate: float = 0.0,
179
185
  drop_path_uniform: bool = False,
180
- block: eqx.Module = AttentionBlock,
186
+ block: str | eqx.Module = AttentionBlock,
181
187
  mlp_ratio: float = 4.0,
182
188
  qkv_bias: bool = True,
183
189
  proj_bias: bool = True,
@@ -185,10 +191,10 @@ class VisionTransformer(eqx.Module):
185
191
  attn_drop: float = 0.0,
186
192
  proj_drop: float = 0.0,
187
193
  act_layer: Callable = jax.nn.gelu,
188
- attn_layer: eqx.Module = Attention,
189
- ffn_layer: eqx.Module = Mlp,
194
+ attn_layer: str | eqx.Module = Attention,
195
+ ffn_layer: str | eqx.Module = Mlp,
190
196
  ffn_bias: bool = True,
191
- norm_layer: eqx.Module = eqx.nn.LayerNorm,
197
+ norm_layer: str | eqx.Module = eqx.nn.LayerNorm,
192
198
  init_values: float | None = None,
193
199
  global_pool: Literal["", "token", "avg", "avgmax", "max"] = "avg",
194
200
  num_classes: int = 1000,
@@ -212,6 +218,11 @@ class VisionTransformer(eqx.Module):
212
218
  self.global_pool = global_pool
213
219
  self.embed_size = img_size // patch_size
214
220
 
221
+ block = get_attention_block(block)
222
+ attn_layer = get_attention(attn_layer)
223
+ ffn_layer = get_ffn(ffn_layer)
224
+ norm_layer = get_norm(norm_layer)
225
+
215
226
  self.patch_embed = PatchEmbedding(
216
227
  in_channels,
217
228
  dim,
@@ -1,4 +1,5 @@
1
1
  from functools import partial
2
+
2
3
  import jax
3
4
  import jax.numpy as jnp
4
5
  from jaxtyping import Array, Float
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Equimo"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Implementation of popular vision models in Jax"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -13,6 +13,21 @@ dependencies = [
13
13
  "lz4>=4.4.3",
14
14
  "requests>=2.32.3",
15
15
  ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: Science/Research",
21
+
22
+ "License :: OSI Approved :: MIT License",
23
+
24
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
25
+
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
30
+ ]
16
31
 
17
32
  [project.optional-dependencies]
18
33
  torch = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes