原文: PyTorch 命名張量
命名張量旨在通過允許用戶將顯式名稱與張量維度相關聯(lián)來使張量更易于使用。 在大多數(shù)情況下,采用尺寸參數(shù)的操作將接受尺寸名稱,從而無需按位置跟蹤尺寸。 此外,命名張量使用名稱來自動檢查運行時是否正確使用了 API,從而提供了額外的安全性。 名稱也可以用于重新排列尺寸,例如,支持“按名稱廣播”而不是“按位置廣播”。
警告
命名的張量 API 是實驗性的,隨時可能更改。
現(xiàn)在,工廠函數(shù)采用新的names
參數(shù),該參數(shù)將名稱與每個維度相關聯(lián)。
>>> torch.zeros(2, 3, names=('N', 'C'))
tensor([[0., 0., 0.],
[0., 0., 0.]], names=('N', 'C'))
命名尺寸(與常規(guī) Tensor 尺寸一樣)已訂購。 tensor.names[i]
是tensor
的尺寸i
的名稱。
以下工廠函數(shù)支持命名張量:
torch.empty()
torch.rand()
torch.randn()
torch.ones()
torch.tensor()
torch.zeros()
有關張量名稱的限制,請參見 names
。
使用 names
訪問張量的尺寸名稱,并使用 rename()
重命名命名尺寸。
>>> imgs = torch.randn(1, 2, 2, 3 , names=('N', 'C', 'H', 'W'))
>>> imgs.names
('N', 'C', 'H', 'W')
>>> renamed_imgs = imgs.rename(H='height', W='width')
>>> renamed_imgs.names
('N', 'C', 'height', 'width)
命名張量可以與未命名張量共存; 命名張量是 torch.Tensor
的實例。 未命名的張量具有None
命名的尺寸。 命名張量不需要命名所有尺寸。
>>> imgs = torch.randn(1, 2, 2, 3 , names=(None, 'C', 'H', 'W'))
>>> imgs.names
(None, 'C', 'H', 'W')
命名張量使用名稱來自動檢查在運行時是否正確調(diào)用了 API。 這在稱為名稱推斷的過程中發(fā)生。 更正式地說,名稱推斷包括以下兩個步驟:
所有支持命名張量的操作都會傳播名稱。
>>> x = torch.randn(3, 3, names=('N', 'C'))
>>> x.abs().names
('N', 'C')
如果兩個名稱相等(字符串相等)或至少一個名稱為None
則匹配。 從本質(zhì)上講,沒有一個是特殊的“通配符”名稱。
unify(A, B)
確定名稱A
和B
中的哪個傳播到輸出。 如果兩個名稱匹配,它將返回更多特定的。 如果名稱不匹配,則錯誤。
注意
在實踐中,使用命名張量時,應避免使用未命名的維,因為它們的處理可能很復雜。 建議使用 refine_names()
將所有未命名的尺寸提升為已命名的尺寸。
讓我們看看在添加兩個不廣播的一維張量的情況下,如何在名稱推斷中使用match
和unify
。
x = torch.randn(3, names=('X',))
y = torch.randn(3)
z = torch.randn(3, names=('Z',))
檢查名稱:檢查兩個張量的名稱是否與相匹配。
對于以下示例:
>>> # x + y # match('X', None) is True
>>> # x + z # match('X', 'Z') is False
>>> # x + x # match('X', 'X') is True
>>> x + z
Error when attempting to broadcast dims ['X'] and dims ['Z']: dim 'X' and dim 'Z' are at the same position from the right but do not match.
傳播名稱:統(tǒng)一的名稱以選擇要傳播的名稱。 在x + y
的情況下,unify('X', None) = 'X'
因為'X'
比None
更特異性。
>>> (x + y).names
('X',)
>>> (x + x).names
('X',)
有關名稱推斷規(guī)則的完整列表,請參見名為張量運算符的覆蓋范圍。 以下是兩個可能有用的常見操作:
使用 align_as()
或 align_to()
按名稱將張量尺寸對齊到指定順序。 這對于執(zhí)行“按名稱廣播”很有用。
## This function is agnostic to the dimension ordering of `input`,
## as long as it has a `C` dimension somewhere.
def scale_channels(input, scale):
scale = scale.refine_names('C')
return input * scale.align_as(input)
>>> num_channels = 3
>>> scale = torch.randn(num_channels, names=('C',))
>>> imgs = torch.rand(3, 3, 3, num_channels, names=('N', 'H', 'W', 'C'))
>>> more_imgs = torch.rand(3, num_channels, 3, 3, names=('N', 'C', 'H', 'W'))
>>> videos = torch.randn(3, num_channels, 3, 3, 3, names=('N', 'C', 'H', 'W', 'D')
>>> scale_channels(imgs, scale)
>>> scale_channels(more_imgs, scale)
>>> scale_channels(videos, scale)
使用 align_to()
排列大量尺寸,而無需提及 permute()
要求的所有尺寸。
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2)
>>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F')
## Move the F (dim 5) and E dimension (dim 4) to the front while keeping
## the rest in the same order
>>> tensor.permute(5, 4, 0, 1, 2, 3)
>>> named_tensor.align_to('F', 'E', ...) # Use '...' instead in Python 2
使用 flatten()
和 unflatten()
分別展平和展平尺寸。 這些方法比 view()
和 reshape()
更冗長,但對于閱讀代碼的人來說,語義更有意義。
>>> imgs = torch.randn(32, 3, 128, 128)
>>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W')
>>> flat_imgs = imgs.view(32, -1)
>>> named_flat_imgs = named_imgs.flatten(['C', 'H', 'W'], 'features')
>>> named_flat_imgs.names
('N', 'features')
>>> unflattened_imgs = imgs.view(32, 3, 128, 128)
>>> unflattened_named_imgs = named_flat_imgs.unflatten(
'features', [('C', 3), ('H', 128), ('W', 128)])
Autograd 當前以有限的方式支持命名張量:autograd 忽略所有張量上的名稱。 梯度計算仍然是正確的,但是我們失去了名稱賦予我們的安全性。
>>> x = torch.randn(3, names=('D',))
>>> weight = torch.randn(3, names=('D',), requires_grad=True)
>>> loss = (x - weight).abs()
>>> grad_loss = torch.randn(3)
>>> loss.backward(grad_loss)
>>> weight.grad # Unnamed for now. Will be named in the future
tensor([-1.8107, -0.6357, 0.0783])
>>> weight.grad.zero_()
>>> grad_loss = grad_loss.refine_names('C')
>>> loss = (x - weight).abs()
## Ideally we'd check that the names of loss and grad_loss match but we don't yet.
>>> loss.backward(grad_loss)
>>> weight.grad
tensor([-1.8107, -0.6357, 0.0783])
有關受支持的torch和張量操作的完整列表,請參見命名為 Tensors 的操作員范圍。 我們尚不支持以下鏈接未涵蓋的內(nèi)容:
對于torch.nn.functional
運算符,我們支持以下內(nèi)容:
torch.nn.functional.relu()
torch.nn.functional.softmax()
torch.nn.functional.log_softmax()
torch.nn.functional.tanh()
torch.nn.functional.sigmoid()
torch.nn.functional.dropout()
支持 Autograd,請參見 Autograd support 。 由于當前未命名漸變,因此優(yōu)化程序可能有效,但未經(jīng)測試。
當前不支持 NN 模塊。 調(diào)用具有命名張量輸入的模塊時,可能導致以下情況:
我們也不支持以下子系統(tǒng),盡管有些子系統(tǒng)可能是開箱即用的:
torch.load()
, torch.save()
)如果其中任何一個可以幫助您解決用例,請搜索是否已提交問題,否則,請?zhí)峤灰粋€。
在本節(jié)中,請找到特定于特定張量的 API 的文檔。 有關如何通過其他 PyTorch 運算符傳播名稱的全面參考,請參見名為 Tensors 運算符的覆蓋范圍。
class torch.Tensor
names?
存儲每個張量維度的名稱。
names[idx]
對應于張量尺寸idx
的名稱。 如果名稱為維,則名稱為字符串;如果名稱為未命名,則名稱為None
。
維度名稱可以包含字符或下劃線。 此外,維度名稱必須是有效的 Python 變量名稱(即,不能以下劃線開頭)。
張量可能沒有兩個具有相同名稱的命名尺寸。
Warning
The named tensor API is experimental and subject to change.
rename(*names, **rename_map)?
重命名self
的尺寸名稱。
主要有兩種用法:
self.rename(**rename_map)
返回張量的視圖,該視圖具有按映射rename_map
中的指定重命名的暗角。
self.rename(*names)
返回張量視圖,并使用 names
重命名所有尺寸。 使用self.rename(None)
在張量上放置名稱。
不能同時指定位置 args names
和關鍵字 args rename_map
。
例子:
>>> imgs = torch.rand(2, 3, 5, 7, names=('N', 'C', 'H', 'W'))
>>> renamed_imgs = imgs.rename(N='batch', C='channels')
>>> renamed_imgs.names
('batch', 'channels', 'H', 'W')
>>> renamed_imgs = imgs.rename(None)
>>> renamed_imgs.names
(None,)
>>> renamed_imgs = imgs.rename('batch', 'channel', 'height', 'width')
>>> renamed_imgs.names
('batch', 'channel', 'height', 'width')
Warning
The named tensor API is experimental and subject to change.
rename_(*names, **rename_map)?
rename()
的就地版本。
refine_names(*names)?
根據(jù) names
細化self
的尺寸名稱。
細化是重命名的特殊情況,可以“提升”未命名的尺寸。 可以將None
暗號細化為任何名稱; 命名的 dim 只能精簡為具有相同的名稱。
由于命名張量可以與未命名張量共存,因此優(yōu)化名稱提供了一種編寫可處理命名張量和未命名張量的命名張量感知代碼的好方法。
names
最多可以包含一個省略號(...
)。 橢圓形貪婪地展開。 使用來自self.names
的相應索引的名稱,將其就地擴展為將 names
填充為與self.dim()
相同的長度。
Python 2 不支持 Ellipsis,但是可以改用字符串文字('...'
)。
參數(shù)
名稱(str 的可迭代)–輸出張量的所需名稱。 最多可以包含一個省略號。
Examples:
>>> imgs = torch.randn(32, 3, 128, 128)
>>> named_imgs = imgs.refine_names('N', 'C', 'H', 'W')
>>> named_imgs.names
('N', 'C', 'H', 'W')
>>> tensor = torch.randn(2, 3, 5, 7, 11)
>>> tensor = tensor.refine_names('A', ..., 'B', 'C')
>>> tensor.names
('A', None, None, 'B', 'C')
Warning
The named tensor API is experimental and subject to change.
align_as(other) → Tensor?
排列self
張量的尺寸以匹配other
張量中的尺寸順序,為任何新名稱添加大小為 1 的變暗。
此操作對于按名稱進行顯式廣播很有用(請參見示例)。
為了使用此方法,必須命名self
的所有暗色。 生成的張量是原始張量的視圖。
self
的所有尺寸名稱必須存在于other.names
中。 other
可能包含不在self.names
中的命名尺寸; 對于這些新名稱中的每一個,輸出張量都有一個一維的尺寸。
要將張量對齊到特定順序,請使用 align_to()
。
Examples:
## Example 1: Applying a mask
>>> mask = torch.randint(2, [127, 128], dtype=torch.bool).refine_names('W', 'H')
>>> imgs = torch.randn(32, 128, 127, 3, names=('N', 'H', 'W', 'C'))
>>> imgs.masked_fill_(mask.align_as(imgs), 0)
## Example 2: Applying a per-channel-scale
def scale_channels(input, scale):
scale = scale.refine_names('C')
return input * scale.align_as(input)
>>> num_channels = 3
>>> scale = torch.randn(num_channels, names=('C',))
>>> imgs = torch.rand(32, 128, 128, num_channels, names=('N', 'H', 'W', 'C'))
>>> more_imgs = torch.rand(32, num_channels, 128, 128, names=('N', 'C', 'H', 'W'))
>>> videos = torch.randn(3, num_channels, 128, 128, 128, names=('N', 'C', 'H', 'W', 'D'))
## scale_channels is agnostic to the dimension order of the input
>>> scale_channels(imgs, scale)
>>> scale_channels(more_imgs, scale)
>>> scale_channels(videos, scale)
Warning
The named tensor API is experimental and subject to change.
align_to(*names)?
排列self
張量的尺寸以匹配 names
中指定的順序,為任何新名稱添加大小為 1 的變暗。
All of the dims of self
must be named in order to use this method. The resulting tensor is a view on the original tensor.
self
的所有尺寸名稱必須出現(xiàn)在 names
中。 names
可能包含self.names
中沒有的其他名稱; 對于這些新名稱中的每一個,輸出張量都有一個一維的尺寸。
names
最多可以包含一個省略號(...
)。 省略號按在self
中出現(xiàn)的順序擴展為等于 names
中未提及的self
的所有尺寸名稱。
Python 2 does not support Ellipsis but one may use a string literal instead ('...'
).
Parameters
名稱(可迭代的)–輸出張量的所需尺寸順序。 最多可以包含一個省略號,擴展為self
的所有未提及的暗號。
Examples:
>>> tensor = torch.randn(2, 2, 2, 2, 2, 2)
>>> named_tensor = tensor.refine_names('A', 'B', 'C', 'D', 'E', 'F')
## Move the F and E dims to the front while keeping the rest in order
>>> named_tensor.align_to('F', 'E', ...)
Warning
The named tensor API is experimental and subject to change.
unflatten(dim, namedshape)?
以namedshape
指定的形狀將命名尺寸 dim
展平。
Parameters
命名為形狀 –(可復制(name, size)
元組)。
Examples:
>>> flat_imgs = torch.rand(32, 3 * 128 * 128, names=('N', 'features'))
>>> imgs = flat_imgs.unflatten('features', (('C', 3), ('H', 128), ('W', 128)))
>>> imgs.names, images.shape
(('N', 'C', 'H', 'W'), torch.Size([32, 3, 128, 128]))
Warning
The named tensor API is experimental and subject to change.
flatten(dims, out_dim) → Tensor
將dims
展平為名稱為out_dim
的單個維度。
所有<cite>變暗</cite>必須在self
張量中按順序連續(xù),但在內(nèi)存中不必是連續(xù)的。
Examples:
>>> imgs = torch.randn(32, 3, 128, 128, names=('N', 'C', 'H', 'W'))
>>> flat_imgs = imgs.flatten(['C', 'H', 'W'], 'features')
>>> flat_imgs.names, flat_imgs.shape
(('N', 'features'), torch.Size([32, 49152]))
Warning
The named tensor API is experimental and subject to change.
更多建議: