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.
- {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/PKG-INFO +10 -1
- {equimo-0.2.0 → equimo-0.2.1}/PKG-INFO +10 -1
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/attention.py +50 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/ffn.py +56 -2
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/norm.py +24 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/vit.py +17 -6
- {equimo-0.2.0 → equimo-0.2.1}/equimo/utils.py +1 -0
- {equimo-0.2.0 → equimo-0.2.1}/pyproject.toml +16 -1
- {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/SOURCES.txt +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/dependency_links.txt +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/requires.txt +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/Equimo.egg-info/top_level.txt +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/LICENSE.md +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/README.md +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/__init__.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/__init__.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/dinov2.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/converters/utils.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/io.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/__init__.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/convolution.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/downsample.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/dropout.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/generic.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/mamba.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/patch.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/posemb.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/sharing.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/layers/squeeze_excite.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/__init__.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/emamodel.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/fastervit.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/mlla.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/partialformer.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/shvit.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/models/vssd.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/equimo/ops/scan.py +0 -0
- {equimo-0.2.0 → equimo-0.2.1}/setup.cfg +0 -0
- {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.
|
|
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.
|
|
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
|
|
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
|
|
12
|
-
|
|
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,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "Equimo"
|
|
3
|
-
version = "0.2.
|
|
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
|
|
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
|