การดำเนินการเทนเซอร์ที่ยืดหยุ่นและทรงพลังสำหรับรหัสที่อ่านได้และเชื่อถือได้
รองรับ Numpy, Pytorch, Tensorflow, Jax และอื่น ๆ
torch.compile ไม่ยุ่งในกรณีที่คุณต้องการข้อโต้แย้งที่น่าเชื่อถือสำหรับการจัดสรรเวลาเพื่อเรียนรู้เกี่ยวกับ Einsum และ Einops ... Tim Rocktäschel
เขียนรหัสที่ดีกว่าด้วย pytorch และ einops? Andrej Karpathy
ช้า แต่แน่นอนว่า Einops กำลังซึมเข้าไปในทุกซอกและรหัสของฉัน หากคุณพบว่าตัวเองกำลังเดินไปรอบ ๆ เทนเซอร์มิลเลียน
ข้อความรับรองเพิ่มเติม
ธรรมดาและเรียบง่าย:
pip install einops บทเรียนเป็นวิธีที่สะดวกที่สุดในการดู einops ในการดำเนินการ
Kapil Sachdeva บันทึกอินโทรเล็ก ๆ ของ Einops
einops มี API ที่เรียบง่าย แต่ทรงพลัง
การดำเนินการหลักสามครั้งให้ (บทช่วยสอนของ Einops แสดงการซ้อนกันปก, การเปลี่ยนรูปร่าง, การขนย้าย, บีบ/ไม่คับ
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 ) เพิ่มเติมในภายหลังกับครอบครัวคือฟังก์ชั่น pack และ unpack (ดีกว่าสแต็ก/แยก/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' )ในที่สุด Einops ให้ Einsum ได้รับการสนับสนุนชื่อหลายตัวอักษร:
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 เป็นเลเยอร์เชิงเส้นทั่วไปเหมาะสำหรับมิกเตอร์ MLP และสถาปัตยกรรมที่คล้ายกัน
EINOPS ให้เลเยอร์ ( einops เก็บรุ่นแยกต่างหากสำหรับแต่ละเฟรมเวิร์ก) ที่สะท้อนถึงฟังก์ชั่นที่สอดคล้องกัน
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 ),
)ไม่จำเป็นต้องแบนอีกต่อไป!
นอกจากนี้เลเยอร์ไฟฉายเป็นสิ่งที่สามารถทำได้และสามารถรวบรวมได้ การดำเนินการคือคบเพลิง compile-able แต่ไม่สามารถใช้สคริปต์ได้เนื่องจากข้อ จำกัด ของ Torch.jit.script
einops หมายถึงสัญกรณ์ที่ได้รับแรงบันดาลใจจากไอน์สไตน์สำหรับการดำเนินงาน (แม้ว่า "การดำเนินงานของไอน์สไตน์" นั้นน่าดึงดูดและจดจำได้ง่ายขึ้น)
สัญกรณ์ได้รับแรงบันดาลใจอย่างหลวม ๆ จากการรวม Einstein (โดยเฉพาะอย่างยิ่งโดย numpy.einsum การดำเนินการ)
einops ! y = x . view ( x . shape [ 0 ], - 1 )
y = rearrange ( x , 'b c h w -> b (c h w)' ) ในขณะที่สองบรรทัดนี้ทำงานเดียวกันใน บาง บริบท แต่อันที่สองให้ข้อมูลเกี่ยวกับอินพุตและเอาต์พุต กล่าวอีกนัยหนึ่ง einops มุ่งเน้นไปที่อินเทอร์เฟซ: อินพุตและเอาต์พุตคืออะไร ไม่ใช่ วิธี การคำนวณเอาต์พุต
การดำเนินการถัดไปมีลักษณะคล้ายกัน:
y = rearrange ( x , 'time c h w -> time (c h w)' )แต่มันให้คำแนะนำแก่ผู้อ่าน: นี่ไม่ใช่ชุดภาพอิสระที่เรากำลังประมวลผล แต่เป็นลำดับ (วิดีโอ)
ข้อมูลความหมายทำให้รหัสอ่านและบำรุงรักษาง่ายขึ้น
พิจารณาตัวอย่างเดียวกัน:
y = x . view ( x . shape [ 0 ], - 1 ) # x: (batch, 256, 19, 19)
y = rearrange ( x , 'b c h w -> b (c h w)' )บรรทัดที่สองตรวจสอบว่าอินพุตมีสี่มิติ แต่คุณสามารถระบุขนาดเฉพาะ ที่ตรงข้ามกับการเขียนความคิดเห็นเกี่ยวกับรูปร่างเนื่องจากความคิดเห็นไม่ได้ป้องกันข้อผิดพลาดไม่ได้ทดสอบและไม่มีการตรวจสอบรหัสมักจะล้าสมัย
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 )ด้านล่างเรามีอย่างน้อยสองวิธีในการกำหนดการดำเนินการเชิงลึกถึงพื้นที่ว่าง
# 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 )มีอย่างน้อยสี่วิธีในการทำ เฟรมเวิร์กอันไหนที่ใช้?
รายละเอียดเหล่านี้จะถูกละเว้นเนื่องจาก โดยปกติแล้ว จะไม่สร้างความแตกต่าง แต่มันสามารถสร้างความแตกต่างได้อย่างมาก (เช่นถ้าคุณใช้ convolutions ที่จัดกลุ่มในขั้นตอนต่อไป) และคุณต้องการระบุสิ่งนี้ในรหัสของคุณ
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 )ตัวอย่างเหล่านี้แสดงให้เห็นว่าเราไม่ได้ใช้การดำเนินการแยกต่างหากสำหรับการรวม 1D/2D/3D ซึ่งทั้งหมดถูกกำหนดไว้ในรูปแบบที่สม่ำเสมอ
ช่องว่างในเชิงลึกและความลึกถึงมีการกำหนดในหลาย ๆ เฟรมเวิร์ก แต่ความกว้างถึงความสูงเป็นอย่างไร? ไปที่นี่:
rearrange ( x , 'b c h (w w2) -> b c (h w2) w' , w2 = 2 )แม้แต่ฟังก์ชั่นง่าย ๆ ก็ถูกกำหนดแตกต่างกันโดยเฟรมเวิร์กที่แตกต่างกัน
y = x . flatten () # or flatten(x) สมมติว่ารูปร่างของ x คือ (3, 4, 5) จากนั้น y มีรูปร่าง ...
(60,)(3, 20) einops ทำงานในลักษณะเดียวกันในทุกเฟรมเวิร์ก
ตัวอย่าง: tile เทียบกับ repeat ทำให้เกิดความสับสนมากมาย ในการคัดลอกภาพตามความกว้าง:
np . tile ( image , ( 1 , 2 )) # in numpy
image . repeat ( 1 , 2 ) # pytorch's repeat ~ numpy's tileด้วย Einops คุณไม่จำเป็นต้องถอดรหัสแกนไหนซ้ำแล้วซ้ำอีก:
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 .)ข้อความรับรองให้มุมมองของผู้ใช้ในคำถามเดียวกัน
Einops ทำงานร่วมกับ ...
นอกจากนี้ Einops สามารถใช้กับเฟรมเวิร์กใด ๆ ที่รองรับมาตรฐาน Python Array API ซึ่งรวมถึง
มีการจัดเตรียม DevContainer สภาพแวดล้อมนี้สามารถใช้งานได้ในเครื่องหรือบนเซิร์ฟเวอร์ของคุณหรือภายในรหัส GitHub ในการเริ่มต้นด้วย devcontainers ในรหัส VS, โคลน repo และคลิก 'เปิดใหม่ใน DevContainer'
เริ่มต้นจากเวอร์ชันถัดไป Einops จะแจกจ่ายการทดสอบเป็นส่วนหนึ่งของแพ็คเกจ เพื่อเรียกใช้การทดสอบ:
# pip install einops
python -m einops.tests.run_tests numpy pytorch jax --pip-install numpy pytorch jax เป็นตัวอย่างชุดย่อยของเฟรมเวิร์กที่ทดสอบได้ใด ๆ สามารถให้ได้ ทุกเฟรมเวิร์กได้รับการทดสอบกับ numpy ดังนั้นจึงเป็นข้อกำหนดสำหรับการทดสอบ
การระบุ --pip-install จะติดตั้งข้อกำหนดใน VirtualENV ปัจจุบันและควรละเว้นหากติดตั้งการพึ่งพาในเครื่อง
เพื่อสร้าง/ทดสอบเอกสาร:
hatch run docs:serve # Serving on http://localhost:8000/ โปรดใช้บันทึก bibtex ต่อไปนี้
@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 ทำงานร่วมกับ Python 3.8 หรือใหม่กว่า