命名张量算子覆盖范围¶
请先阅读 命名张量 以获取命名张量介绍。
本文档是 名称推断 的参考资料,这个过程定义了命名张量如何
使用名称来提供额外的自动运行时正确性检查
从输入张量传播名称到输出张量
下面列出了命名张量支持的所有操作及其相关的名称推断规则。
如果您在此处未找到某个操作,但它对您的用例有帮助,请搜索是否已有相关问题被提交,如果没有,提交一个问题。
警告
命名张量 API 是实验性的,未来可能会发生变化。
API |
名称推断规则 |
---|---|
参见文档 |
|
参见文档 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
|
无 |
|
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
参见文档 |
|
无 |
|
无 |
|
|
无 |
无 |
|
|
参见文档 |
|
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
|
无 |
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
|
|
无 |
|
将掩码与输入对齐,然后合并来自输入张量的名称 |
|
参见文档 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
|
无 |
无 |
|
无 |
|
参见文档 |
|
无 |
|
无 |
|
参见文档 |
|
参见文档 |
|
无 |
|
无 |
|
只允许不改变形状的 resize 操作 |
|
只允许不改变形状的 resize 操作 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
无 |
|
参见文档 |
|
无 |
|
无 |
|
保留输入名称¶
所有逐点一元函数以及其他一些一元函数都遵循此规则。
检查名称:无
传播名称:将输入张量的名称传播到输出张量。
>>> 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])
必须为真。检查名称:此外,所有已命名维度必须从右侧对齐。在匹配过程中,如果我们将命名维度
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])
isTrue
match(tensor.names[-2], tensor.names[-2])
isTrue
因为我们将
tensor
中的None
与'C'
匹配,请检查确保'C'
不存在于tensor
中(它确实不存在)。检查确保
'N'
不存在于other
中(它确实不存在)。
最后,输出名称通过 [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)
检查名称:无
传播名称:结果名称为
(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 函数和原地(in-place)变体¶
指定为 out=
张量的行为如下:
如果它没有命名维度,则从操作中计算出的名称会传播给它。
如果它有任何命名维度,则从操作中计算出的名称必须与现有名称完全一致。否则,操作会报错。
所有原地(in-place)方法都会修改输入,使其名称等于名称推断计算出的名称。例如
>>> x = torch.randn(3, 3)
>>> y = torch.randn(3, 3, names=('N', 'C'))
>>> x.names
(None, None)
>>> x += y
>>> x.names
('N', 'C')