Equimo 0.4.0a2__tar.gz → 0.4.0a4__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 (44) hide show
  1. {equimo-0.4.0a2/src/Equimo.egg-info → equimo-0.4.0a4}/PKG-INFO +1 -1
  2. {equimo-0.4.0a2 → equimo-0.4.0a4}/pyproject.toml +1 -1
  3. {equimo-0.4.0a2 → equimo-0.4.0a4/src/Equimo.egg-info}/PKG-INFO +1 -1
  4. equimo-0.4.0a4/src/equimo/__init__.py +1 -0
  5. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/attention.py +47 -7
  6. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/convolution.py +46 -8
  7. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/dropout.py +1 -1
  8. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/reduceformer.py +29 -10
  9. equimo-0.4.0a2/src/equimo/__init__.py +0 -1
  10. {equimo-0.4.0a2 → equimo-0.4.0a4}/LICENSE.md +0 -0
  11. {equimo-0.4.0a2 → equimo-0.4.0a4}/README.md +0 -0
  12. {equimo-0.4.0a2 → equimo-0.4.0a4}/setup.cfg +0 -0
  13. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/Equimo.egg-info/SOURCES.txt +0 -0
  14. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/Equimo.egg-info/dependency_links.txt +0 -0
  15. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/Equimo.egg-info/requires.txt +0 -0
  16. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/Equimo.egg-info/top_level.txt +0 -0
  17. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/conversion/__init__.py +0 -0
  18. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/conversion/utils.py +0 -0
  19. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/experimental/__init__.py +0 -0
  20. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/experimental/text.py +0 -0
  21. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/io.py +0 -0
  22. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/__init__.py +0 -0
  23. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/activation.py +0 -0
  24. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/downsample.py +0 -0
  25. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/ffn.py +0 -0
  26. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/generic.py +0 -0
  27. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/mamba.py +0 -0
  28. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/norm.py +0 -0
  29. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/patch.py +0 -0
  30. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/posemb.py +0 -0
  31. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/sharing.py +0 -0
  32. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/layers/squeeze_excite.py +0 -0
  33. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/__init__.py +0 -0
  34. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/emamodel.py +0 -0
  35. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/fastervit.py +0 -0
  36. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/lowformer.py +0 -0
  37. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/mlla.py +0 -0
  38. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/partialformer.py +0 -0
  39. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/shvit.py +0 -0
  40. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/vit.py +0 -0
  41. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/models/vssd.py +0 -0
  42. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/ops/scan.py +0 -0
  43. {equimo-0.4.0a2 → equimo-0.4.0a4}/src/equimo/utils.py +0 -0
  44. {equimo-0.4.0a2 → equimo-0.4.0a4}/tests/test_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Equimo
3
- Version: 0.4.0a2
3
+ Version: 0.4.0a4
4
4
  Summary: Implementation of popular vision models in Jax
5
5
  Classifier: Development Status :: 4 - Beta
6
6
  Classifier: Intended Audience :: Developers
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Equimo"
3
- version = "0.4.0-alpha.2"
3
+ version = "0.4.0-alpha.4"
4
4
  description = "Implementation of popular vision models in Jax"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Equimo
3
- Version: 0.4.0a2
3
+ Version: 0.4.0a4
4
4
  Summary: Implementation of popular vision models in Jax
5
5
  Classifier: Development Status :: 4 - Beta
6
6
  Classifier: Intended Audience :: Developers
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0-alpha.4"
@@ -97,7 +97,7 @@ class Attention(eqx.Module):
97
97
  attn = jnp.where(mask == 0, jnp.finfo(attn.dtype).min, attn)
98
98
 
99
99
  attn = jax.nn.softmax(attn, axis=-1)
100
- attn = self.attn_drop(attn, inference=inference, key=key1)
100
+ attn = self.attn_drop(attn, inference=infeoence, key=key1)
101
101
 
102
102
  x = jnp.einsum("hqk,hkd->hqd", attn, v)
103
103
  x = rearrange(x, "h s d -> s (h d)")
@@ -1591,6 +1591,7 @@ class RFAttention(eqx.Module):
1591
1591
  qkv: eqx.nn.Conv2d
1592
1592
  aggreg: list[eqx.nn.Conv2d]
1593
1593
  proj: SingleConvBlock
1594
+ proj_drop: eqx.nn.Dropout
1594
1595
 
1595
1596
  def __init__(
1596
1597
  self,
@@ -1604,6 +1605,7 @@ class RFAttention(eqx.Module):
1604
1605
  scales: Sequence[int] = (5,),
1605
1606
  use_bias: bool = False,
1606
1607
  kernel_func: Callable = jax.nn.relu,
1608
+ proj_drop: float = 0.0,
1607
1609
  # TODO: Benchmark against LN, RMSN, NsLN
1608
1610
  norm_layer: eqx.Module = eqx.nn.GroupNorm,
1609
1611
  norm_kwargs: dict = {},
@@ -1649,12 +1651,14 @@ class RFAttention(eqx.Module):
1649
1651
  key=key_proj,
1650
1652
  )
1651
1653
 
1654
+ self.proj_drop = eqx.nn.Dropout(proj_drop)
1655
+
1652
1656
  def __call__(
1653
1657
  self,
1654
- x: Float[Array, "seqlen height width"],
1658
+ x: Float[Array, "dim height width"],
1655
1659
  key: PRNGKeyArray,
1656
1660
  inference: Optional[bool] = None,
1657
- ) -> Float[Array, "seqlen height width"]:
1661
+ ) -> Float[Array, "dim height width"]:
1658
1662
  qkv_base = self.qkv(x)
1659
1663
 
1660
1664
  aggregated_qkvs = [op(qkv_base) for op in self.aggreg]
@@ -1671,12 +1675,13 @@ class RFAttention(eqx.Module):
1671
1675
  k = self.kernel_func(k)
1672
1676
 
1673
1677
  sum_k = jnp.sum(k, axis=(-1, -2), keepdims=True)
1674
- sum_v = jnp.sum(v, axis=(-1, -2), keepdims=True)
1678
+ sum_v = jnp.sum(v * sum_k, axis=(-1, -2), keepdims=True)
1675
1679
  sum_kv = jnp.sum(k * sum_v, axis=(-1, -2), keepdims=True)
1676
1680
  sum_q = jnp.sum(q, axis=0, keepdims=True)
1677
1681
 
1678
1682
  out = (q * sum_kv) / (sum_q * sum_k + self.eps)
1679
1683
  out = self.proj(out)
1684
+ out = self.proj_drop(out, inference=inference, key=key)
1680
1685
 
1681
1686
  return out
1682
1687
 
@@ -1684,6 +1689,8 @@ class RFAttention(eqx.Module):
1684
1689
  class RFAttentionBlock(eqx.Module):
1685
1690
  context_module: RFAttention
1686
1691
  local_module: MBConv
1692
+ drop_path1: DropPathAdd
1693
+ drop_path2: DropPathAdd
1687
1694
 
1688
1695
  def __init__(
1689
1696
  self,
@@ -1699,10 +1706,25 @@ class RFAttentionBlock(eqx.Module):
1699
1706
  mbconv_norm_layers: tuple = (None, None, eqx.nn.GroupNorm),
1700
1707
  mbconv_act_layers: tuple = (jax.nn.hard_swish, jax.nn.hard_swish, None),
1701
1708
  fuse_mbconv: bool = False,
1709
+ context_drop: float = 0.0,
1710
+ local_drop: float = 0.0,
1711
+ drop_path: float | List[float] = 0.0,
1712
+ residual_mbconv: bool = False,
1702
1713
  **kwargs,
1703
1714
  ):
1704
1715
  key_context, key_local = jr.split(key, 2)
1705
1716
 
1717
+ if isinstance(drop_path, list):
1718
+ if len(drop_path) != 2:
1719
+ raise AssertionError(
1720
+ f"`drop_path` needs to have 2 elements, got {len(drop_path)} ({drop_path})."
1721
+ )
1722
+ dr1, dr2 = drop_path
1723
+ dr1 = float(dr1)
1724
+ dr2 = float(dr2)
1725
+ else:
1726
+ dr1 = dr2 = float(drop_path)
1727
+
1706
1728
  self.context_module = RFAttention(
1707
1729
  in_channels=in_channels,
1708
1730
  out_channels=in_channels,
@@ -1711,6 +1733,7 @@ class RFAttentionBlock(eqx.Module):
1711
1733
  scales=scales,
1712
1734
  norm_layer=rfattn_norm_layer,
1713
1735
  norm_kwargs=norm_kwargs,
1736
+ proj_drop=context_drop,
1714
1737
  key=key_context,
1715
1738
  )
