具名張量運算子涵蓋範圍¶
請先閱讀具名張量以瞭解具名張量的簡介。
本文件是關於*名稱推斷*的參考,這是一個定義如何使用具名張量的過程
- 使用名稱來提供額外的自動執行時正確性檢查 
- 將名稱從輸入張量傳播到輸出張量 
以下列出所有支援具名張量的運算及其相關聯的名稱推斷規則。
如果您沒有看到這裡列出的運算,但它有助於您的使用案例,請搜尋是否已提交問題,如果沒有,請提交一個。
警告
具名張量 API 仍為實驗性質,可能會有所變動。
| API | 名稱推斷規則 | 
|---|---|
| 請參閱文件 | |
| 請參閱文件 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 
 | 無 | 
| 
 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 請參閱文件 | |
| 無 | |
| 無 | |
| 
 | 無 | 
| 無 | |
| 
 | 請參閱文件 | 
| 
 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 
 | 無 | 
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 
 | |
| 無 | |
| 將遮罩對齊輸入,然後 unifies_names_from_input_tensors | |
| 請參閱文件 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 
 | 無 | 
| 無 | |
| 無 | |
| 請參閱文件 | |
| 無 | |
| 無 | |
| 請參閱文件 | |
| 請參閱文件 | |
| 無 | |
| 無 | |
| 僅允許不改變形狀的調整大小 | |
| 僅允許不改變形狀的調整大小 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 無 | |
| 請參閱文件 | |
| 無 | |
| 無 | |
保留輸入名稱¶
所有逐點一元函數以及其他一些一元函數都遵循此規則。
- 檢查名稱:無 
- 傳播名稱:輸入張量的名稱會傳播到輸出。 
>>> 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中,- match(tensor.names[i], other.names[i])對於- (-min(tensor.dim(), other.dim()) + 1, -1]中的所有- 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])為- True
- match(tensor.names[-2], tensor.names[-2])為- True
- 因為我們將 - 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 版本的 matmul 函數。例如,addmm() 和 addmv()。這些被視為組成名稱推斷,例如 mm() 和 add() 的名稱推斷。
工廠函數¶
工廠函數現在採用新的 names 參數,它會將名稱與每個維度關聯。
>>> torch.zeros(2, 3, names=('N', 'C'))
tensor([[0., 0., 0.],
        [0., 0., 0.]], names=('N', 'C'))
out 函數和原地變體¶
指定為 out= 張量的張量具有以下行為
- 如果它沒有已命名的維度,則從運算計算的名稱會傳播到它。 
- 如果有任何已命名的維度,則從操作計算出來的名稱必須與現有名稱完全相同。否則,操作會出錯。 
所有就地方法都會修改輸入,使其名稱等於從名稱推斷計算出來的名稱。例如
>>> x = torch.randn(3, 3)
>>> y = torch.randn(3, 3, names=('N', 'C'))
>>> x.names
(None, None)
>>> x += y
>>> x.names
('N', 'C')