PyTorch 命名張量

2020-09-15 13:38 更新

原文: PyTorch 命名張量

命名張量旨在通過允許用戶將顯式名稱與張量維度相關聯(lián)來使張量更易于使用。 在大多數(shù)情況下,采用尺寸參數(shù)的操作將接受尺寸名稱,從而無需按位置跟蹤尺寸。 此外,命名張量使用名稱來自動檢查運行時是否正確使用了 API,從而提供了額外的安全性。 名稱也可以用于重新排列尺寸,例如,支持“按名稱廣播”而不是“按位置廣播”。

警告

命名的張量 API 是實驗性的,隨時可能更改。

創(chuàng)建命名張量

現(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ā)生。 更正式地說,名稱推斷包括以下兩個步驟:

  • 檢查名稱:操作員可以在運行時執(zhí)行自動檢查,以檢查某些尺寸名稱是否必須匹配。
  • 傳播名稱:名稱推斷會將名稱傳播到輸出張量。

所有支持命名張量的操作都會傳播名稱。

>>> x = torch.randn(3, 3, names=('N', 'C'))
>>> x.abs().names
('N', 'C')

匹配語義

如果兩個名稱相等(字符串相等)或至少一個名稱為None則匹配。 從本質(zhì)上講,沒有一個是特殊的“通配符”名稱。

unify(A, B)確定名稱AB中的哪個傳播到輸出。 如果兩個名稱匹配,它將返回更多特定的。 如果名稱不匹配,則錯誤。

注意

在實踐中,使用命名張量時,應避免使用未命名的維,因為它們的處理可能很復雜。 建議使用 refine_names() 將所有未命名的尺寸提升為已命名的尺寸。

基本名稱推斷規(guī)則

讓我們看看在添加兩個不廣播的一維張量的情況下,如何在名稱推斷中使用matchunify。

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ī)則的完整列表,請參見名為張量運算符的覆蓋范圍。 以下是兩個可能有用的常見操作:

  • 二進制算術(shù)運算:統(tǒng)一輸入的名稱
  • 矩陣乘法操作:縮小暗淡

按名稱明確對齊

使用 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 當前以有限的方式支持命名張量: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])

當前支持的操作和子系統(tǒng)

經(jīng)營者

有關受支持的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()

子系統(tǒng)

支持 Autograd,請參見 Autograd support 。 由于當前未命名漸變,因此優(yōu)化程序可能有效,但未經(jīng)測試。

當前不支持 NN 模塊。 調(diào)用具有命名張量輸入的模塊時,可能導致以下情況:

  • NN 模塊參數(shù)未命名,因此輸出可以部分命名。
  • NN 模塊正向傳遞的代碼不支持命名張量,并且會適當?shù)爻鲥e。

我們也不支持以下子系統(tǒng),盡管有些子系統(tǒng)可能是開箱即用的:

  • 分布
  • 序列化 (torch.load() , torch.save())
  • 并行處理
  • JIT
  • Distributed
  • ONNX

如果其中任何一個可以幫助您解決用例,請搜索是否已提交問題,否則,請?zhí)峤灰粋€。

命名張量 API 參考

在本節(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.

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號