1716
1739
  self.local_module = MBConv(
@@ -1721,19 +1744,36 @@ class RFAttentionBlock(eqx.Module):
1721
1744
  act_layers=mbconv_act_layers,
1722
1745
  use_bias=(True, True, False),
1723
1746
  fuse=fuse_mbconv,
1747
+ dropout=local_drop,
1748
+ drop_path=dr1,
1749
+ residual=False,
1724
1750
  key=key_local,
1725
1751
  )
1726
1752
 
1753
+ self.drop_path1 = DropPathAdd(dr1)
1754
+ self.drop_path2 = DropPathAdd(dr2)
1755
+
1727
1756
  def __call__(
1728
1757
  self,
1729
1758
  x: Float[Array, "dim height width"],
1730
1759
  key: PRNGKeyArray,
1731
1760
  inference: Optional[bool] = None,
1732
1761
  ):
1733
- key_context, key_local = jr.split(key, 2)
1762
+ key_context, key_local, key_dr1, key_dr2 = jr.split(key, 4)
1734
1763
 
1735
- x += self.context_module(x, inference=inference, key=key_context)
1736
- x += self.local_module(x, inference=inference, key=key_local)
1764
+ # TODO: some prenorm?
1765
+ x = self.drop_path1(
1766
+ x,
1767
+ self.context_module(x, inference=inference, key=key_context),
1768
+ inference=inference,
1769
+ key=key_dr1,
1770
+ )
1771
+ x = self.drop_path2(
1772
+ x,
1773
+ self.local_module(x, inference=inference, key=key_local),
1774
+ inference=inference,
1775
+ key=key_dr2,
1776
+ )
1737
1777
 
1738
1778
  return x
1739
1779
 
