網(wǎng)站背景怎么設(shè)置seo教學(xué)視頻教程
這篇簡明扼要的文章是關(guān)于PyTorch中的tensor.view()方法的介紹與應(yīng)用,與reshape()方法的區(qū)別,同時給出示例進(jìn)行詳細(xì)解釋。
Tensor基礎(chǔ)
Tensor(張量)的視圖是一個新的Tensor,它與原始Tensor共享相同的底層數(shù)據(jù),但具有不同的形狀或大小。view()方法用于在不改變其數(shù)據(jù)的情況下將張量重塑為新的形狀。它返回原始張量的新視圖。這意味著修改新的張量會影響原來的張量,反之亦然。
語法:
Tensor.view(*shape) -> Tensor
- self:想要重塑的輸入Tensor。
- *shape:一個
torch.Size
對象或指定輸出張量所需形狀的整數(shù)序列。還可以使用-1從其他維度推斷一個維度的大小。
然而,Tensor.view()僅適用于連續(xù)張量,即存儲在連續(xù)內(nèi)存中的張量。如果輸入張量不是連續(xù)的,則需要在調(diào)用tensor .view()之前調(diào)用tensor.consecuous()。你可以通過調(diào)用tensor.is_consecuous()來檢查張量是否是連續(xù)的。
代碼示例
下面演示如何在實踐中使用tensor.view()方法:
>>> import torch
>>> torch.manual_seed(2023)
>>> # Create a tensor with the shape of 4x4
>>> x = torch.randn(4, 4)
>>> print(x)
tensor([[ 0.4305, -0.3499, 0.4749, 0.9041],[-0.7021, 1.5963, 0.4228, -0.6940],[ 0.9672, 1.5569, -2.3860, 0.6994],[-1.0325, -2.6043, 0.9337, -0.1050]])
>>> y = x.view(16)
>>> print(y)
tensor([ 0.4305, -0.3499, 0.4749, 0.9041, -0.7021, 1.5963, 0.4228, -0.6940,0.9672, 1.5569, -2.3860, 0.6994, -1.0325, -2.6043, 0.9337, -0.1050])
>>> z=x.view(2,8)
>>> print(z)
tensor([[ 0.4305, -0.3499, 0.4749, 0.9041, -0.7021, 1.5963, 0.4228, -0.6940],[ 0.9672, 1.5569, -2.3860, 0.6994, -1.0325, -2.6043, 0.9337, -0.1050]])
>>> w=x.view(-1,2)
>>> print(w)
tensor([[ 0.4305, -0.3499],[ 0.4749, 0.9041],[-0.7021, 1.5963],[ 0.4228, -0.6940],[ 0.9672, 1.5569],[-2.3860, 0.6994],[-1.0325, -2.6043],[ 0.9337, -0.1050]])
>>>
你可以看到y(tǒng)和x有相同的數(shù)據(jù),但形狀不同,是16x1。Z和x有相同的數(shù)據(jù),但形狀不同,是2x8。W和x有相同的數(shù)據(jù),但形狀不同,是8x2。w的最后一個維度是從其他維度和x中的元素數(shù)量推斷出來的。
Torch.view()和torch.reshape()的區(qū)別
torch.reshape()函數(shù)和tensor .view()方法之間的區(qū)別在于torch.reshape()可以返回原始張量的視圖或副本,具體取決于新形狀是否與原始形狀和步幅兼容,而tensor .view()總是返回原始張量的視圖,但僅適用于連續(xù)張量。
當(dāng)你想重塑一個張量而不擔(dān)心它的連續(xù)性或復(fù)制行為時,你應(yīng)該使用torch.reshape(),當(dāng)你想重塑一個連續(xù)張量并確保它與原始張量共享相同的數(shù)據(jù)時,你應(yīng)該使用tensor. view()。
示例對比
場景 1:數(shù)據(jù)連續(xù)時,兩者行為一致
import torch# 創(chuàng)建一個連續(xù)存儲的張量 (2x3)
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("原始形狀:", x.shape) # (2, 3)
print("是否連續(xù):", x.is_contiguous()) # True# 使用 view 改變形狀 (3x2)
y = x.view(3, 2)
print("view 結(jié)果:", y) # [[1, 2], [3, 4], [5, 6]]# 使用 reshape 改變形狀 (3x2)
z = x.reshape(3, 2)
print("reshape 結(jié)果:", z) # [[1, 2], [3, 4], [5, 6]]
結(jié)果一致,且未復(fù)制數(shù)據(jù)(is_contiguous()
返回 True
)。
場景 2:數(shù)據(jù)不連續(xù)時,view
失敗,reshape
成功
# 轉(zhuǎn)置后數(shù)據(jù)不再連續(xù)(原按行存儲,轉(zhuǎn)置后按列邏輯訪問)
x_transposed = x.t()
print("轉(zhuǎn)置后形狀:", x_transposed.shape) # (3, 2)
print("是否連續(xù):", x_transposed.is_contiguous()) # False# 嘗試用 view 改變形狀 → 報錯!
try:y = x_transposed.view(2, 3)
except RuntimeError as e:print("view 錯誤:", str(e)) # "invalid argument: cannot view a non-contiguous tensor as ..."# 使用 reshape 成功(自動復(fù)制數(shù)據(jù))
z = x_transposed.reshape(2, 3)
print("reshape 結(jié)果:", z) # [[1, 4], [2, 5], [3, 6]]
print("是否連續(xù):", z.is_contiguous()) # True
場景 3:reshape
的靈活性(使用 -1
)
# 不確定某一維度的大小時,僅用 reshape
x_2d = torch.randn(4, 6) # 形狀 (4, 6)
# 將最后一維壓縮為總和,剩余維度自動推斷
y = x_2d.reshape(-1, 3) # 結(jié)果形狀: (8, 3)
print(y.shape) # torch.Size([8, 3])
因此,我們應(yīng)優(yōu)先用 view
:當(dāng)數(shù)據(jù)連續(xù)且形狀明確時,view
更高效(零復(fù)制);優(yōu)先用 reshape
:需處理非連續(xù)數(shù)據(jù)、動態(tài)推斷維度或不確定形狀時。