torch-einops-kit 0.1.3__tar.gz → 0.1.4__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.
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/PKG-INFO +1 -1
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/pyproject.toml +1 -1
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_padding.py +26 -10
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/scaleValues.py +24 -11
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/README.md +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/__init__.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_cat_and_stack.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_dimensions.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_helpers.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_masking.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_semiotics.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_slicing.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/_theTypes.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/device.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/einops.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/nn.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/py.typed +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/save_load.py +0 -0
- {torch_einops_kit-0.1.3 → torch_einops_kit-0.1.4}/src/torch_einops_kit/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: torch-einops-kit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Typed tensor-shaping, masking, padding, device-routing, and checkpoint utilities for PyTorch and `einops`. A superset of `lucidrains/torch-einops-utils` with similar utilities from other lucidrains packages. Adds strict typing, extensive tests, and comprehensive docstrings.
|
|
5
5
|
Keywords: artificial intelligence,einops,machine learning,pytorch,torch
|
|
6
6
|
Author: Phil Wang, Hunter Hogan
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "torch-einops-kit"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
description = "Typed tensor-shaping, masking, padding, device-routing, and checkpoint utilities for PyTorch and `einops`. A superset of `lucidrains/torch-einops-utils` with similar utilities from other lucidrains packages. Adds strict typing, extensive tests, and comprehensive docstrings."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -289,32 +289,42 @@ def pad_sequence(
|
|
|
289
289
|
return_stacked: Literal[True] = True,
|
|
290
290
|
return_lens: Literal[False] = False,
|
|
291
291
|
pad_lens: bool = False
|
|
292
|
-
) -> Tensor
|
|
293
|
-
# `list[Tensor] | None` could create confusion: see the tuple | None overloads.
|
|
292
|
+
) -> Tensor: ...
|
|
294
293
|
@overload
|
|
295
294
|
def pad_sequence(
|
|
296
295
|
tensors: Sequence[Tensor], *, dim: int = -1, value: float = 0., left: bool = False, dim_stack: int = 0,
|
|
297
296
|
return_stacked: Literal[False],
|
|
298
297
|
return_lens: Literal[False] = False,
|
|
299
298
|
pad_lens: bool = False
|
|
300
|
-
) -> list[Tensor]
|
|
301
|
-
# TODO return `tuple | None` is problematic. See `test_better_pad_sequence`. Pyright gives a confusing error: "None is not iterable" when trying to unpack the tuple.
|
|
299
|
+
) -> list[Tensor]: ...
|
|
302
300
|
@overload
|
|
303
301
|
def pad_sequence(
|
|
304
302
|
tensors: Sequence[Tensor], *, dim: int = -1, value: float = 0., left: bool = False, dim_stack: int = 0,
|
|
305
303
|
return_stacked: Literal[True] = True,
|
|
306
304
|
return_lens: Literal[True],
|
|
307
305
|
pad_lens: bool = False
|
|
308
|
-
) -> tuple[Tensor, Tensor]
|
|
306
|
+
) -> tuple[Tensor, Tensor]: ...
|
|
309
307
|
@overload
|
|
310
308
|
def pad_sequence(
|
|
311
309
|
tensors: Sequence[Tensor], *, dim: int = -1, value: float = 0., left: bool = False, dim_stack: int = 0,
|
|
312
310
|
return_stacked: Literal[False],
|
|
313
311
|
return_lens: Literal[True],
|
|
314
312
|
pad_lens: bool = False
|
|
315
|
-
) -> tuple[list[Tensor], Tensor]
|
|
313
|
+
) -> tuple[list[Tensor], Tensor]: ...
|
|
314
|
+
@overload
|
|
315
|
+
def pad_sequence(
|
|
316
|
+
tensors: list[Tensor] = [], # noqa: B006
|
|
317
|
+
*, dim: int = -1, value: float = 0.0, left: bool = False, dim_stack: int = 0,
|
|
318
|
+
return_stacked: bool = True, return_lens: bool = False, pad_lens: bool = False
|
|
319
|
+
) -> None: ...
|
|
320
|
+
@overload
|
|
321
|
+
def pad_sequence(
|
|
322
|
+
tensors: tuple[()] = (),
|
|
323
|
+
*, dim: int = -1, value: float = 0.0, left: bool = False, dim_stack: int = 0,
|
|
324
|
+
return_stacked: bool = True, return_lens: bool = False, pad_lens: bool = False
|
|
325
|
+
) -> None: ...
|
|
316
326
|
def pad_sequence(
|
|
317
|
-
tensors: Sequence[Tensor],
|
|
327
|
+
tensors: Sequence[Tensor] = (),
|
|
318
328
|
*,
|
|
319
329
|
dim: int = -1,
|
|
320
330
|
value: float = 0.0,
|
|
@@ -443,7 +453,13 @@ def pad_sequence(
|
|
|
443
453
|
|
|
444
454
|
return output
|
|
445
455
|
|
|
446
|
-
|
|
456
|
+
@overload
|
|
457
|
+
def pad_sequence_and_cat(tensors: Sequence[Tensor], *, dim_cat: int = 0, dim: int = -1, value: float = 0., left: bool = False) -> Tensor:...
|
|
458
|
+
@overload
|
|
459
|
+
def pad_sequence_and_cat(tensors: list[Tensor] = [], *, dim_cat: int = 0, dim: int = -1, value: float = 0., left: bool = False) -> None:... # noqa: B006
|
|
460
|
+
@overload
|
|
461
|
+
def pad_sequence_and_cat(tensors: tuple[()]=(), *, dim_cat: int = 0, dim: int = -1, value: float = 0., left: bool = False) -> None:...
|
|
462
|
+
def pad_sequence_and_cat(tensors: Sequence[Tensor]=(), *, dim_cat: int = 0, dim: int = -1, value: float = 0., left: bool = False) -> Tensor | None:
|
|
447
463
|
"""Pad `tensors` to a shared length along `dim` and concatenate along `dim_cat`.
|
|
448
464
|
|
|
449
465
|
You can use `pad_sequence_and_cat` to align and merge a heterogeneous-length sequence of `Tensor`
|
|
@@ -498,12 +514,12 @@ def pad_sequence_and_cat(tensors: Sequence[Tensor], *, dim_cat: int = 0, dim: in
|
|
|
498
514
|
[3] tests/test_utils.py
|
|
499
515
|
"""
|
|
500
516
|
padded: Tensor | list[Tensor] | None = pad_sequence(tensors, dim=dim, value=value, left=left, return_stacked=False, return_lens=False)
|
|
501
|
-
if padded is not None:
|
|
517
|
+
if padded is not None: # pyright: ignore[reportUnnecessaryComparison]
|
|
502
518
|
return cat(padded, dim=dim_cat)
|
|
503
519
|
return padded
|
|
504
520
|
|
|
505
521
|
"""
|
|
506
|
-
Some
|
|
522
|
+
Some of the logic in this module may be protected by the following.
|
|
507
523
|
|
|
508
524
|
MIT License
|
|
509
525
|
|
|
@@ -107,7 +107,8 @@ def l2norm(t: Tensor) -> Tensor:
|
|
|
107
107
|
"""
|
|
108
108
|
return F.normalize(t, dim=-1, p=2)
|
|
109
109
|
|
|
110
|
-
def masked_mean(t: Tensor, mask: Tensor | None = None, dim: torch.Size | list[int] | tuple[int, ...] | int | None = None, eps: float = 1e-5
|
|
110
|
+
def masked_mean(t: Tensor, mask: Tensor | None = None, dim: torch.Size | list[int] | tuple[int, ...] | int | None = None, eps: float = 1e-5
|
|
111
|
+
, *, keepdim: bool = False) -> Tensor:
|
|
111
112
|
"""Compute the mean of `t` over positions selected by `mask`.
|
|
112
113
|
|
|
113
114
|
You can use this function to average only the elements of `t` where `mask` is `True`, ignoring
|
|
@@ -131,6 +132,9 @@ def masked_mean(t: Tensor, mask: Tensor | None = None, dim: torch.Size | list[in
|
|
|
131
132
|
eps : float = 1e-5
|
|
132
133
|
A small value added to the denominator to prevent division by zero when computing the masked
|
|
133
134
|
mean along a dimension.
|
|
135
|
+
keepdim : bool = False
|
|
136
|
+
When `True`, the reduced dimension is retained as a size-one dimension in `result`, allowing
|
|
137
|
+
`result` to broadcast against `t`.
|
|
134
138
|
|
|
135
139
|
Returns
|
|
136
140
|
-------
|
|
@@ -172,6 +176,15 @@ def masked_mean(t: Tensor, mask: Tensor | None = None, dim: torch.Size | list[in
|
|
|
172
176
|
# result == tensor([1.0, 3.5])
|
|
173
177
|
```
|
|
174
178
|
|
|
179
|
+
Compute the sequence-level mean of transformer activations with `keepdim=True` to preserve the
|
|
180
|
+
sequence dimension for broadcasting, used in the mean-variance split residual update [4][5]:
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
mean_x = masked_mean(x, mask=mask, dim=-2, keepdim=True)
|
|
184
|
+
mean_residual = masked_mean(residual, mask=mask, dim=-2, keepdim=True)
|
|
185
|
+
centered_x = x - mean_x
|
|
186
|
+
```
|
|
187
|
+
|
|
175
188
|
References
|
|
176
189
|
----------
|
|
177
190
|
[1] torch.Tensor.mean - PyTorch documentation
|
|
@@ -180,20 +193,20 @@ def masked_mean(t: Tensor, mask: Tensor | None = None, dim: torch.Size | list[in
|
|
|
180
193
|
|
|
181
194
|
[3] tests.test_utils.test_masked_mean
|
|
182
195
|
|
|
196
|
+
[4] Lu, P. (2026). Mean Mode Screaming: Mean-Variance Split Residuals for 1000-Layer Diffusion
|
|
197
|
+
Transformers. arXiv:2605.06169.
|
|
198
|
+
https://arxiv.org/abs/2605.06169
|
|
199
|
+
[5] x_transformers.x_transformers.MVSplitResidualUpdate.forward - lucidrains/x-transformers
|
|
200
|
+
https://github.com/lucidrains/x-transformers
|
|
201
|
+
|
|
183
202
|
"""
|
|
184
203
|
if not exists(mask):
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if mask.ndim < t.ndim:
|
|
188
|
-
mask = pad_right_ndim(mask, t.ndim - mask.ndim)
|
|
189
|
-
|
|
190
|
-
mask = mask.expand_as(t)
|
|
204
|
+
mask = torch.ones_like(t, dtype=torch.bool)
|
|
191
205
|
|
|
192
|
-
|
|
193
|
-
return t[mask].mean() if mask.any() else t[mask].sum()
|
|
206
|
+
mask = pad_right_ndim(mask, max(0, t.ndim - mask.ndim)).expand_as(t)
|
|
194
207
|
|
|
195
|
-
num: Tensor = (t * mask).sum(dim=dim)
|
|
196
|
-
den: Tensor = mask.sum(dim=dim)
|
|
208
|
+
num: Tensor = (t * mask).sum(dim=dim, keepdim=keepdim)
|
|
209
|
+
den: Tensor = mask.sum(dim=dim, keepdim=keepdim)
|
|
197
210
|
|
|
198
211
|
return num / den.clamp(min=eps)
|
|
199
212
|
|
|
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
|