需自行安装 numpy、pytorch、jax 等后端框架,einops 本身不带;使用 array API 标准后端时需从 einops.array_api 导入;部分后端(如 flax、paddle、oneflow、tinygrad)为社区维护

einops
arogozhnikovMIT活跃维护用一套可读的 Einstein 记号统一 PyTorch、JAX、TensorFlow 等框架的张量操作,让 reshape、转置、rearrange 这类代码更清晰、更不容易出错。
Flexible and powerful tensor operations for readable and reliable code (for pytorch, jax, TF and others)
pip install einopsREADME 未说明,纯 Python 库,无 GPU 或显存要求
用爱因斯坦式记法统一各框架的张量重排、归约与复制操作,让形状变换代码可读且自带校验
用一套可读的 Einstein 记号统一 PyTorch、JAX、TensorFlow 等框架的张量操作,让 reshape、转置、rearrange 这类代码更清晰、更不容易出错。
核心能力
- 用 rearrange 按模式字符串重排张量维度
- 用 reduce 在重排同时做 mean、max 等归约
- 用 repeat 沿新轴或已有轴复制张量
- 用 pack/unpack 可逆地打包多个不同维度的张量
- 用 einsum 支持多字母轴名且跨框架通用
容易踩的坑
- v0.9.0devv0.9.0dev: dev. release for public testing (mostly typing changes)pre-release2026-07-05 · 2026-07-05 04:47 UTC
查看更新说明
What's Changed
- upgrade python versions, stop using/supporting python 3.9, set version to 0.9.0dev by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/396
- use list/dict/tuple instead of List/Dict/Tuple by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/397
- typing.Sequence -> collections.abc.Sequence + switch off a couple of ruff rules by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/398
- add einops playground by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/400
- MLXBackend: Rename add_axes method to add_axis by @Datamance in https://github.com/arogozhnikov/einops/pull/401
- framework name: mlx -> mlx.core by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/403
- fix the
einops.ReductionCallabletype by @jorenham in https://github.com/arogozhnikov/einops/pull/405 - modernize annotations with PEP 604 union syntax by @jorenham in https://github.com/arogozhnikov/einops/pull/410
- explicitly mark type aliases as
TypeAlias(PEP 613) by @jorenham in https://github.com/arogozhnikov/einops/pull/411 - Add ruff rules, set correct requires-version, update ruff by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/412
- proper typing of array_api submodule by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/413
- remove unnecessary overloads by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/414
- fix mypy errors in
einops.parsingand add missing annotations by @jorenham in https://github.com/arogozhnikov/einops/pull/417 - fill in the missing annotations in
einops.layers.oneflowby @jorenham in https://github.com/arogozhnikov/einops/pull/421 - fix mypy errors in
einops.layers.paddleand add missing annotations by @jorenham in https://github.com/arogozhnikov/einops/pull/422 - fix mypy errors in
einops.layers.flaxand add missing annotations by @jorenham in https://github.com/arogozhnikov/einops/pull/420 - fix mypy errors in
einops.layers.torchand add missing annotations by @jorenham in https://github.com/arogozhnikov/einops/pull/425 - annotate the return type of
array_api.asnumpyby @jorenham in https://github.com/arogozhnikov/einops/pull/418 - fix mypy errors in
einops.layers.__init__and add missing annotations by @jorenham in https://github.com/arogozhnikov/einops/pull/419 - add
hatch run checkby @arogozhnikov in https://github.com/arogozhnikov/einops/pull/426 - minor: remove unused function, adjust test by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/427
- suppress/fix various mypy complains by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/428
- delete fake setup.py by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/429
- more typing work by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/430
- resolve rest of mypy complains by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/432
- create empty env "pypi" by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/437
- switch deployment to uv from hatch by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/438
New Contributors
- @Datamance made their first contribution in https://github.com/arogozhnikov/einops/pull/401
- @jorenham made their first contribution in https://github.com/arogozhnikov/einops/pull/405
Full Changelog: https://github.com/arogozhnikov/einops/compare/v0.8.2...v0.9.0dev
- v0.8.2v0.8.2: full MLX backend, rely on torch.compile, set python 3.9 as minimum最新正式版2026-01-26 · 2026-01-26 04:12 UTC
- torch.compile: previously we relied on registration of einops in torch.compile. This registration was called by torch. Now with torch >= 2.8
torch.compileengine can compile einops operations without additional hints/registrations. - recommended backend for MLX is still
einops.array_api.<operation>, but since community asked multiple times for support ofeinops.einsum, there is now MLX backend in einops, soeinops.<operation>would also work with MLX. - minor improvements to docs, and mention of several related projects.
What's Changed
- Update README.md by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/366
- Update codebase, introduce consistency checks, update EinMix tutorial by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/374
- Update python versions in tests, change min supported version to 3.9 by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/364
- mention cubed as one more backend via array api by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/375
- Extend tests for torch.compile by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/382
- add einops.jl and einops for R in docs_src/pages/projects.md by @Qile0317 in https://github.com/arogozhnikov/einops/pull/383
- mention ein color and AlphaFold3 by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/389
- A bit more of compile tests by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/390
- Patch #391 (conflicts in multithreading initialization) by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/392
- switch off debug importing by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/393
- Skip
allow_in_graphif torch >= 2.8 by @guilhermeleobas in https://github.com/arogozhnikov/einops/pull/394 - Add mlx backend by @ifsheldon in https://github.com/arogozhnikov/einops/pull/376
- update testing by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/395
New Contributors
- @Qile0317 made their first contribution in https://github.com/arogozhnikov/einops/pull/383
- @guilhermeleobas made their first contribution in https://github.com/arogozhnikov/einops/pull/394
- @ifsheldon made their first contribution in https://github.com/arogozhnikov/einops/pull/376
Full Changelog: https://github.com/arogozhnikov/einops/compare/v0.8.1...v0.8.2
- torch.compile: previously we relied on registration of einops in torch.compile. This registration was called by torch. Now with torch >= 2.8
- v0.8.1v0.8.1 Multiple improvements2025-02-09 · 2025-02-09 03:16 UTC
查看更新说明
What's Changed
TLDR:
- ellipsis is added to EinMix
- tests moved into the package
- devcontainer provided
- added backend for pyTensor
- niceties: citation, docs, fixed broken links
- this did not require any changes in einops, but array API is supported by more libs these days, and einops can operate on them
PRs:
- Update README.md by @project-delphi in https://github.com/arogozhnikov/einops/pull/316
- change tests for numpy2.0 + fix for numpy regression by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/325
- PR from @pzread: fix tinygrad concat + changed formatting to fix CI errors by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/329
- Add devcontainer and dockerfile by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/330
- delete experimental/indexing by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/333
- Use same ruff version in CI and in pre-commit, reformat notebooks by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/336
- Delete chainer backend by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/335
- Mention support of cupy, pydata/sparse, ndonnx and others by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/337
- Moving tests into source tree by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/338
- Update documentation, mention changes in testing + devcontainers by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/339
- Auto-deploy mkdocs + update mkdocs requirements by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/341
- Add dict syntax to the einops layers example by @eadadi in https://github.com/arogozhnikov/einops/pull/342
- include CITATION.cff for einops by @luke-carlson in https://github.com/arogozhnikov/einops/pull/345
- mention that cupy and jax now support array api by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/348
- Fix docs broken links after
master->mainmigration by @VladKha in https://github.com/arogozhnikov/einops/pull/349 - [Paddle] Update _backends.py to support pir.Value by @HydrogenSulfate in https://github.com/arogozhnikov/einops/pull/353
- Update docstring for einops.reduce by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/358
- add a comment about axes names by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/359
- Add support of ellipsis to einmix by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/360
- Add PyTensor backend by @ricardoV94 in https://github.com/arogozhnikov/einops/pull/362
- rename input_dict, document parameter by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/363
New Contributors
- @project-delphi made their first contribution in https://github.com/arogozhnikov/einops/pull/316
- @eadadi made their first contribution in https://github.com/arogozhnikov/einops/pull/342
- @luke-carlson made their first contribution in https://github.com/arogozhnikov/einops/pull/345
- @VladKha made their first contribution in https://github.com/arogozhnikov/einops/pull/349
- @HydrogenSulfate made their first contribution in https://github.com/arogozhnikov/einops/pull/353
- @ricardoV94 made their first contribution in https://github.com/arogozhnikov/einops/pull/362
Full Changelog: https://github.com/arogozhnikov/einops/compare/v0.8.0...v0.8.1
- v0.8.0v0.8.0: tinygrad, small fixes and updates2024-04-28 · 2024-04-28 04:07 UTC
查看更新说明
TLDR
- tinygrad backend added
- resolve warning in py3.11 related to docstring
- remove graph break for unpack
- breaking TF layers were updated to follow new instructions, new layers compatible with TF 2.16, and not compatible with old TF (certainly does not work with TF2.13)
What's Changed
- Fix invalid escape sequence in einsum docstring by @atwam in https://github.com/arogozhnikov/einops/pull/298
- Tinygrad support by @blueridanus in https://github.com/arogozhnikov/einops/pull/297
- Coerce bool to int in unpack by @drubinstein in https://github.com/arogozhnikov/einops/pull/287
- Remove oneflow from testing by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/289
- tests: fix torch installation to force CPU by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/288
- Allow anonymous axes in parse_shape, fix #302 by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/303
- Codebase standards + update TF layers by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/318
- update github actions by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/319
New Contributors
- @drubinstein made their first contribution in https://github.com/arogozhnikov/einops/pull/287
- @atwam made their first contribution in https://github.com/arogozhnikov/einops/pull/298
- @blueridanus made their first contribution in https://github.com/arogozhnikov/einops/pull/297
Full Changelog: https://github.com/arogozhnikov/einops/compare/v0.7.0...v0.8.0
- v0.7.0V0.7.0: torch.compile, preserve axis identity, array api2023-10-01 · 2023-10-01 01:13 UTC
查看更新说明
Major changes:
torch.compilejust works, registration of operations happens automatically- JAX's distributed arrays can use ellipses, and in general ellipsis processing now preserves axis identity. This involved changing internal gears of einops.
- Array API:
einopsoperations can be used with any framework that follows the standard (seeeinops.array_api) - Python 3.7 is dead. Good bye, you were great at the time
- Gluon is dropped as previously announced
- reduce/repeat/rearrange all accept lists now
PRs list
- Preserve axis identity + drop python 3.7 by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/255
- Support array api by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/261
- add type-based caching by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/262
- Uniform support for list inputs across rearrange/reduce/repeat by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/263
- Drop gluon by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/264
- automatically register torch ops in torchdynamo by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/265
- release 0.7.0rc1, highlight changes in README by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/266
- cover dynamic shapes in torch.compile, introduce fallback if shape was not cacheable by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/275
- bump version by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/276
- fix #279, update description by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/281
- Add support for any/all reductions in einops.reduce by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/282
- maintenance: cache pip dependencies by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/283
- maintenance: update versions of github actions by @arogozhnikov in https://github.com/arogozhnikov/einops/pull/285
Full Changelog: https://github.com/arogozhnikov/einops/compare/v0.6.1...v0.7.0
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
https://user-images.githubusercontent.com/6318811/177030658-66f0eb5d-e136-44d8-99c9-86ae298ead5b.mp4
einops
Flexible and powerful tensor operations for readable and reliable code. Supports numpy, pytorch, jax, mlx and others.
Recent updates:
- 0.9.0: overhaul of typing in einops
- einops playground can run 2 of 4 example notebooks right in your browser
- 0.8.2: MLX backend added
- 0.8.0: tinygrad backend added, small fixes
- 0.7.0: no-hassle
torch.compile, support of array api standard and more - 10'000🎉: github reports that more than 10k project use einops
- einops 0.6 introduces packing and unpacking
Tweets
In case you need convincing arguments for setting aside time to learn about einsum and einops... Tim Rocktäschel
Writing better code with PyTorch and einops 👌 Andrej Karpathy
Slowly but surely, einops is seeping in to every nook and cranny of my code. If you find yourself shuffling around bazillion dimensional tensors, this might change your life Nasim Rahaman
Contents
- Installation
- Documentation
- Tutorial
- API micro-reference
- Why use einops
- Supported frameworks
- Citing
- Repository and discussions
Installation
Plain and simple:
pip install einops
(uv pip install einops works as well)
Tutorials
Tutorials are the most convenient way to see einops in action
- part 1: einops fundamentals
- part 2: einops for deep learning
- part 3: packing and unpacking
- part 4: improve pytorch code with einops
Kapil Sachdeva recorded a small intro to einops.
API
einops has a minimalistic yet powerful API.
Three core operations provided (einops tutorial shows those cover stacking, reshape, transposition, squeeze/unsqueeze, repeat, tile, concatenate, view and numerous reductions)
from einops import rearrange, reduce, repeat
# rearrange elements according to the pattern
output_tensor = rearrange(input_tensor, 't b c -> b c t')
# combine rearrangement and reduction
output_tensor = reduce(input_tensor, 'b c (h h2) (w w2) -> b h w c', 'mean', h2=2, w2=2)
# copy along a new axis
output_tensor = repeat(input_tensor, 'h w -> h w c', c=3)
Later additions to the family are pack and unpack functions (better than stack/split/concatenate):
from einops import pack, unpack
# pack and unpack allow reversibly 'packing' multiple tensors into one.
# Packed tensors may be of different dimensionality:
packed, ps = pack([class_token_bc, image_tokens_bhwc, text_tokens_btc], 'b * c')
class_emb_bc, image_emb_bhwc, text_emb_btc = unpack(transformer(packed), ps, 'b * c')
Finally, einops provides einsum with a support of multi-lettered names:
from einops import einsum, pack, unpack
# einsum is like ... einsum, generic and flexible dot-product
# but 1) axes can be multi-lettered 2) pattern goes last 3) works with multiple frameworks
C = einsum(A, B, 'b t1 head c, b t2 head c -> b head t1 t2')
EinMix
EinMix is a generic linear layer, perfect for MLP Mixers and similar architectures.
Layers
Einops provides layers (einops keeps a separate version for each framework) that reflect corresponding functions
from einops.layers.torch import Rearrange, Reduce
from einops.layers.tensorflow import Rearrange, Reduce
from einops.layers.flax import Rearrange, Reduce
from einops.layers.paddle import Rearrange, Reduce
from torch.nn import Sequential, Conv2d, MaxPool2d, Linear, ReLU
from einops.layers.torch import Rearrange
model = Sequential(
...,
Conv2d(6, 16, kernel_size=5),
MaxPool2d(kernel_size=2),
# flattening without need to write forward
Rearrange('b c h w -> b (c h w)'),
Linear(16*5*5, 120),
ReLU(),
Linear(120, 10),
)
No more flatten needed!
Operations and layers can be torch.compiled.
Naming
einops stands for Einstein-Inspired Notation for operations
(though "Einstein operations" is more attractive and easier to remember).
Notation was loosely inspired by Einstein summation (in particular by numpy.einsum operation).
Why use einops notation?!
Semantic information (being verbose in expectations)
y = x.view(x.shape[0], -1)
y = rearrange(x, 'b c h w -> b (c h w)')
While these two lines are doing the same job in some context,
the second one provides information about the input and output.
In other words, einops focuses on interface: what is the input and output, not how the output is computed.
The next operation looks similar:
y = rearrange(x, 'time c h w -> time (c h w)')
but it gives the reader a hint: this is not an independent batch of images we are processing, but rather a sequence (video).
Semantic information makes the code easier to read and maintain.
Convenient checks
Reconsider the same example:
y = x.view(x.shape[0], -1) # x: (batch, 256, 19, 19)
y = rearrange(x, 'b c h w -> b (c h w)')
The second line checks that the input has four dimensions, but you can also specify particular dimensions. That's opposed to just writing comments about shapes since comments don't prevent mistakes, not tested, and without code review tend to be outdated
y = x.view(x.shape[0], -1) # x: (batch, 256, 19, 19)
y = rearrange(x, 'b c h w -> b (c h w)', c=256, h=19, w=19)
Result is strictly determined
Below we have at least two ways to define the depth-to-space operation
# depth-to-space
rearrange(x, 'b c (h h2) (w w2) -> b (c h2 w2) h w', h2=2, w2=2)
rearrange(x, 'b c (h h2) (w w2) -> b (h2 w2 c) h w', h2=2, w2=2)
There are at least four more ways to do it. Which one is used by the framework?
These details are ignored, since usually it makes no difference, but it can make a big difference (e.g. if you use grouped convolutions in the next stage), and you'd like to specify this in your code.
Uniformity
reduce(x, 'b c (x dx) -> b c x', 'max', dx=2)
reduce(x, 'b c (x dx) (y dy) -> b c x y', 'max', dx=2, dy=3)
reduce(x, 'b c (x dx) (y dy) (z dz) -> b c x y z', 'max', dx=2, dy=3, dz=4)
These examples demonstrated that we don't use separate operations for 1d/2d/3d pooling, those are all defined in a uniform way.
Space-to-depth and depth-to space are defined in many frameworks but how about width-to-height? Here you go:
rearrange(x, 'b c h (w w2) -> b c (h w2) w', w2=2)
Framework independent behavior
Even simple functions are defined differently by different frameworks
y = x.flatten() # or flatten(x)
Suppose x's shape was (3, 4, 5), then y has shape ...
- numpy, pytorch, cupy, chainer, jax:
(60,) - keras, tensorflow.layers, gluon:
(3, 20)
einops works the same way in all frameworks.
Independence of framework terminology
Example: tile vs repeat causes lots of confusion. To copy image along width:
np.tile(image, (1, 2)) # in numpy
image.repeat(1, 2) # pytorch's repeat ~ numpy's tile
With einops you don't need to decipher which axis was repeated:
repeat(image, 'h w -> h (tile w)', tile=2) # in numpy
repeat(image, 'h w -> h (tile w)', tile=2) # in pytorch
repeat(image, 'h w -> h (tile w)', tile=2) # in tf
repeat(image, 'h w -> h (tile w)', tile=2) # in jax
repeat(image, 'h w -> h (tile w)', tile=2) # in cupy
... (etc.)
Testimonials provide users' perspective on the same question.
Supported frameworks
Einops works with ...
- numpy
- pytorch
- tensorflow
- jax
- cupy
- flax (community)
- paddle (community)
- oneflow (community)
- tinygrad (community)
- pytensor (community)
from einops import rearrange
=> from einops.array_api import rearrange
But actually it is even better: einops can be used with any framework that supports Python array API standard, to name a few:
- numpy >= 2.0
- MLX # yes, einops works with apple's framework
- pydata/sparse >= 0.15 # and works with sparse tensors
- cubed # and with distributed tensors too
- quantco/ndonnx
- jax
- cupy
- dask is supported via array-api-compat
Development
Devcontainer is provided, this environment can be used locally, or on your server, or within github codespaces. To start with devcontainers in vs code, clone repo, and click 'Reopen in Devcontainer'.
Starting from einops 0.8.1, einops distributes tests as a part of package.
# pip install einops pytest
python -m einops.tests.run_tests numpy pytorch jax --pip-install
numpy pytorch jax is an example, any subset of testable frameworks can be provided.
Every framework is tested against numpy, so it is a requirement for tests.
Specifying --pip-install will install requirements in current virtualenv,
and should be omitted if dependencies are installed locally.
To build/test docs:
hatch run docs:serve # Serving on http://localhost:8000/
Citing einops
Please use the following bibtex record
@inproceedings{
rogozhnikov2022einops,
title={Einops: Clear and Reliable Tensor Manipulations with Einstein-like Notation},
author={Alex Rogozhnikov},
booktitle={International Conference on Learning Representations},
year={2022},
url={https://openreview.net/forum?id=oapKSVM2bcj}
}
Supported python versions
einops works with python 3.10 or later.