Title: | Flexible, Powerful, and Readable Tensor Operations |
Version: | 0.2.1 |
Maintainer: | Qile Yang <qile.yang@berkeley.edu> |
Description: | Perform tensor operations using a concise yet expressive syntax inspired by the Python library of the same name. Reshape, rearrange, and combine multidimensional arrays for scientific computing, machine learning, and data analysis. Einops simplifies complex manipulations, making code more maintainable and intuitive. The original implementation is demonstrated in Rogozhnikov (2022) https://openreview.net/forum?id=oapKSVM2bcj. |
License: | MIT + file LICENSE |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.2 |
URL: | https://github.com/Qile0317/einops, https://qile0317.github.io/einops/ |
BugReports: | https://github.com/Qile0317/einops/issues |
Imports: | assertthat, FastUtils, glue, magrittr, r2r, R6, roperators |
Suggests: | abind, grid, imager, knitr, lifecycle, lintr, lobstr, rmarkdown, spelling, testthat (≥ 3.0.0), torch, zeallot |
Config/testthat/edition: | 3 |
VignetteBuilder: | knitr |
Depends: | R (≥ 3.5) |
LazyData: | true |
Language: | en-US |
NeedsCompilation: | no |
Packaged: | 2025-08-29 22:24:54 UTC; qile |
Author: | Qile Yang |
Repository: | CRAN |
Date/Publication: | 2025-09-03 21:40:08 UTC |
einops: Flexible, Powerful, and Readable Tensor Operations
Description
Perform tensor operations using a concise yet expressive syntax inspired by the Python library of the same name. Reshape, rearrange, and combine multidimensional arrays for scientific computing, machine learning, and data analysis. Einops simplifies complex manipulations, making code more maintainable and intuitive. The original implementation is demonstrated in Rogozhnikov (2022) https://openreview.net/forum?id=oapKSVM2bcj.
Author(s)
Maintainer: Qile Yang qile.yang@berkeley.edu (ORCID) [copyright holder]
See Also
Useful links:
Report bugs at https://github.com/Qile0317/einops/issues
Pipe operator
Description
See magrittr::%>%
for details.
Usage
lhs %>% rhs
Arguments
lhs |
A value or the magrittr placeholder. |
rhs |
A function call using the magrittr semantics. |
Value
The result of calling rhs(lhs)
.
Create an AddOnlyOrderedMap
instance
Description
This function initializes a new list-like object using the specified keys and values if provided. The resulting map preserves the order of insertion and does not allow modification or removal of existing entries.
The AddOnlyOrderedMap
can be interacted with exactly like a regular
list, possessing methods for [
, [[
, [<-
, and [[<-
with the same
behaviour, except that NULL cannot be passed in since removal is not
permitted.
The keys()
generic is defined for this class, which will return a list
of the keys in their insertion order. The has_key()
generic is also defined
for this class, returning TRUE/FALSE if a key exists. Lastly, the values()
generic is defined to get all values in insertion order.
Usage
AddOnlyOrderedMap(
keys = NULL,
values = NULL,
key_validator = Negate(is.null),
val_validator = Negate(is.null)
)
Arguments
keys |
Optional list. A vector of keys to initialize the map with. Can
be any R object. It is assumed that all keys are unique, otherwise the
behaviour is undefined. This CANNOT be a scalar value. If that is desired,
wrap it in a |
values |
Optional list. An iterable vector of values corresponding to
the keys. This CANNOT be a scalar value. If that is desired, wrap it in a
|
key_validator |
Optional function. A function that validates individual keys before insertion, returning TRUE if valid, FALSE otherwise. |
val_validator |
Optional function. A function that validates individual values before insertion, returning TRUE if valid, FALSE otherwise. |
Details
The average time complexity of all operations are linear with respect to the number of insertion/query inputs, in contrast to R lists which has quadratic time complexity for the same operations.
Value
An AddOnlyOrderedMap
instance
Construct an instance of an AxisNames
class
Description
This is a wrapper for a list()
, but the elements may only be singular
character()
, ConstantAstNode()
or other AstNode objects. (only 1 level
of nesting allowed, as its essentially another representation of a
OneSidedAstNode()
.
Note that when using c()
on an AxisNames
object, when the other object is
another AxisNames()
, the elements of that will simply be appended to the
first object. To nest (in the case of a GroupAstNode
), you must append
a list(AxisNames(...))
to the first object instead.
Usage
AxisNames(...)
Arguments
... |
a list of elements or arbitrary number of elements |
Value
an AxisNames
object, which is a list with a specific class
Singleton Backend Registry, managing all available backends.
Description
Contains global backend pool, ensuring backends are only loaded if actually required.
Methods
Public methods
Method get_backend()
detect the return relevant backend from the input
Usage
BackendRegistry$get_backend(tensor)
Arguments
tensor
any supported tensor-like class
Returns
A singleton instance of a EinopsBackend()
object
Method get_backend_from_type()
Get a backend instance for a specific tensor type. If the backend is not loaded, it will be instantiated.
Usage
BackendRegistry$get_backend_from_type(tensor_class)
Arguments
tensor_class
A string representing the tensor type.
Returns
An instance of the backend class for the specified tensor type.
Method register_backend()
Register a new backend singleton
Usage
BackendRegistry$register_backend( tensor_type, backend_class_thunk, dependencies = character(0), testing = FALSE, aliases = character(0) )
Arguments
tensor_type
a string with the tensor type the backend supports
backend_class_thunk
a
thunk()
'ed EinopsBackend subclass generatordependencies
a character vector of required package names
testing
logical flag indicating if this is a testing-only backend
aliases
a character vector of aliases for the tensor type
Returns
this object
Method unregister_backend()
Unregister a backend for a specific tensor type.
Usage
BackendRegistry$unregister_backend(tensor_type)
Arguments
tensor_type
a string with the tensor type
Returns
this object
Method add_backend_alias()
Add an alias for a backend type.
Usage
BackendRegistry$add_backend_alias(alias, tensor_type)
Arguments
alias
a string with the alias name
tensor_type
a string with the canonical tensor type
Returns
this object
Method clear_testing_backends()
Clear all testing-only backends.
Usage
BackendRegistry$clear_testing_backends()
Returns
this object
Method get_supported_types()
Get a list of all registered backend types.
Usage
BackendRegistry$get_supported_types()
Returns
A character vector of backend types.
Method get_dependencies()
given a tensor type, return the required packages
Usage
BackendRegistry$get_dependencies(tensor_type)
Arguments
tensor_type
a string with the tensor type
Returns
a character vector with required packages. Length 0 if no packages are required.
Method is_loadable()
Check if a tensor type is truly loadable, i.e., if it is registered and has no missing dependencies.
Usage
BackendRegistry$is_loadable(tensor_type)
Arguments
tensor_type
a string with the tensor type
Returns
TRUE if the tensor type is loadable, FALSE otherwise.
Create a ConstantAstNode
Description
Create a ConstantAstNode
Usage
ConstantAstNode(count, src = list())
Arguments
count |
Character string representing the constant value |
src |
List with start position |
Value
ConstantAstNode object
Create an EinopsAst root node
Description
Create an EinopsAst root node
Usage
EinopsAst(input_axes, output_axes, src)
Arguments
input_axes |
List of axis nodes for the input pattern, or
|
output_axes |
List of axis nodes for the input pattern, or
|
src |
List with start position covering the full pattern |
Value
EinopsAst
object
Base Backend Class for Einops Tensor Operations
Description
Abstract base class that defines the interface for tensor operations across different frameworks. All backend implementations must inherit from this class and implement the required methods.
Methods
Public methods
Method new()
Initialize the backend and check for required packages. It is assumed that the constructor will fully load and setup all dependencies and error otherwise.
Usage
EinopsBackend$new()
Returns
A new EinopsBackend instance.
Method print()
The print method for EinopsBackend instances
Usage
EinopsBackend$print(...)
Arguments
...
arguments passed to
pprint()
Returns
This object, invisibly
Method repr()
Get a string representation of this backend.
Usage
EinopsBackend$repr()
Returns
A character string describing the backend.
Method tensor_type()
Get the type of tensor this backend supports. This method should be overridden in subclasses to return the specific tensor type (e.g., "torch_tensor", "array").
Usage
EinopsBackend$tensor_type()
Returns
A string representing the tensor type.
Method preprocess()
Do any relevant preprocessing of a tensor before any operations are done on it. This should always be called before running any backend operations on a tensor
Usage
EinopsBackend$preprocess(x)
Arguments
x
The input raw tensor-like object
Returns
A preprocessed version of the input, may or may not have changed classes
Method create_tensor()
Create a tensor of the specified type with given values and dimensions.
Usage
EinopsBackend$create_tensor(values, dims, ...)
Arguments
values
A vector of values to initialize the tensor.
dims
A numeric vector specifying the dimensions of the tensor.
...
Additional arguments for specific backend implementations.
Returns
A tensor of the specified type.
Method as_array()
Convert a tensor to a standard base::array()
Usage
EinopsBackend$as_array(x)
Arguments
x
The input tensor/array.
Returns
A standard array representation of the tensor.
Method flatten()
Return a flattened version of the tensor. Note that the order of calling as_array and flatten does matter because different frameworks may store data differently.
Usage
EinopsBackend$flatten(x)
Arguments
x
The input tensor/array
Returns
A 1 dimensional tensor
Method arange()
Usage
EinopsBackend$arange(start, stop)
Arguments
start
integer, inclusive
stop
integer, inclusive
Returns
a sequence from start to stop
Method shape()
Get the shape of a tensor. Shape should return a tuple with integers or "shape symbols" (which will evaluate to actual size).
Usage
EinopsBackend$shape(x)
Arguments
x
The input tensor/array.
Returns
A numeric vector representing the tensor shape.
Method reshape()
Reshape a tensor to the specified dimensions.
Usage
EinopsBackend$reshape(x, shape)
Arguments
x
The input tensor/array.
shape
A numeric vector specifying the new shape.
Returns
The reshaped tensor/array.
Method transpose()
Transpose a tensor along the specified axes.
Usage
EinopsBackend$transpose(x, axes)
Arguments
x
The input tensor/array.
axes
A numeric vector specifying the new axis order.
Returns
The transposed tensor/array.
Method reduce()
Reduce a tensor along specified axes using the given operation.
Usage
EinopsBackend$reduce(x, operation, axes)
Arguments
x
The input tensor/array.
operation
A character string specifying the reduction operation (e.g., "sum", "mean", "max", "min", "prod", "all", "any"), OR a two argument function, with the first argument being the tensor to modify, and the second argument being an integer list of axes to perform the reduction over.
axes
A numeric vector specifying which axes to reduce over.
Returns
The reduced tensor/array.
Method stack_on_zeroth_dimension()
Stack multiple tensors along a new zeroth dimension.
Usage
EinopsBackend$stack_on_zeroth_dimension(tensors)
Arguments
tensors
A list of tensors/arrays to stack.
Returns
A tensor/array with the input tensors stacked along dimension 1.
Method add_axis()
Add a new axis to a tensor at the specified position.
Usage
EinopsBackend$add_axis(x, new_position)
Arguments
x
The input tensor/array.
new_position
The position (1-based) where to insert the new axis.
Returns
The tensor/array with a new axis added.
Method add_axes()
Add multiple axes to a tensor and tile along specified axes.
This function adds new axes to the input tensor at the specified positions and tiles the tensor along those axes according to the provided lengths.
Usage
EinopsBackend$add_axes(x, n_axes, pos2len)
Arguments
x
The input tensor/array.
n_axes
The total number of axes after addition.
pos2len
int->int
r2r::hashmap()
mapping positions to lengths.
Returns
The tensor/array with new axes added and tiled as specified.
Method tile()
Tile (repeat) a tensor along each axis according to the repeat counts. The repeats vector should have the same length as the tensor's shape.
Usage
EinopsBackend$tile(x, repeats)
Arguments
x
The input tensor/array.
repeats
A numeric vector specifying how many times to repeat along each axis. Must have same length as x.shape.
Returns
The tiled tensor/array.
Method concat()
Concatenate tensors along the specified axis. Assumes identical devices, dtypes and shapes except for the selected axis.
Usage
EinopsBackend$concat(tensors, axis)
Arguments
tensors
A list of tensors/arrays to concatenate.
axis
The axis along which to concatenate (1-based).
Returns
The concatenated tensor/array.
Method is_float_type()
Check if the tensor has a floating point data type.
Usage
EinopsBackend$is_float_type(x)
Arguments
x
The input tensor/array.
Returns
A logical value indicating if the tensor is of float type.
Method layers()
Get neural network layers specific to this backend.
Usage
EinopsBackend$layers()
Returns
Backend-specific layer implementations.
Method einsum()
Perform Einstein summation on tensors.
Usage
EinopsBackend$einsum(pattern, ...)
Arguments
pattern
A character string specifying the einsum pattern.
...
Additional tensors to operate on.
Returns
The result of the einsum operation.
Constructor for an Execution Plan (CookedRecipe
in the python sourcecode)
Description
Constructor for an Execution Plan (CookedRecipe
in the python sourcecode)
Usage
EinopsExecutionPlan(
init_shapes,
axes_reordering,
reduced_axes,
added_axes,
final_shapes,
n_axes_w_added
)
Arguments
init_shapes |
integer vector specifying initial tensor shapes for reshaping. Length 0 signifies nullness. |
axes_reordering |
integer vector specifying the order for transposing tensor axes. Length 0 signifies nullness. |
reduced_axes |
List of integers specifying which axes to reduce during operations. Length 0 signifies nullness. |
added_axes |
|
final_shapes |
list of integers specifying final tensor shapes for reshaping. Length 0 signifies nullness. |
n_axes_w_added |
Integer specifying the total number of axes after adding new axes. |
Value
An object of class EinopsExecutionPlan
, which is a list containing
the execution plan for transforming tensors according to the specified
recipe.
EinopsTokenSequence constructor
Description
Helper to build a token sequence (list of tokens)
Usage
EinopsTokenSequence(...)
Arguments
... |
tokens or EinopsTokenSequences to include |
Value
list of tokens
Create an EllipsisAstNode
Description
Create an EllipsisAstNode
Usage
EllipsisAstNode(src)
Arguments
src |
List with start position |
Value
EllipsisAstNode object
Create a GroupAstNode
Description
Create a GroupAstNode
Usage
GroupAstNode(children, src = list())
Arguments
children |
List of axis nodes contained in this group, potentially empty |
src |
List with start position |
Value
GroupAstNode object
Create a NamedAxisAstNode
Description
Create a NamedAxisAstNode
Usage
NamedAxisAstNode(name, src = list())
Arguments
name |
Character string, the name of the axis |
src |
List with start position |
Value
NamedAxisAstNode object
Create a OneSidedAstNode (wrapper for input/output axes lists)
Description
Create a OneSidedAstNode (wrapper for input/output axes lists)
Usage
OneSidedAstNode(...)
Arguments
... |
Axis nodes (or a single list of axis nodes) If this is already a OneSidedAstNode, it is returned as is. |
Value
OneSidedAstNode object
TransformRecipe S3 constructor
Description
Recipe describes actual computation pathway. Can be applied to a tensor or variable.
Usage
TransformRecipe(
elementary_axes_lengths,
axis_name2elementary_axis,
input_composition_known_unknown,
axes_permutation,
first_reduced_axis,
added_axes,
output_composite_axes
)
Arguments
elementary_axes_lengths |
Integer vector. List of sizes for elementary axes as they appear in the input (left) expression. This is what (after computing unknown parts) will be a shape after first transposition. This does not include any ellipsis dimensions. |
axis_name2elementary_axis |
|
input_composition_known_unknown |
List of list(known, unknown). known and unknown are integer vectors containing axis positions. These unknown and unknown integer vectors represent an unordered set and are always sorted to help with testing. ascending order for deterministic output. |
axes_permutation |
Integer vector. Permutation applied to elementary axes, if ellipsis is absent. |
first_reduced_axis |
Integer of length 1. First position of reduced axes. Permutation puts reduced axes in the end, we only need to know the first position. |
added_axes |
|
output_composite_axes |
List of integer vectors. Ids of axes as they appear in result. Again pointers to elementary_axes_lengths, only used to infer result dimensions. |
Value
An object of class 'TransformRecipe'.
Create an UnderscoreAstNode
Description
Create an UnderscoreAstNode
Usage
UnderscoreAstNode(src = list())
Arguments
src |
List with start position |
Value
UnderscoreAstNode object
Vector Merging
Description
Add elements to a vector.
Usage
append(x, values, after = length(x), ...)
Arguments
x |
the vector the values are to be appended to. |
values |
to be included in the modified vector. |
after |
a subscript, after which the values are to be appended. |
... |
Additional arguments passed to or from other methods. |
Value
A vector containing the values in x
with the elements of
values
appended after the specified element of x
.
References
Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New S Language. Wadsworth & Brooks/Cole.
Examples
append(1:5, 0:1, after = 3)
Apply a TransformRecipe to a Tensor
Description
This function applies a TransformRecipe to a tensor, performing rearrangement and reduction as specified by the recipe.
TODO docs for which parts of the compilation pipeline this is.
Usage
apply_recipe(backend, recipe, tensor, reduction_type, axes_lengths)
Arguments
backend |
The |
recipe |
A |
tensor |
A tensor to be transformed |
reduction_type |
A character of length 1 that specifies the type of reduction to apply. |
axes_lengths |
TODO check - I think its just an integer vector? |
Value
A tensor that has been transformed according to the recipe, with the same type (if possible) as the input tensor.
Convert an AstNode into an AxisNames()
object
Description
Convert an AstNode into an AxisNames()
object
Usage
as_axis_names(ast, ...)
Arguments
ast |
the AstNode input |
... |
other args |
Value
an AxisNames()
object of the axes in order
Convert an object to a list of iterables (lists)
Description
This function converts an object into a list of iterables, where each iterable is a list of elements. The function is generic and can be extended for different classes.
Usage
as_iterables(x, ...)
Arguments
x |
the input object to be converted |
... |
additional arguments (not used) |
Value
a list of iterables, where each iterable is a list of elements
AxisNames
This method converts an AxisNames
object into a list of iterables.
Each element in the AxisNames
is processed to extract its name or
constant value. If the element is a ConstantAstNode
with a count of
1, it is converted to an empty list. Otherwise, it is wrapped in
a list. If the element is a NamedAxisAstNode
, its name is extracted.
Regular AxisNames that are nested will be unclassed
Reconstruct all actual parameters using shape.
Description
This implements _reconstruct_from_shape_uncached
from the python
implementation of einops. In the future, a cached version may be
implemented.
Usage
create_execution_plan(recipe, shape, axes_dims)
Arguments
recipe |
a populated |
shape |
A vector of integers representing the shape of the tensor. |
axes_dims |
A named list of axes names to their dimensions/lengths. May also be an empty list. |
Value
An EinopsExecutionPlan
object that contains the execution plan for
transforming tensors according to the specified recipe and shape.
Perform Einstein-style tensor operations
Description
A unified interface for rearranging, reducing, and repeating tensor
dimensions using Einstein notation-inspired expressions. This was directly
adapted from the python einop
package: https://github.com/cgarciae/einop
einop()
auto detects the operation type based on the provided expression:
-
rearrange()
when all input dimensions are present in output -
reduce()
when some input dimensions are missing from output -
einops.repeat()
when output contains dimensions not in input
Note that there are ongoing debates about the use of this function purely
from the perspective of code readability and maintainability:
https://github.com/arogozhnikov/einops/issues/84. Generally, some argue
that the descriptive names of rearrange
, reduce
, and repeat
encourage good practices, while others think that semantically einop()
actually makes it clearer what the operation
is doing, as opposed to mandating the use of these commonly used function
names across many packages.
Usage
einop(
x,
expr,
reduction = NULL,
...,
.row_major = getOption("einops_row_major", FALSE)
)
Arguments
x |
tensor: array, matrix, or list of arrays of the same shape and type |
expr |
string: reduction pattern |
reduction |
A string specifying the reduction operation (e.g., "mean", "sum", "max"). Required for reduce operations, ignored for rearrange and repeat operations. |
... |
either corresponding axes lengths or a single list of them. |
.row_major |
|
Value
A tensor with dimensions transformed according to the expression
Examples
if (requireNamespace("abind", quietly = TRUE)) {
# load a 3d tensor representing an rgb image
x <- get(data("einops_image"))[1, , , ]
# Rearrange dimensions
einop(x, "h w c -> c h w")
# Reduce dimensions
einop(x, "h w c -> h w", "mean")
# Repeat dimensions
einop(x[, , 1], "h w -> h w c", c = 3)
}
Allows reordering elements and repeating them in arbitrary combinations.
Description
This operation includes functionality of repeat, tile, and broadcast functions.
Usage
einops.repeat(x, expr, ..., .row_major = getOption("einops_row_major", FALSE))
`repeat`(x, expr, ..., .row_major = getOption("einops_row_major", FALSE))
Arguments
x |
tensor: array, matrix, or list of arrays of the same shape and type |
expr |
string: reduction pattern |
... |
either corresponding axes lengths or a single list of them. |
.row_major |
|
Details
When composing axes, C-order enumeration is used (consecutive elements have different last axis). Find more examples in the vignettes.
Value
tensor of the same type as input, with dimensions according to output pattern
Why can't the function be called as repeat()
?
repeat
is a reserved keyword in R that acts the same as
while(TRUE)
, and has no way of being overridden. Hence,
this function can only be called as einops.repeat()
or
using backticks as `repeat`()
.
Examples
if (requireNamespace("abind", quietly = TRUE)) {
set.seed(42)
# a grayscale image (of shape height x width)
image <- array(rnorm(30 * 40), dim = c(30, 40))
# change it to RGB format by repeating in each channel
output <- einops.repeat(image, 'h w -> h w c', c = 3)
# Visualize the output
as_image_tensor(output)
# repeat image 2 times along height (vertical axis)
output <- einops.repeat(image, 'h w -> (r h) w', r = 2)
# repeat image 2 times along height and 3 times along width
output <- einops.repeat(image, 'h w -> (h2 h) (w3 w)', h2 = 2, w3 = 3)
# convert each pixel to a small square 2x2, i.e. upsample an image by 2x
output <- einops.repeat(image, 'h w -> (h h2) (w w2)', h2 = 2, w2 = 2)
# 'pixelate' an image first by downsampling by 2x, then upsampling
downsampled <- reduce(image, '(h h2) (w w2) -> h w', 'mean', h2 = 2, w2 = 2)
output <- einops.repeat(downsampled, 'h w -> (h h2) (w w2)', h2 = 2, w2 = 2)
as_image_tensor(einops.repeat(output, 'h w -> h w 3'))
}
Example 4D Image Tensor for Einops
Description
An image_tensor()
object that is a super thin wrapper around a 4D
base::array()
, representing image data in the format "b h w c"
(batch, height, width, channels). The actual image data is 6 black letters
on differently colored backgrounds, spelling out the word "einops". When
printing this object in the terminal it will automatically plot the images.
To subset, use the [
operator, and when used with a single index, it
will return a single image tensor.
Usage
einops_image
Format
An image_tensor()
object with 6 images, each of size 96 x 96
pixels, with 3 color channels (RGB). The images are stored in a 4D array
with dimensions (6, 96, 96, 3).
Examples
data("einops_image")
for (i in seq_len(6)) print(einops_image[i, , , ])
Expand ellipses of an EinopsAst
Description
Helper for prepare_transformation_recipe()
.
This function expands each relevant ellipsis ast node in-place into a
sequence of NamedAxisAstNode
nodes, where each node will have
a name like "...1"
, "...2"
, etc. and an empty src
list.
Also does some further validation of the ellipses syntax using ndim
.
Usage
expand_ellipsis(einops_ast, ndim)
Arguments
einops_ast |
an EinopsAst |
ndim |
integer. Number of dimensions in the input tensor |
Value
an expanded EinopsAst with ellipses expanded
Find the arrow in a token sequence
Description
Find the arrow in a token sequence
Usage
find_top_level_arrow_index(tokens)
Arguments
tokens |
EinopsTokenSequence object |
Value
one-indexed Integer position of the arrow token
Main function to detect and return backend
Description
Main function to detect and return backend
Usage
get_backend(tensor)
Arguments
tensor |
any supported tensor-like object |
Value
An instance of a EinopsBackend()
class. Every returned object
is a singleton, so the same object will be returned for the same tensor type.
Given a OneSidedAstNode
object, get unique identifiers
Description
get an unordered list, representing a set of all unique identifiers on one side of the expression. Named nodes become the character representing its name, ConstantAstNode nodes are just themselves, aside from 1 which is ignored. GroupAstNode nodes are flattened, and EllipsisAstNode nodes are ignored.
Usage
get_identifiers(ast, ...)
Arguments
ast |
the Abstract Syntax Tree (AST) of the einops expression
positions to the |
... |
additional arguments (not used) |
Value
an AxisNames()
of unique identifiers
Get the ordered axis names from a OneSidedAstNode, removing all nesting.
Description
Get the ordered axis names from a OneSidedAstNode, removing all nesting.
Usage
get_ordered_axis_names(ast, ...)
Arguments
ast |
OneSidedAstNode object |
... |
additional arguments (not used) |
Value
a list()
of axis names
get flat list of all AstNodes in order, including children of GroupAstNodes.
Description
get flat list of all AstNodes in order, including children of GroupAstNodes.
Usage
get_ungrouped_nodes(ast, ...)
Arguments
ast |
An AstNode object |
Value
A flat list
of AstNodes
Image Tensor: A thin wrapper around 2-4D arrays
Description
The image_tensor
class provides a convenient way to work with image data
in tensor format. It extends the base array
class and provides methods
for conversion to/from various image formats, plotting, and printing.
An image_tensor
object represents image data in the format "h w c"
(height, width, channels) for single images, or "b h w c"
(batch, height, width, channels) for batches of images, which is a common
format for deep learning frameworks. It also can be a 2D array, in which
case it is treated as a black and white image and shown as such.
The main utility of wrapping image data in the image_tensor
class is that
printing of the object will automatically display the image as a plot,
as long as the imager
package is installed. Otherwise it will simply
print the dimension of the image.
Usage
as_image_tensor(x)
image_tensor(x)
Arguments
x |
An object to convert to or from |
Details
The image_tensor
class provides the following methods (and more):
-
as_image_tensor()
: Generic function to convert objects toimage_tensor
format. Takes in array-like objects of 2-4 dimensions. for 2 dimensional objects, it will convert them to 3D by repeating the data across 3 channels, essentially converting grayscale images to RGB. -
as_image_tensor.default()
: Default method that converts arrays toimage_tensor
-
as_image_tensor.cimg()
: Method to convertcimg
objects (from imager package) toimage_tensor
-
as.cimg.image_tensor()
: Method to convertimage_tensor
objects back tocimg
format -
[.image_tensor()
: Subset method forimage_tensor
objects -
plot.image_tensor()
: Plot method forimage_tensor
objects -
print.image_tensor()
: Print method forimage_tensor
objects
Value
-
as_image_tensor()
: An object of classimage_tensor
-
as.cimg()
: Acimg
object (from imager package) -
[.image_tensor()
: A subset of theimage_tensor
object. For 4D arrays with single index, returns a 3D slice without the batch dimension. -
plot()
: Invisibly returns the input object -
print()
: Invisibly returns the input object
Format
An image_tensor
object is an array with dimensions in "h w c" format for
single images, or "b h w c" format for batches of images:
-
h: height dimension (image height in pixels)
-
w: width dimension (image width in pixels)
-
c: channel dimension (RGB, only for 3D & 4D arrays)
-
b: batch dimension (number of images, only for 4D arrays)
Options
The following options control the default behavior of image_tensor
methods:
-
plot_image_tensor_axes
: Whether to show axes in plots (default: FALSE) -
print_image_tensor_as_plot
: Whether to print images as plots (default: TRUE)
Examples
# create from a matrix (grayscale)
img <- image_tensor(matrix(1:9, 3, 3))
print(img)
print(img[1:2, 1:2])
# create from a 3D array (RGB image)
img_rgb <- as_image_tensor(array(runif(27), dim = c(3, 3, 3)))
print(img_rgb)
Lexically analyze einops pattern into structured tokens
Description
Lexically analyze einops pattern into structured tokens
Usage
lex(pattern)
Arguments
pattern |
character string with einops pattern |
Value
list of token objects with type, value, start, end fields
Parse a sequence of axis tokens
Description
Parse a sequence of axis tokens
Usage
parse_axes_iter(tokens)
Arguments
tokens |
List of tokens representing one side of the pattern |
Value
List of AST nodes
Parse einops pattern into AST
Description
In the python implementation, they preprocess all 1's into () and then parse it into the equivalent of a GroupAstNode. Here, we won't do that
Usage
parse_einops_ast(tokens)
Arguments
tokens |
EinopsTokenSequence object from the lexer |
Value
EinopsAst object
Parse a one-sided einops pattern into OneSidedAstNode
Description
Parse a one-sided einops pattern into OneSidedAstNode
Usage
parse_onesided_ast(tokens)
Arguments
tokens |
EinopsTokenSequence object from the lexer (no arrow expected) |
Value
OneSidedAstNode object
Parse a tensor shape to dictionary mapping axes names to their lengths.
Description
Use underscore to skip the dimension in parsing.
Usage
parse_shape(x, expr, ...)
Arguments
x |
tensor of any supported framework |
expr |
character of length 1, space separated names for axes, underscore means skip axis |
... |
additional arguments passed to methods |
Value
named list, maps axes names to their lengths
Examples
if (requireNamespace("abind", quietly = TRUE)) {
# Use underscore to skip the dimension in parsing.
x <- array(0, dim = c(2, 3, 5, 7))
parse_shape(x, 'batch _ h w')
# `parse_shape` output can be used to specify axes_lengths for other
# operations:
y <- array(0, dim = 700)
shape_info <- parse_shape(x, 'b _ h w')
# rearrange(y, '(b c h w) -> b c h w', shape_info) would give shape
# (2, 10, 5, 7)
}
Pretty Print
Description
This is a convenience function that prints the repr()
of an object.
It is similar to python's pprint.pprint()
. Usually, to ensure that
an object is displayed in the terminal using its pprint format, just
define a print.that_object_class
method that calls pprint()
.
Usage
pprint(x, ...)
Arguments
x |
Object to pretty print |
... |
Additional arguments passed to |
Value
The input object, invisibly
Create the Transformation Recipe for an einops call
Description
This function does the following parts of the einops 'compilation' pipeline:
Lexing: tokenizing the input expression string
Parsing: converting the tokens into an Abstract Syntax Tree (AST)
Syntactic Analysis:
operation-based AST validation pass
Compile syntactic info for intermediate representation (IR).
IR generation: return the
TransformRecipe()
object.
Usage
prepare_transformation_recipe(
expr,
func,
axes_names,
ndim,
reverse_groups = FALSE
)
Arguments
expr |
The input einops expression string |
func |
The string/function indicating the reduction operation |
axes_names |
user defined axis names as a |
ndim |
count for the number of dimensions of the input tensor |
reverse_groups |
|
Value
a populated TransformRecipe()
object
Reader-friendly smart element reordering for multidimensional tensors.
Description
This operation includes functionality of transpose (axes permutation), reshape (view), squeeze, unsqueeze, stack, concatenate and other operations.
Usage
rearrange(x, expr, ..., .row_major = getOption("einops_row_major", FALSE))
einops.rearrange(
x,
expr,
...,
.row_major = getOption("einops_row_major", FALSE)
)
Arguments
x |
tensor: array, matrix, or list of arrays of the same shape and type |
expr |
string: reduction pattern |
... |
either corresponding axes lengths or a single list of them. |
.row_major |
|
Details
When composing axes, C-order enumeration is used (consecutive elements have different last axis). Find more examples in the vignettes.
Value
tensor of the same type as input, with dimensions according to output pattern
Examples
if (requireNamespace("abind", quietly = TRUE)) {
# suppose we have a set of 32 images in "h w c" format (height-width-channel)
images <- lapply(1:32, function(i) {
as_image_tensor(array(rnorm(30*40*3), dim = c(30, 40, 3)))
})
# stacked and reordered axes to "b c h w" format
y <- rearrange(images, 'b h w c -> b c h w')
# concatenate images along height (vertical axis), 960 = 32 * 30
y <- rearrange(images, 'b h w c -> (b h) w c')
# concatenated images along horizontal axis, 1280 = 32 * 40
y <- rearrange(images, 'b h w c -> h (b w) c')
# flattened each image into a vector, 3600 = 30 * 40 * 3
y <- rearrange(images, 'b h w c -> b (c h w)')
# split each image into 4 smaller quadrants, 128 = 32 * 2 * 2
y <- rearrange(
images, 'b (h1 h) (w1 w) c -> (b h1 w1) h w c', h1 = 2, w1 = 2
)
# space-to-depth operation
y <- rearrange(
images, 'b (h h1) (w w1) c -> b h w (c h1 w1)', h1 = 2, w1 = 2
)
}
Rearrangement and reduction in one step
Description
reduce()
combines rearrangement and reduction using
reader-friendly notation.
Usage
reduce(x, expr, func, ..., .row_major = getOption("einops_row_major", FALSE))
einops.reduce(
x,
expr,
func,
...,
.row_major = getOption("einops_row_major", FALSE)
)
Arguments
x |
tensor: array, matrix, or list of arrays of the same shape and type |
expr |
string: reduction pattern |
func |
string or function: one of available reductions ('min', 'max', 'sum', 'mean', 'prod', 'any', 'all'), or an R 2 argument function which takes in two arguments, with the first being the tensor, and the second being an integer array indicating the dimensions to reduce over. |
... |
either corresponding axes lengths or a single list of them. |
.row_major |
|
Value
tensor of the same type as input, with dimensions according to output pattern
Examples
if (requireNamespace("abind", quietly = TRUE)) {
set.seed(42)
# Suppose x is a 3D array: 100 x 32 x 64
x <- array(rnorm(100 * 32 * 64), dim = c(100, 32, 64))
# perform max-reduction on the first axis
# Axis t does not appear on RHS - thus we reduced over t
y <- reduce(x, 't b c -> b c', 'max')
# same as previous, but using verbose names for axes
y <- reduce(x, 'time batch channel -> batch channel', 'max')
# let's pretend now that x is a batch of images
# with 4 dims: batch=10height = 20width = 30channel = 40
x <- array(rnorm(10 * 20 * 30 * 40), dim = c(10, 20, 30, 40))
# 2d max-pooling with kernel size = 2 * 2 for image processing
y1 <- reduce(x, 'b c (h1 h2) (w1 w2) -> b c h1 w1', 'max', h2 = 2, w2 = 2)
as_image_tensor(y1)
# same as previous, using anonymous axes,
# note: only reduced axes can be anonymous
y1 <- reduce(x, 'b c (h1 2) (w1 2) -> b c h1 w1', 'max')
as_image_tensor(y1)
# adaptive 2d max-pooling to 3 * 4 grid,
# each element is max of 10x10 tile in the original tensor.
dim(reduce(x, 'b c (h1 h2) (w1 w2) -> b c h1 w1', 'max', h1 = 3, w1 = 4))
# (10, 20, 3, 4)
# Global average pooling
dim(reduce(x, 'b c h w -> b c', 'mean'))
# (10, 20)
}
Register a new backend for a tensor type
Description
Registers a backend implementation for a specific tensor type, along with any
required dependencies, testing flag, and optional aliases. This function
wraps the backend class in a thunk()
and registers it with the backend
registry.
Usage
register_backend(
tensor_type,
backend_class,
dependencies = character(0),
testing = FALSE,
aliases = character(0)
)
Arguments
tensor_type |
A string specifying the tensor type the backend supports. |
backend_class |
An R6Class generator for the backend (subclass of EinopsBackend). Note that this binding does not necessarily have to have a defined value at the time of calling this function. |
dependencies |
Optional character vector of required package names. |
testing |
If TRUE, indicates its only used for testing. |
aliases |
Optional character vector of aliases for the tensor type. |
Value
Invisibly returns the backend registry object.
Python-like Representation of Objects as Strings
Description
This is an R implementation of python's repr()
function.
All objects will have a default repr that uses its print method.
This is important because the pprint()
function will always
be able to give a repr-esque output of any object.
Usage
repr(x, indent = 0L, ...)
Arguments
x |
Object to represent |
indent |
Indentation level (number of spaces) |
... |
Additional arguments passed to methods |
Value
A character vector of class c("repr_output", "character"), each element is a line
Get the last n children of a GroupAstNode as a list of AstNodes.
Description
Get the last n children of a GroupAstNode as a list of AstNodes.
Usage
## S3 method for class 'GroupAstNode'
tail(x, n = 1, ...)
Simple thunk: wraps an input in a no-argument function
Description
Simple thunk: wraps an input in a no-argument function
Usage
thunk(input)
Arguments
input |
Any R object or expression |
Value
A thunk that returns the object when called with
class c("thunk", "function")
Syntactically Validate the reduction operation in the einops expression
Description
Syntactically Validate the reduction operation in the einops expression
Usage
validate_reduction_operation(einops_ast, operation)
Arguments
einops_ast |
the parsed Abstract Syntax Tree (AST) of the einops expression |
operation |
the reduction operation, either a string or a function |
Value
the input einops_ast (invisibly) if the validation passes