You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Wherever one can pass an integer dimension index to an operator, one can also pass
a dimension name. Functions that take lists of dimension indices can also take in a
list of dimension names.
Propagate names: If the dimensions of the input tensor specified by :attr:`dim`
or :attr:`dims` are not present in the output tensor, then the corresponding names
of those dimensions do not appear in output.names.
All binary arithmetic ops follow this rule. Operations that broadcast still
broadcast positionally from the right to preserve compatibility with unnamed
tensors. To perform explicit broadcasting by names, use :meth:`Tensor.align_as`.
Check names: All names must match positionally from the right. i.e., in
tensor + other, match(tensor.names[i], other.names[i]) must be true for all
i in (-min(tensor.dim(), other.dim()) + 1, -1].
Check names: Furthermore, all named dimensions must be aligned from the right.
During matching, if we match a named dimension A with an unnamed dimension
None, then A must not appear in the tensor with the unnamed dimension.
Propagate names: unify pairs of names from the right from both tensors to
produce output names.
Because we matched None in :attr:`tensor` with 'C',
check to make sure 'C' doesn't exist in :attr:`tensor` (it does not).
Check to make sure 'N' doesn't exists in :attr:`other` (it does not).
Finally, the output names are computed with
[unify('N', None), unify(None, 'C')] = ['N', 'C']
More examples:
# Dimensions don't match from the right:
# tensor: Tensor[N, C]
# other: Tensor[ N]
>>> tensor = torch.randn(3, 3, names=('N', 'C'))
>>> other = torch.randn(3, names=('N',))
>>> (tensor + other).names
RuntimeError: Error when attempting to broadcast dims ['N', 'C'] and dims
['N']: dim 'C' and dim 'N' are at the same position from the right but do
not match.
# Dimensions aren't aligned when matching tensor.names[-1] and other.names[-1]:
# tensor: Tensor[N, None]
# other: Tensor[ N]
>>> tensor = torch.randn(3, 3, names=('N', None))
>>> other = torch.randn(3, names=('N',))
>>> (tensor + other).names
RuntimeError: Misaligned dims when attempting to broadcast dims ['N'] and
dims ['N', None]: dim 'N' appears in a different position from the right
across both lists.
Note
In both of the last examples, it is possible to align the tensors by names
and then perform the addition. Use :meth:`Tensor.align_as` to align
tensors by name or :meth:`Tensor.align_to` to align tensors to a custom
dimension ordering.
Permutes dimensions
Some operations, like :meth:`Tensor.t()`, permute the order of dimensions. Dimension names
are attached to individual dimensions so they get permuted as well.
If the operator takes in positional index :attr:`dim`, it is also able to take a dimension
name as :attr:`dim`.
Check names: If :attr:`dim` is passed as a name, check that it exists in the tensor.
Propagate names: Permute dimension names in the same way as the dimensions that are
being permuted.
Matrix multiply functions follow some variant of this. Let's go through
:func:`torch.mm` first and then generalize the rule for batch matrix multiplication.
For torch.mm(tensor, other):
Check names: None
Propagate names: result names are (tensor.names[-2], other.names[-1]).
>>> x = torch.randn(3, 3, names=('N', 'D'))
>>> y = torch.randn(3, 3, names=('in', 'out'))
>>> x.mm(y).names
('N', 'out')
Inherently, a matrix multiplication performs a dot product over two dimensions,
collapsing them. When two tensors are matrix-multiplied, the contracted dimensions
disappear and do not show up in the output tensor.
:func:`torch.mv`, :func:`torch.dot` work in a similar way: name inference does not
check input names and removes the dimensions that are involved in the dot product:
>>> x = torch.randn(3, 3, names=('N', 'D'))
>>> y = torch.randn(3, names=('something',))
>>> x.mv(y).names
('N',)
Now, let's take a look at torch.matmul(tensor, other). Assume that tensor.dim() >= 2
and other.dim() >= 2.
Check names: Check that the batch dimensions of the inputs are aligned and broadcastable.
See :ref:`unifies_names_from_inputs-doc` for what it means for the inputs to be aligned.
Propagate names: result names are obtained by unifying the batch dimensions and removing
the contracted dimensions:
unify(tensor.names[:-2], other.names[:-2]) + (tensor.names[-2], other.names[-1]).
Examples:
# Batch matrix multiply of matrices Tensor['C', 'D'] and Tensor['E', 'F'].
# 'A', 'B' are batch dimensions.
>>> x = torch.randn(3, 3, 3, 3, names=('A', 'B', 'C', 'D'))
>>> y = torch.randn(3, 3, 3, names=('B', 'E', 'F'))
>>> torch.matmul(x, y).names
('A', 'B', 'C', 'F')
Finally, there are fused add versions of many matmul functions. i.e., :func:`addmm`
and :func:`addmv`. These are treated as composing name inference for i.e. :func:`mm` and
name inference for :func:`add`.
Factory functions
Factory functions now take a new :attr:`names` argument that associates a name
with each dimension.
A tensor specified as an out= tensor has the following behavior:
If it has no named dimensions, then the names computed from the operation
get propagated to it.
If it has any named dimensions, then the names computed from the operation
must be exactly equal to the existing names. Otherwise, the operation errors.
All in-place methods modify inputs to have names equal to the computed names
from name inference. For example:
>>> x = torch.randn(3, 3)
>>> y = torch.randn(3, 3, names=('N', 'C'))
>>> x.names
(None, None)
>>> x += y
>>> x.names
('N', 'C')