Opérations de tenseur flexibles et puissantes pour un code lisible et fiable.
Prend en charge Numpy, Pytorch, Tensorflow, Jax et autres.
torch.compile sans hasse.Dans le cas où vous auriez besoin d'arguments convaincants pour réserver du temps pour en savoir plus sur Einsum et Einops ... Tim Rocktäschel
Écrire un meilleur code avec Pytorch et Einops? Andrej Karpathy
Lentement mais sûrement, Einops s'infiltre dans tous les coins et recoins de mon code. Si vous vous retrouvez à vous promener dans des tenseurs dimensionnels bazillion, cela pourrait changer votre vie Nasim Rahaman
Plus de témoignages
Simple et simple:
pip install einops Les tutoriels sont le moyen le plus pratique de voir einops en action
Kapil Sachdeva a enregistré une petite introduction à Einops.
einops a une API minimaliste mais puissante.
Trois opérations principales fournies (le tutoriel Einops montre ces empilées de couvertures, remodeler, transposition, compression / non-éventualité, répéter, carreaux, concaténate, vue et nombreuses réductions)
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 ) Les ajouts ultérieurs à la famille sont des fonctions pack et unpack (mieux que pile / fractionnement / concaténate):
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' )Enfin, Einops fournit à Einsum une prise en charge des noms à plusieurs lettres:
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 est une couche linéaire générique, parfaite pour les mélangeurs MLP et les architectures similaires.
Einops fournit des couches ( einops conserve une version distincte pour chaque cadre) qui reflète les fonctions correspondantes
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 ),
)Plus d'aplatissement nécessaire!
De plus, les couches de torche comme celles-ci sont scénariées et compilées. Les opérations sont TORCH.COMPILEABLE, mais pas le script en raison des limites de Torch.jit.script.
einops signifie Einstein inspiré de la notation pour les opérations (bien que les «opérations d'Einstein» soient plus attrayantes et plus faciles à retenir).
La notation a été inspirée de manière lâche par la somme d'Einstein (en particulier par l'opération numpy.einsum ).
einops ?! y = x . view ( x . shape [ 0 ], - 1 )
y = rearrange ( x , 'b c h w -> b (c h w)' ) Alors que ces deux lignes font le même travail dans un certain contexte, la seconde fournit des informations sur l'entrée et la sortie. En d'autres termes, einops se concentre sur l'interface: quelle est l'entrée et la sortie , pas la façon dont la sortie est calculée.
L'opération suivante semble similaire:
y = rearrange ( x , 'time c h w -> time (c h w)' )Mais cela donne au lecteur un indice: ce n'est pas un lot indépendant d'images que nous traitons, mais plutôt une séquence (vidéo).
Les informations sémantiques rendent le code plus facile à lire et à maintenir.
Reconsidérez le même exemple:
y = x . view ( x . shape [ 0 ], - 1 ) # x: (batch, 256, 19, 19)
y = rearrange ( x , 'b c h w -> b (c h w)' )La deuxième ligne vérifie que l'entrée a quatre dimensions, mais vous pouvez également spécifier des dimensions particulières. Cela s'oppose à la simple rédaction de commentaires sur les formes car les commentaires n'empêchent pas les erreurs, et non testés, et sans revue de code, il a tendance à être obsolète
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 )Ci-dessous, nous avons au moins deux façons de définir l'opération de profondeur à l'espace
# 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 )Il y a au moins quatre autres façons de le faire. Lequel est utilisé par le cadre?
Ces détails sont ignorés, car généralement cela ne fait aucune différence, mais cela peut faire une grande différence (par exemple, si vous utilisez des convolutions groupées dans la prochaine étape), et vous souhaitez spécifier cela dans votre code.
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 )Ces exemples ont démontré que nous n'utilisons pas d'opérations distinctes pour la mise en commun 1D / 2D / 3D, celles-ci sont toutes définies de manière uniforme.
L'espace à profondeur et la profondeur à l'espace sont définis dans de nombreux cadres, mais qu'en est-il de la largeur à la hauteur? Voici:
rearrange ( x , 'b c h (w w2) -> b c (h w2) w' , w2 = 2 )Même les fonctions simples sont définies différemment par différents cadres
y = x . flatten () # or flatten(x) Supposons que la forme de x était (3, 4, 5) , puis y a la forme ...
(60,)(3, 20) einops fonctionne de la même manière dans tous les cadres.
Exemple: tile vs repeat provoquent beaucoup de confusion. Pour copier l'image le long de la largeur:
np . tile ( image , ( 1 , 2 )) # in numpy
image . repeat ( 1 , 2 ) # pytorch's repeat ~ numpy's tileAvec Einops, vous n'avez pas besoin de déchiffrer quel axe a été répété:
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 .)Les témoignages fournissent une perspective des utilisateurs sur la même question.
Einops travaille avec ...
De plus, Einops peut être utilisé avec n'importe quel cadre qui prend en charge la norme API Python Array, qui comprend
DevContainer est fourni, cet environnement peut être utilisé localement, ou sur votre serveur, ou dans des codes GitHub. Pour commencer par DevContainers dans VS Code, clone Repo et cliquez sur «Rouvrir dans DevContainer».
À partir de la prochaine version, Einops distribuera des tests dans le cadre du package. Pour exécuter des tests:
# pip install einops
python -m einops.tests.run_tests numpy pytorch jax --pip-install numpy pytorch jax est un exemple, tout sous-ensemble de cadres testables peut être fourni. Chaque cadre est testé contre Numpy, c'est donc une exigence pour les tests.
Spécifier --pip-install installera les exigences dans le virtualenv actuel et doit être omis si les dépendances sont installées localement.
Pour construire / tester les documents:
hatch run docs:serve # Serving on http://localhost:8000/ Veuillez utiliser l'enregistrement Bibtex suivant
@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}
}
einops fonctionne avec Python 3.8 ou version ultérieure.