Equimo 0.4.6a2__tar.gz → 0.4.6a4__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.4.6a2/src/Equimo.egg-info → equimo-0.4.6a4}/PKG-INFO +1 -1
- {equimo-0.4.6a2 → equimo-0.4.6a4}/pyproject.toml +1 -1
- {equimo-0.4.6a2 → equimo-0.4.6a4/src/Equimo.egg-info}/PKG-INFO +1 -1
- equimo-0.4.6a4/src/equimo/__init__.py +1 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/convolution.py +60 -26
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/wavelet.py +24 -10
- equimo-0.4.6a2/src/equimo/__init__.py +0 -1
- {equimo-0.4.6a2 → equimo-0.4.6a4}/LICENSE.md +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/README.md +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/setup.cfg +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/Equimo.egg-info/SOURCES.txt +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/Equimo.egg-info/dependency_links.txt +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/Equimo.egg-info/requires.txt +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/Equimo.egg-info/top_level.txt +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/conversion/__init__.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/conversion/utils.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/experimental/__init__.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/experimental/text.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/io.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/__init__.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/activation.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/attention.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/downsample.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/dropout.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/ffn.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/generic.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/mamba.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/norm.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/patch.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/posemb.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/sharing.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/layers/squeeze_excite.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/__init__.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/emamodel.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/fastervit.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/lowformer.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/mlla.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/partialformer.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/reduceformer.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/shvit.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/vit.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/models/vssd.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/ops/scan.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/src/equimo/utils.py +0 -0
- {equimo-0.4.6a2 → equimo-0.4.6a4}/tests/test_models.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.6a4"
|
|
@@ -1125,13 +1125,13 @@ class GenericGhostModule(eqx.Module):
|
|
|
1125
1125
|
self.mode = mode
|
|
1126
1126
|
self.num_conv_branches = num_conv_branches
|
|
1127
1127
|
self.out_channels = out_channels
|
|
1128
|
-
self.kernel_size = kernel_size
|
|
1129
|
-
self.dw_size = dw_size
|
|
1130
|
-
self.stride = stride
|
|
1131
|
-
self.primary_has_skip = primary_has_skip
|
|
1132
|
-
self.primary_has_scale = primary_has_scale
|
|
1133
|
-
self.cheap_has_skip = cheap_has_skip
|
|
1134
|
-
self.cheap_has_scale = cheap_has_scale
|
|
1128
|
+
self.kernel_size = kernel_size
|
|
1129
|
+
self.dw_size = dw_size
|
|
1130
|
+
self.stride = stride
|
|
1131
|
+
self.primary_has_skip = primary_has_skip
|
|
1132
|
+
self.primary_has_scale = primary_has_scale
|
|
1133
|
+
self.cheap_has_skip = cheap_has_skip
|
|
1134
|
+
self.cheap_has_scale = cheap_has_scale
|
|
1135
1135
|
|
|
1136
1136
|
# Those are actually placeholders, updated at each epoch, only used at inference time
|
|
1137
1137
|
self.primary_conv = eqx.nn.Conv2d(
|
|
@@ -1147,7 +1147,7 @@ class GenericGhostModule(eqx.Module):
|
|
|
1147
1147
|
in_channels=init_channels,
|
|
1148
1148
|
out_channels=new_channels,
|
|
1149
1149
|
kernel_size=dw_size,
|
|
1150
|
-
stride=1,
|
|
1150
|
+
stride=1,
|
|
1151
1151
|
padding=dw_size // 2,
|
|
1152
1152
|
groups=init_channels,
|
|
1153
1153
|
use_bias=False,
|
|
@@ -1300,16 +1300,31 @@ class GenericGhostModule(eqx.Module):
|
|
|
1300
1300
|
inference: Optional[bool] = None,
|
|
1301
1301
|
):
|
|
1302
1302
|
use_inference = self.inference if inference is None else inference
|
|
1303
|
-
|
|
1303
|
+
use_inference = jnp.asarray(use_inference, dtype=bool)
|
|
1304
|
+
|
|
1305
|
+
out = jax.lax.cond(
|
|
1306
|
+
use_inference,
|
|
1307
|
+
lambda x_: self.inference_features(x_),
|
|
1308
|
+
lambda x_: self.training_features(x_),
|
|
1309
|
+
operand=x,
|
|
1310
|
+
)
|
|
1304
1311
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1312
|
+
def _shortcut_branch(ox):
|
|
1313
|
+
out_, x_ = ox
|
|
1314
|
+
res = self.short_conv(self.pool2(x_))
|
|
1315
|
+
gating = jax.image.resize(
|
|
1308
1316
|
image=jax.nn.sigmoid(res / self.gate_scale),
|
|
1309
|
-
shape=(res.shape[0],
|
|
1317
|
+
shape=(res.shape[0], out_.shape[1], out_.shape[2]),
|
|
1310
1318
|
method="nearest",
|
|
1311
1319
|
)
|
|
1312
|
-
|
|
1320
|
+
return out_[: self.out_channels, :, :] * gating[: self.out_channels, :, :]
|
|
1321
|
+
|
|
1322
|
+
out = jax.lax.cond(
|
|
1323
|
+
self.mode == "shortcut",
|
|
1324
|
+
_shortcut_branch,
|
|
1325
|
+
lambda ox: ox[0],
|
|
1326
|
+
operand=(out, x),
|
|
1327
|
+
)
|
|
1313
1328
|
|
|
1314
1329
|
return out
|
|
1315
1330
|
|
|
@@ -1347,7 +1362,6 @@ class GhostBottleneck(eqx.Module):
|
|
|
1347
1362
|
stride: int = 1,
|
|
1348
1363
|
act_layer: Callable = jax.nn.relu,
|
|
1349
1364
|
se_ratio: float = 0.0,
|
|
1350
|
-
layer_id: Optional[int] = None,
|
|
1351
1365
|
use_shortcut_mode_in_ghost1: bool = True,
|
|
1352
1366
|
allow_identity_residual: bool = True,
|
|
1353
1367
|
key: PRNGKeyArray,
|
|
@@ -1490,34 +1504,54 @@ class GhostBottleneck(eqx.Module):
|
|
|
1490
1504
|
inference: Optional[bool] = None,
|
|
1491
1505
|
) -> Float[Array, "channels height width"]:
|
|
1492
1506
|
use_inference = self.inference if inference is None else inference
|
|
1493
|
-
|
|
1507
|
+
use_inference = jax.numpy.asarray(use_inference, dtype=bool)
|
|
1494
1508
|
|
|
1509
|
+
k_g1, k_g2 = jr.split(key, 2)
|
|
1495
1510
|
residual = x
|
|
1496
1511
|
|
|
1497
1512
|
x = self.ghost1(x, key=k_g1, inference=use_inference)
|
|
1498
1513
|
|
|
1499
1514
|
if self.stride > 1:
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1515
|
+
x = jax.lax.cond(
|
|
1516
|
+
use_inference,
|
|
1517
|
+
lambda y: self.dw_shared_norm(self.dw_conv(y)),
|
|
1518
|
+
lambda y: self.dw_shared_norm(
|
|
1519
|
+
jax.tree_util.tree_reduce(
|
|
1520
|
+
operator.add,
|
|
1521
|
+
(
|
|
1522
|
+
(
|
|
1523
|
+
[]
|
|
1524
|
+
if isinstance(self.dw_rpr_scale, eqx.nn.Identity)
|
|
1525
|
+
else [self.dw_rpr_scale(y)]
|
|
1526
|
+
)
|
|
1527
|
+
+ [conv(y) for conv in self.dw_rpr_conv]
|
|
1528
|
+
),
|
|
1529
|
+
)
|
|
1530
|
+
),
|
|
1531
|
+
operand=x,
|
|
1532
|
+
)
|
|
1508
1533
|
|
|
1509
1534
|
x = self.se(x)
|
|
1510
1535
|
|
|
1511
1536
|
x = self.ghost2(x, key=k_g2, inference=use_inference)
|
|
1512
1537
|
|
|
1513
1538
|
if not isinstance(self.shortcut, eqx.nn.Identity):
|
|
1514
|
-
x
|
|
1539
|
+
x = x + self.shortcut(residual)
|
|
1515
1540
|
elif self.allow_identity_residual:
|
|
1516
|
-
x
|
|
1541
|
+
x = x + residual
|
|
1517
1542
|
|
|
1518
1543
|
return x
|
|
1519
1544
|
|
|
1520
1545
|
|
|
1546
|
+
key = jr.PRNGKey(42)
|
|
1547
|
+
x = jr.normal(key, (64, 16, 16))
|
|
1548
|
+
f = GhostBottleneck(64, 128, 64, se_ratio=0.25, key=key)
|
|
1549
|
+
x1 = f.ghost1(x, key=key)
|
|
1550
|
+
x2 = f.se(x1)
|
|
1551
|
+
x3 = f.ghost2(x2, key=key)
|
|
1552
|
+
print(x2.shape)
|
|
1553
|
+
|
|
1554
|
+
|
|
1521
1555
|
def _pad_kernel_to_target(kernel: Array, target_size: tuple[int, int]) -> Array:
|
|
1522
1556
|
kh, kw = kernel.shape[-2], kernel.shape[-1]
|
|
1523
1557
|
th, tw = target_size
|
|
@@ -63,7 +63,7 @@ def haar_dwt_split(
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class HWDConv(eqx.Module):
|
|
66
|
-
mode: Literal["h_discard", "accurate"] = eqx.field(static=True)
|
|
66
|
+
mode: Literal["h_discard", "band_grouped", "accurate"] = eqx.field(static=True)
|
|
67
67
|
|
|
68
68
|
pre_norm: eqx.nn.GroupNorm
|
|
69
69
|
proj: eqx.nn.Conv2d
|
|
@@ -78,31 +78,43 @@ class HWDConv(eqx.Module):
|
|
|
78
78
|
kernel_size: int = 1,
|
|
79
79
|
use_bias: bool = False,
|
|
80
80
|
act: Callable = jax.nn.relu,
|
|
81
|
-
mode: Literal["h_discard", "accurate"] = "accurate",
|
|
81
|
+
mode: Literal["h_discard", "band_grouped", "accurate"] = "accurate",
|
|
82
82
|
dropout: float = 0.0,
|
|
83
83
|
key: PRNGKeyArray,
|
|
84
84
|
):
|
|
85
85
|
self.mode = mode
|
|
86
86
|
|
|
87
|
-
# Channels entering the projection (and thus the pre-norm)
|
|
88
87
|
channels_in = in_channels if mode == "h_discard" else 4 * in_channels
|
|
89
88
|
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
# For h_discard mode: total_groups = groups_per_band (single band).
|
|
89
|
+
# GroupNorm: align groups to sub-band boundaries
|
|
90
|
+
# groups_per_band divides in_channels; total_groups = 4 * groups_per_band for 4 bands
|
|
93
91
|
groups_per_band = nearest_power_of_2_divisor(in_channels, 32)
|
|
94
92
|
total_groups = groups_per_band if mode == "h_discard" else 4 * groups_per_band
|
|
95
|
-
|
|
96
93
|
self.pre_norm = eqx.nn.GroupNorm(channels=channels_in, groups=total_groups)
|
|
97
94
|
|
|
95
|
+
# Projection 1x1 conv
|
|
96
|
+
# - accurate: dense projection (groups=1)
|
|
97
|
+
# - band_grouped: independent per-band projections (groups=4), no cross-band mixing
|
|
98
|
+
# - h_discard: single-band dense projection (groups=1)
|
|
99
|
+
proj_groups = 1
|
|
100
|
+
if mode == "band_grouped":
|
|
101
|
+
if out_channels % 4 != 0:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"band_grouped mode requires out_channels to be divisible by 4 "
|
|
104
|
+
"so each sub-band produces an equal share."
|
|
105
|
+
)
|
|
106
|
+
proj_groups = 4
|
|
107
|
+
|
|
98
108
|
self.proj = eqx.nn.Conv2d(
|
|
99
|
-
channels_in,
|
|
100
|
-
out_channels,
|
|
109
|
+
in_channels=channels_in,
|
|
110
|
+
out_channels=out_channels,
|
|
101
111
|
kernel_size=kernel_size,
|
|
102
112
|
use_bias=use_bias,
|
|
103
113
|
padding="SAME",
|
|
114
|
+
groups=proj_groups,
|
|
104
115
|
key=key,
|
|
105
116
|
)
|
|
117
|
+
|
|
106
118
|
self.act = act
|
|
107
119
|
|
|
108
120
|
self.dropout = eqx.nn.Dropout(dropout)
|
|
@@ -115,11 +127,13 @@ class HWDConv(eqx.Module):
|
|
|
115
127
|
if self.mode == "h_discard":
|
|
116
128
|
y = LL # (C, H/2, W/2)
|
|
117
129
|
else:
|
|
130
|
+
# Keep sub-bands contiguous and ordered so GN groups and grouped conv line up
|
|
118
131
|
y = jnp.concatenate([LL, HL, LH, HH], axis=0) # (4*C, H/2, W/2)
|
|
119
132
|
|
|
133
|
+
# Band-aligned normalization (no cross-band statistics)
|
|
120
134
|
y = self.pre_norm(y)
|
|
121
135
|
|
|
122
|
-
y = self.proj(y) # (
|
|
136
|
+
y = self.proj(y) # (out_channels, H/2, W/2)
|
|
123
137
|
y = self.act(y)
|
|
124
138
|
|
|
125
139
|
y = self.dropout(y, inference=inference, key=key)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.4.6a2"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|