命名为 Tensors 操作员范围
请首先阅读命名张量,以了解命名张量。
本文档是_名称推断_的参考,HTH1 是一个定义张量命名方式的过程:
-
使用名称提供其他自动运行时正确性检查
-
将名称从输入张量传播到输出张量
以下是命名张量及其关联的名称推断规则支持的所有操作的列表。
如果此处未列出操作,但对您的用例有帮助,请搜索问题是否已提交,否则请提交一个问题。
警告
命名的张量 API 是实验性的,随时可能更改。
保留输入名称
所有逐点一元函数以及其他一些一元函数都遵循此规则。
-
检查姓名:无
-
传播名称:输入张量的名称会传播到输出。
>>> x = torch.randn(3, 3, names=('N', 'C'))
>>> x.abs().names
('N', 'C')
移除尺寸
所有缩小操作,例如 sum()
,都会通过缩小所需尺寸来删除尺寸。 select()
和 squeeze()
等其他操作会删除尺寸。
只要有人可以将整数维度索引传递给运算符,就可以传递维度名称。 包含维索引列表的函数也可以包含维名称列表。
-
检查名称:如果
dim
或dims
作为名称列表传入,请检查self
中是否存在这些名称。 -
传播名称:如果在输出张量中不存在
dim
或dims
指定的输入张量的尺寸,则这些尺寸的相应名称不会出现在output.names
中。
>>> x = torch.randn(1, 3, 3, 3, names=('N', 'C', 'H', 'W'))
>>> x.squeeze('N').names
('C', 'H', 'W')
>>> x = torch.randn(3, 3, 3, 3, names=('N', 'C', 'H', 'W'))
>>> x.sum(['N', 'C']).names
('H', 'W')
# Reduction ops with keepdim=True don't actually remove dimensions.
>>> x = torch.randn(3, 3, 3, 3, names=('N', 'C', 'H', 'W'))
>>> x.sum(['N', 'C'], keepdim=True).names
('N', 'C', 'H', 'W')
统一输入中的名称
所有二进制算术运算都遵循此规则。 广播操作仍然从右侧进行位置广播,以保持与未命名张量的兼容性。 要通过名称执行显式广播,请使用 Tensor.align_as()
。
-
检查名称:所有名称都必须从右侧位置匹配。 即,在
tensor + other
中,对于(-min(tensor.dim(), other.dim()) + 1, -1]
中的所有i
,match(tensor.names[i], other.names[i])
必须为 true。 -
检查名称:此外,所有命名的尺寸必须从右对齐。 在匹配期间,如果我们将命名尺寸
A
与未命名尺寸None
匹配,则A
不得出现在具有未命名尺寸的张量中。 -
传播名称:从两个张量的右边开始统一名称对,以产生输出名称。
例如,
# tensor: Tensor[ N, None]
# other: Tensor[None, C]
>>> tensor = torch.randn(3, 3, names=('N', None))
>>> other = torch.randn(3, 3, names=(None, 'C'))
>>> (tensor + other).names
('N', 'C')
检查姓名:
-
match(tensor.names[-1], other.names[-1])
是True
-
match(tensor.names[-2], tensor.names[-2])
是True
-
检查以确保
other
中不存在'N'
(不存在)。
最后,使用[unify('N', None), unify(None, 'C')] = ['N', 'C']
计算输出名称
更多示例:
# 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.
注意
在最后两个示例中,可以通过名称对齐张量,然后执行加法。 使用 Tensor.align_as()
按名称对齐张量,或使用 Tensor.align_to()
将张量对齐到自定义尺寸顺序。
排列尺寸
某些操作(例如 Tensor.t()
)会置换尺寸顺序。 维度名称附加到各个维度,因此也可以排列。
如果操作员输入位置索引dim
,它也可以采用尺寸名称作为dim
。
-
检查名称:如果将
dim
作为名称传递,请检查其是否在张量中存在。 -
传播名称:以与要排列的维相同的方式排列维名称。
>>> x = torch.randn(3, 3, names=('N', 'C'))
>>> x.transpose('N', 'C').names
('C', 'N')
收缩消失
矩阵乘法函数遵循此方法的某些变体。 让我们先通过 torch.mm()
,然后概括一下批矩阵乘法的规则。
对于torch.mm(tensor, other)
:
-
Check names: None
-
传播名称:结果名称为
(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')
本质上,矩阵乘法在二维上执行点积运算,使它们折叠。 当两个张量矩阵相乘时,收缩尺寸消失,并且不出现在输出张量中。
torch.mv()
, torch.dot()
的工作方式类似:名称推断不会检查输入名称,并且会删除点积所涉及的尺寸:
>>> x = torch.randn(3, 3, names=('N', 'D'))
>>> y = torch.randn(3, names=('something',))
>>> x.mv(y).names
('N',)
现在,让我们看一下torch.matmul(tensor, other)
。 假设tensor.dim() >= 2
和other.dim() >= 2
。
-
检查名称:检查输入的批次尺寸是否对齐并可以广播。 请参见统一输入的名称,以了解对齐输入的含义。
-
传播名称:结果名称是通过统一批次尺寸并删除合同规定的尺寸获得的:
unify(tensor.names[:-2], other.names[:-2]) + (tensor.names[-2], other.names[-1])
。
例子:
# 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')
最后,还有许多功能的融合add
版本。 即 addmm()
和 addmv()
。 这些被视为构成 mm()
的名称推断和 add()
的命名推断。
工厂功能
现在,工厂函数采用新的names
参数,该参数将名称与每个维度相关联。
>>> torch.zeros(2, 3, names=('N', 'C'))
tensor([[0., 0., 0.],
[0., 0., 0.]], names=('N', 'C'))
输出功能和就地变型
指定为out=
张量的张量具有以下行为:
-
如果没有命名维,则将从操作中计算出的名称传播到其中。
-
如果它具有任何命名维,则从该操作计算出的名称必须与现有名称完全相同。 否则,操作错误。
所有就地方法都会将输入修改为具有与根据名称推断计算出的名称相同的名称。 例如,
>>> x = torch.randn(3, 3)
>>> y = torch.randn(3, 3, names=('N', 'C'))
>>> x.names
(None, None)
>>> x += y
>>> x.names
('N', 'C')