@@ -663,11 +663,14 @@ class MBConv(eqx.Module):
663
663
  """
664
664
 
665
665
  fused: bool = eqx.field(static=True)
666
+ residual: bool = eqx.field(static=True)
666
667
 
667
668
  inverted_conv: SingleConvBlock | None
668
669
  depth_conv: SingleConvBlock | None
669
670
  spatial_conv: SingleConvBlock | None
670
671
  point_conv: SingleConvBlock
672
+ dropout: eqx.nn.Dropout
673
+ drop_path: DropPathAdd
671
674
 
672
675
  def __init__(
673
676
  self,
@@ -688,6 +691,9 @@ class MBConv(eqx.Module):
688
691
  fuse_threshold: int = 256,
689
692
  fuse_group: bool = False,
690
693
  fused_conv_groups: int = 1,
694
+ dropout: float = 0.0,
695
+ drop_path: float = 0.0,
696
+ residual: bool = False,
691
697
  **kwargs,
692
698
  ):
693
699
  key_inverted, key_depth, key_point = jr.split(key, 3)
@@ -711,6 +717,9 @@ class MBConv(eqx.Module):
711
717
  f"`act_layers` should be a Tuple of length 3, got: {len(act_layers)}"
712
718
  )
713
719
 
720
+ # Ensure shapes are the same between input and output
721
+ self.residual = residual and (stride == 1) and (in_channels == out_channels)
722
+
714
723
  mid_channels = (
715
724
  mid_channels
716
725
  if mid_channels is not None
@@ -779,25 +788,38 @@ class MBConv(eqx.Module):
779
788
  key=key_point,
780
789
  )
781
790
 
791
+ self.dropout = eqx.nn.Dropout(dropout)
792
+ self.drop_path = DropPathAdd(drop_path)
793
+
782
794
  def __call__(
783
795
  self,
784
796
  x: Float[Array, "channels height width"],
785
797
  key: PRNGKeyArray,
786
798
  inference: Optional[bool] = None,
787
799
  ):
800
+ key_dropout, key_droppath = jr.split(key, 2)
788
801
  if self.fused:
789
- x = self.spatial_conv(x)
802
+ out = self.spatial_conv(x)
790
803
  else:
791
- x = self.inverted_conv(x)
792
- x = self.depth_conv(x)
793
- x = self.point_conv(x)
804
+ out = self.inverted_conv(x)
805
+ out = self.depth_conv(out)
806
+ out = self.point_conv(out)
794
807
 
795
- return x
808
+ out = self.dropout(out, inference=inference, key=key_dropout)
809
+
810
+ if self.residual:
811
+ out = self.drop_path(x, out, inference=inference, key=key_droppath)
812
+
813
+ return out
796
814
 
797
815
 
798
816
  class DSConv(eqx.Module):
817
+ residual: bool = eqx.field(static=True)
818
+
799
819
  depth_conv: SingleConvBlock
800
820
  point_conv: SingleConvBlock
821
+ dropout: eqx.nn.Dropout
822
+ drop_path: DropPathAdd
801
823
 
802
824
  def __init__(
803
825
  self,
@@ -812,6 +834,9 @@ class DSConv(eqx.Module):
812
834
  | eqx.Module
813
835
  | None = eqx.nn.GroupNorm,
814
836
  act_layers: Tuple[Callable | None, ...] | Callable | None = jax.nn.relu6,
837
+ residual: bool = False,
838
+ dropout: float = 0.0,
839
+ drop_path: float = 0.0,
815
840
  **kwargs,
816
841
  ):
817
842
  key_depth, key_point = jr.split(key, 2)
@@ -835,6 +860,9 @@ class DSConv(eqx.Module):
835
860
  f"`act_layers` should be a Tuple of length 2, got: {len(act_layers)}"
836
861
  )
837
862
 
863
+ # Ensure shapes are the same between input and output
864
+ self.residual = residual and (stride == 1) and (in_channels == out_channels)
865
+
838
866
  self.depth_conv = SingleConvBlock(
839
867
  in_channels=in_channels,
840
868
  out_channels=in_channels,
@@ -859,13 +887,23 @@ class DSConv(eqx.Module):
859
887
  key=key_point,
860
888
  )
861
889
 
890
+ self.dropout = eqx.nn.Dropout(dropout)
891
+ self.drop_path = DropPathAdd(drop_path)
892
+
862
893
  def __call__(
863
894
  self,
864
895
  x: Float[Array, "channels height width"],
865
896
  key: PRNGKeyArray,
866
897
  inference: Optional[bool] = None,
867
898
  ):
868
- x = self.depth_conv(x)
869
- x = self.point_conv(x)
899
+ key_dropout, key_droppath = jr.split(key, 2)
900
+
901
+ out = self.depth_conv(x)
902
+ out = self.point_conv(out)
903
+
904
+ out = self.dropout(out, inference=inference, key=key_dropout)
905
+
906
+ if self.residual:
907
+ out = self.drop_path(x, out, inference=inference, key=key_droppath)
870
908
 
871
- return x
909
+ return out
@@ -124,5 +124,5 @@ class DropPathAdd(eqx.Module, strict=True):
124
124
  )
125
125
  else:
126
126
  q = 1 - lax.stop_gradient(self.p)
127
- add = jrandom.bernouilli(key, q)
127
+ add = jrandom.bernoulli(key, q)
128
128
  return jax.lax.cond(add, lambda x, y: x + y, lambda x, y: x, x1, x2)
@@ -2,6 +2,7 @@ from typing import Callable, Literal, Optional, Tuple
2
2
 
3
3
  import equinox as eqx
4
4
  import jax
5
+ import jax.numpy as jnp
5
6
  import jax.random as jr
6
7
  from einops import reduce
7
8
  from jaxtyping import Array, Float, PRNGKeyArray
@@ -13,7 +14,6 @@ from equimo.layers.norm import get_norm
13
14
 
14
15
 
15
16
  class BlockChunk(eqx.Module):
16
- residuals: list[bool] = eqx.field(static=True)
17
17
  blocks: list[DSConv | MBConv | RFAttentionBlock]
18
18
 
19
19
  def __init__(
@@ -33,6 +33,8 @@ class BlockChunk(eqx.Module):
33
33
  act_layer: Callable = jax.nn.hard_swish,
34
34
  fewer_norm: bool = False,
35
35
  fuse_mbconv: bool = False,
36
+ dropout: float = 0.0,
37
+ drop_path: list[float] | float = 0.0,
36
38
  **kwargs,
37
39
  ):
38
40
  key, *block_subkeys = jr.split(key, depth + 1)
@@ -41,8 +43,10 @@ class BlockChunk(eqx.Module):
41
43
  k for k, v in kwargs.items() if isinstance(v, list) and len(v) == depth
42
44
  ]
43
45
 
46
+ if isinstance(drop_path, float):
47
+ drop_path = [drop_path] * depth
48
+
44
49
  blocks = []
45
- residuals = []
46
50
 
47
51
  # TODO: simplify logic
48
52
  match block_type:
@@ -74,6 +78,9 @@ class BlockChunk(eqx.Module):
74
78
  stride=stride if i == 0 else 1,
75
79
  use_bias=use_bias,
76
80
  norm_layers=norm_layer,
81
+ dropout=dropout,
82
+ drop_path=drop_path[i],
83
+ residual=True,
77
84
  act_layers=(act_layer, None)
78
85
  if block == DSConv
79
86
  else (act_layer, act_layer, None),
@@ -81,9 +88,6 @@ class BlockChunk(eqx.Module):
81
88
  key=block_subkeys[i],
82
89
  )
83
90
  )
84
- residuals.append(
85
- (in_channels == out_channels and stride == 1) or i > 0
86
- )
87
91
 
88
92
  case "attention":
89
93
  blocks.append(
@@ -95,6 +99,7 @@ class BlockChunk(eqx.Module):
95
99
  norm_layers=(None, None, norm_layer),
96
100
  act_layers=(act_layer, act_layer, None),
97
101
  use_bias=(True, True, False),
102
+ dropout=dropout,
98
103
  fuse=fuse_mbconv,
99
104
  key=key,
100
105
  )
@@ -111,13 +116,14 @@ class BlockChunk(eqx.Module):
111
116
  mbconv_norm_layers=(None, None, norm_layer),
112
117
  mbconv_act_layers=(act_layer, act_layer, None),
113
118
  fuse_mbconv=fuse_mbconv,
119
+ context_drop=dropout,
120
+ local_drop=dropout,
121
+ drop_path=drop_path[i],
114
122
  key=block_subkeys[i],
115
123
  )
116
124
  )
117
- residuals.append(False)
118
125
 
119
126
  self.blocks = blocks
120
- self.residuals = residuals
121
127
 
122
128
  def __call__(
123
129
  self,
@@ -130,9 +136,8 @@ class BlockChunk(eqx.Module):
130
136
  keys = jr.split(key, len(self.blocks))
131
137
 
132
138
  # TODO: Dropout and Stochastic Path Add
133
- for blk, residual, key_block in zip(self.blocks, self.residuals, keys):
134
- res = blk(x, inference=inference, key=key_block, **kwargs)
135
- x = x + res if residual else res
139
+ for blk, key_block in zip(self.blocks, keys):
140
+ x = blk(x, inference=inference, key=key_block, **kwargs)
136
141
 
137
142
  return x
138
143
 
@@ -156,6 +161,9 @@ class ReduceFormer(eqx.Module):
156
161
  act_layer: Callable | str = jax.nn.hard_swish,
157
162
  fuse_mbconv: bool = False,
158
163
  num_classes: int | None = 1000,
164
+ dropout: float = 0.0,
165
+ drop_path_rate: float = 0.0,
166
+ drop_path_uniform: bool = False,
159
167
  **kwargs,
160
168
  ):
161
169
  if not len(widths) == len(depths) == len(block_types):
@@ -165,6 +173,13 @@ class ReduceFormer(eqx.Module):
165
173
 
166
174
  key_stem, key_head, *key_blocks = jr.split(key, 3 + len(depths))
167
175
 
176
+ depth = sum(depths)
177
+
178
+ if drop_path_uniform:
179
+ dpr = [drop_path_rate] * depth
180
+ else:
181
+ dpr = list(jnp.linspace(0.0, drop_path_rate, depth))
182
+
168
183
  act_layer = get_act(act_layer)
169
184
  norm_layer = get_norm(norm_layer)
170
185
 
@@ -195,6 +210,8 @@ class ReduceFormer(eqx.Module):
195
210
  expand_ratio=1.0,
196
211
  norm_layer=norm_layer,
197
212
  act_layer=act_layer,
213
+ dropout=dropout,
214
+ drop_path=0.0,
198
215
  key=key_block_stem,
199
216
  ),
200
217
  ]
@@ -211,6 +228,8 @@ class ReduceFormer(eqx.Module):
211
228
  norm_layer=norm_layer,
212
229
  act_layer=act_layer,
213
230
  fuse_mbconv=fuse_mbconv,
231
+ dropout=dropout,
232
+ drop_path=dpr[sum(depths[:i]) : sum(depths[: i + 1])],
214
233
  key=key_block,
215
234
  )
216
235
  for i, (depth, block_type, key_block) in enumerate(
@@ -1 +0,0 @@
1
- __version__ = "0.4.0-alpha.2"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes