捷徑

torch.nested

簡介

警告

巢狀 Tensor 的 PyTorch API 處於原型階段,近期將會變更。

NestedTensor 允許使用者將 Tensor 清單封裝到單一、有效率的資料結構中。

對輸入 Tensor 的唯一限制是它們的維度必須相符。

這能夠實現更有效率的中繼資料表示,並能存取專為此目的建立的核心。

NestedTensor 的一個應用是表達各個領域中的序列資料。傳統方法是填充可變長度的序列,而 NestedTensor 允許使用者繞過填充。在巢狀 tensor 上呼叫操作的 API 與常規 torch.Tensor 的 API 沒有區別,這應該允許與現有模型無縫整合,主要區別在於 輸入的建構

由於這是一項原型功能,支援的操作仍然有限。但是,我們歡迎提出問題、功能請求和貢獻。有關貢獻的更多資訊,請參閱 此 Readme

建構

建構很簡單,只需將 Tensor 清單傳遞給 torch.nested.nested_tensor 建構函式即可。

>>> a, b = torch.arange(3), torch.arange(5) + 3
>>> a
tensor([0, 1, 2])
>>> b
tensor([3, 4, 5, 6, 7])
>>> nt = torch.nested.nested_tensor([a, b])
>>> nt
nested_tensor([
  tensor([0, 1, 2]),
    tensor([3, 4, 5, 6, 7])
    ])

資料類型、裝置以及是否需要梯度可以透過通常的關鍵字引數來選擇。

>>> nt = torch.nested.nested_tensor([a, b], dtype=torch.float32, device="cuda", requires_grad=True)
>>> nt
nested_tensor([
  tensor([0., 1., 2.], device='cuda:0', requires_grad=True),
  tensor([3., 4., 5., 6., 7.], device='cuda:0', requires_grad=True)
], device='cuda:0', requires_grad=True)

torch.as_tensor 類似,torch.nested.as_nested_tensor 可用於保留從傳遞給建構子的 tensors 的 autograd 歷史記錄。 更多資訊請參考 巢狀張量建構子與轉換函式 一節。

為了形成一個有效的 NestedTensor,所有傳遞的 Tensors 需要在維度上匹配,但其他屬性則不需要。

>>> a = torch.randn(3, 50, 70) # image 1
>>> b = torch.randn(3, 128, 64) # image 2
>>> nt = torch.nested.nested_tensor([a, b], dtype=torch.float32)
>>> nt.dim()
4

如果其中一個維度不匹配,建構子將會拋出錯誤。

>>> a = torch.randn(50, 128) # text 1
>>> b = torch.randn(3, 128, 64) # image 2
>>> nt = torch.nested.nested_tensor([a, b], dtype=torch.float32)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All Tensors given to nested_tensor must have the same dimension. Found dimension 3 for Tensor at index 1 and dimension 2 for Tensor at index 0.

請注意,傳遞的 Tensors 會被複製到連續的記憶體區塊中。產生的 NestedTensor 會分配新的記憶體來儲存它們,並且不會保留引用。

目前我們僅支援單層巢狀結構,即簡單的 tensors 平面列表。未來我們可以添加對多層巢狀結構的支援,例如完全由 tensors 列表組成的列表。 請注意,對於此擴充,重要的是在條目之間保持均勻的巢狀結構層級,以便產生的 NestedTensor 具有明確定義的維度。 如果您需要此功能,請隨時開啟一個功能請求,以便我們可以追蹤並據此進行規劃。

size

即使 NestedTensor 不支援 .size() (或 .shape),如果維度 i 是規則的,則它支援 .size(i)

>>> a = torch.randn(50, 128) # text 1
>>> b = torch.randn(32, 128) # text 2
>>> nt = torch.nested.nested_tensor([a, b], dtype=torch.float32)
>>> nt.size(0)
2
>>> nt.size(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Given dimension 1 is irregular and does not have a size.
>>> nt.size(2)
128

如果所有維度都是規則的,則 NestedTensor 在語義上應與常規的 torch.Tensor 無法區分。

>>> a = torch.randn(20, 128) # text 1
>>> nt = torch.nested.nested_tensor([a, a], dtype=torch.float32)
>>> nt.size(0)
2
>>> nt.size(1)
20
>>> nt.size(2)
128
>>> torch.stack(nt.unbind()).size()
torch.Size([2, 20, 128])
>>> torch.stack([a, a]).size()
torch.Size([2, 20, 128])
>>> torch.equal(torch.stack(nt.unbind()), torch.stack([a, a]))
True

未來我們可能會更容易檢測到這種情況並無縫轉換。

如果您需要此功能(或任何其他相關功能),請開啟一個功能請求。

unbind

unbind 允許您檢索組成分量的視圖。

>>> import torch
>>> a = torch.randn(2, 3)
>>> b = torch.randn(3, 4)
>>> nt = torch.nested.nested_tensor([a, b], dtype=torch.float32)
>>> nt
nested_tensor([
  tensor([[ 1.2286, -1.2343, -1.4842],
          [-0.7827,  0.6745,  0.0658]]),
  tensor([[-1.1247, -0.4078, -1.0633,  0.8083],
          [-0.2871, -0.2980,  0.5559,  1.9885],
          [ 0.4074,  2.4855,  0.0733,  0.8285]])
])
>>> nt.unbind()
(tensor([[ 1.2286, -1.2343, -1.4842],
        [-0.7827,  0.6745,  0.0658]]), tensor([[-1.1247, -0.4078, -1.0633,  0.8083],
        [-0.2871, -0.2980,  0.5559,  1.9885],
        [ 0.4074,  2.4855,  0.0733,  0.8285]]))
>>> nt.unbind()[0] is not a
True
>>> nt.unbind()[0].mul_(3)
tensor([[ 3.6858, -3.7030, -4.4525],
        [-2.3481,  2.0236,  0.1975]])
>>> nt
nested_tensor([
  tensor([[ 3.6858, -3.7030, -4.4525],
          [-2.3481,  2.0236,  0.1975]]),
  tensor([[-1.1247, -0.4078, -1.0633,  0.8083],
          [-0.2871, -0.2980,  0.5559,  1.9885],
          [ 0.4074,  2.4855,  0.0733,  0.8285]])
])

請注意,nt.unbind()[0] 不是副本,而是底層記憶體的切片,代表 NestedTensor 的第一個條目或組成分量。

巢狀張量建構子與轉換函式

以下函式與巢狀張量相關

torch.nested.nested_tensor(tensor_list, *, dtype=None, layout=None, device=None, requires_grad=False, pin_memory=False)[原始碼][原始碼]

tensor_list(一個 tensors 列表)建構一個沒有 autograd 歷史記錄的巢狀張量(也稱為“葉張量”,請參閱 Autograd 機制)。

參數
  • tensor_list (List[array_like]) – tensors 列表,或任何可以傳遞給 torch.tensor 的東西,

  • dimensionality. (其中列表中的每個元素 具有相同的) –

關鍵字參數
  • dtype (torch.dtype, optional) – 返回的巢狀張量所需的類型。預設值:如果為 None,則與列表中最左側 tensor 的 torch.dtype 相同。

  • layout (torch.layout, optional) – 返回的巢狀張量所需的 layout。 僅支援 strided 和 jagged layouts。預設值:如果為 None,則為 strided layout。

  • device (torch.device, optional) – 返回的巢狀張量所需的裝置。預設值:如果為 None,則與列表中最左側 tensor 的 torch.device 相同

  • requires_grad (bool, optional) – 如果 autograd 應記錄返回的巢狀張量上的操作。預設值:False

  • pin_memory (bool, optional) – 如果設定,返回的巢狀張量將分配在 pinned memory 中。僅適用於 CPU tensors。預設值:False

返回類型

Tensor

範例

>>> a = torch.arange(3, dtype=torch.float, requires_grad=True)
>>> b = torch.arange(5, dtype=torch.float, requires_grad=True)
>>> nt = torch.nested.nested_tensor([a, b], requires_grad=True)
>>> nt.is_leaf
True
torch.nested.as_nested_tensor(ts, dtype=None, device=None, layout=None)[原始碼][原始碼]

從 tensor 或 tensors 的列表/元組建構一個保留 autograd 歷史記錄的巢狀張量。

如果傳遞了巢狀張量,則將直接返回它,除非 device / dtype / layout 不同。請注意,轉換 device / dtype 將導致複製,而此函數目前不支援轉換 layout。

如果傳遞了非巢狀張量,則將其視為一致大小的組成分量批次。 如果傳遞的 device / dtype 與輸入的不同,或者如果輸入不連續,則會產生複製。 否則,將直接使用輸入的儲存空間。

如果提供了 tensor 列表,則在建構巢狀張量期間始終會複製列表中的 tensors。

參數

ts (Tensor or List[Tensor] or Tuple[Tensor]) – 要視為巢狀張量的 tensor OR 具有相同 ndim 的 tensors 列表/元組

關鍵字參數
  • dtype (torch.dtype, optional) – 返回的巢狀張量所需的類型。預設值:如果為 None,則與列表中最左側 tensor 的 torch.dtype 相同。

  • device (torch.device, optional) – 返回的巢狀張量所需的裝置。預設值:如果為 None,則與列表中最左側 tensor 的 torch.device 相同

  • layout (torch.layout, optional) – 返回的巢狀張量所需的 layout。 僅支援 strided 和 jagged layouts。預設值:如果為 None,則為 strided layout。

返回類型

Tensor

範例

>>> a = torch.arange(3, dtype=torch.float, requires_grad=True)
>>> b = torch.arange(5, dtype=torch.float, requires_grad=True)
>>> nt = torch.nested.as_nested_tensor([a, b])
>>> nt.is_leaf
False
>>> fake_grad = torch.nested.nested_tensor([torch.ones_like(a), torch.zeros_like(b)])
>>> nt.backward(fake_grad)
>>> a.grad
tensor([1., 1., 1.])
>>> b.grad
tensor([0., 0., 0., 0., 0.])
>>> c = torch.randn(3, 5, requires_grad=True)
>>> nt2 = torch.nested.as_nested_tensor(c)
torch.nested.to_padded_tensor(input, padding, output_size=None, out=None) Tensor

透過填補 input 巢狀張量,返回一個新的 (非巢狀) 張量。 前導條目將會以巢狀資料填滿,而尾隨條目將會被填補。

警告

to_padded_tensor() 總是複製底層資料,因為巢狀和非巢狀張量在記憶體佈局上有所不同。

參數

padding (float) – 尾隨條目的填補值。

關鍵字參數
  • output_size (Tuple[int]) – 輸出張量的大小。 如果給定,它必須夠大以包含所有巢狀資料;否則,將會透過沿著每個維度獲取每個巢狀子張量的最大大小來推斷。

  • out (Tensor, optional) – 輸出張量。

範例

>>> nt = torch.nested.nested_tensor([torch.randn((2, 5)), torch.randn((3, 4))])
nested_tensor([
  tensor([[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276],
          [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995]]),
  tensor([[-1.8546, -0.7194, -0.2918, -0.1846],
          [ 0.2773,  0.8793, -0.5183, -0.6447],
          [ 1.8009,  1.8468, -0.9832, -1.5272]])
])
>>> pt_infer = torch.nested.to_padded_tensor(nt, 0.0)
tensor([[[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276],
         [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000]],
        [[-1.8546, -0.7194, -0.2918, -0.1846,  0.0000],
         [ 0.2773,  0.8793, -0.5183, -0.6447,  0.0000],
         [ 1.8009,  1.8468, -0.9832, -1.5272,  0.0000]]])
>>> pt_large = torch.nested.to_padded_tensor(nt, 1.0, (2, 4, 6))
tensor([[[ 1.6862, -1.1282,  1.1031,  0.0464, -1.3276,  1.0000],
         [-1.9967, -1.0054,  1.8972,  0.9174, -1.4995,  1.0000],
         [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000],
         [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000]],
        [[-1.8546, -0.7194, -0.2918, -0.1846,  1.0000,  1.0000],
         [ 0.2773,  0.8793, -0.5183, -0.6447,  1.0000,  1.0000],
         [ 1.8009,  1.8468, -0.9832, -1.5272,  1.0000,  1.0000],
         [ 1.0000,  1.0000,  1.0000,  1.0000,  1.0000,  1.0000]]])
>>> pt_small = torch.nested.to_padded_tensor(nt, 2.0, (2, 2, 2))
RuntimeError: Value in output_size is less than NestedTensor padded size. Truncation is not supported.

支援的操作

在本節中,我們總結了目前 NestedTensor 上支援的操作以及它們的任何約束。

PyTorch 操作

約束

torch.matmul()

支援兩個 (>= 3d) 巢狀張量之間的矩陣乘法,其中最後兩個維度是矩陣維度,並且前導 (批次) 維度具有相同的大小 (即,目前不支援批次維度的廣播)。

torch.bmm()

支援兩個 3-d 巢狀張量的批次矩陣乘法。

torch.nn.Linear()

支援 3-d 巢狀輸入和一個密集的 2-d 權重矩陣。

torch.nn.functional.softmax()

支援沿著所有維度(除了 dim=0)的 softmax。

torch.nn.Dropout()

行為與在常規張量上相同。

torch.Tensor.masked_fill()

行為與在常規張量上相同。

torch.relu()

行為與在常規張量上相同。

torch.gelu()

行為與在常規張量上相同。

torch.silu()

行為與在常規張量上相同。

torch.abs()

行為與在常規張量上相同。

torch.sgn()

行為與在常規張量上相同。

torch.logical_not()

行為與在常規張量上相同。

torch.neg()

行為與在常規張量上相同。

torch.sub()

支援兩個巢狀張量的元素減法。

torch.add()

支援兩個巢狀張量的元素加法。 支援將標量加到巢狀張量。

torch.mul()

支援兩個巢狀張量的元素乘法。 支援將巢狀張量乘以標量。

torch.select()

支援沿著所有維度進行選擇。

torch.clone()

行為與在常規張量上相同。

torch.detach()

行為與在常規張量上相同。

torch.unbind()

僅支援沿著 dim=0 的 unbinding。

torch.reshape()

支援重新塑形,且 dim=0 的大小保持不變 (即,巢狀張量的數量無法更改)。 與常規張量不同,此處的大小 -1 意味著繼承現有的大小。 特別是,不規則維度的唯一有效大小是 -1。 尺寸推斷尚未實作,因此對於新維度,大小不能為 -1

torch.Tensor.reshape_as()

reshape 類似的約束。

torch.transpose()

支援除了 dim=0 之外的所有維度的轉置。

torch.Tensor.view()

新形狀的規則與 reshape 的規則類似。

torch.empty_like()

行為與常規張量的行為類似;返回一個新的空巢狀張量 (即,具有未初始化的值),並與輸入的巢狀結構相符。

torch.randn_like()

行為與常規張量的行為類似;返回一個新的巢狀張量,其值根據標準常態分佈隨機初始化,並與輸入的巢狀結構相符。

torch.zeros_like()

行為與常規張量的行為類似;返回一個新的巢狀張量,其所有值均為零,並與輸入的巢狀結構相符。

torch.nn.LayerNorm()

normalized_shape 引數被限制為不延伸到 NestedTensor 的不規則維度中。

文件

取得 PyTorch 的全面開發人員文件

檢視文件

教學

取得初學者和進階開發人員的深入教學

檢視教學

資源

尋找開發資源並取得問題解答

檢視資源