3.8.1 其他張量存儲(chǔ)的視圖
我們可以通過提供相應(yīng)的索引來獲得張量中的第二個(gè)點(diǎn):
# In[21]:
points = torch.tensor([[4.0, 1.0], [5.0, 3.0], [2.0, 1.0]])
second_point = points[1]
second_point.storage_offset()
# Out[21]:
2
# In[22]:
second_point.size()
# Out[22]:
torch.Size([2])
結(jié)果張量在存儲(chǔ)中的偏移量為2(因?yàn)槲覀冃枰^第一個(gè)點(diǎn),該點(diǎn)有兩個(gè)項(xiàng)目),并且由于張量是一維的,因此size是包含一個(gè)元素的Size類的實(shí)例。 請(qǐng)務(wù)必注意,這與張量對(duì)象的shape屬性中包含的信息相同:
# In[23]:
second_point.shape
# Out[23]:
torch.Size([2])
步幅是一個(gè)元組,指示當(dāng)索引在每個(gè)維度上增加1時(shí)必須跳過的存儲(chǔ)中元素的數(shù)量。 例如,我們的點(diǎn)張量的步幅為(2,1):
# In[24]:
points.stride()
# Out[24]:
(2, 1)
在2D張量中訪問元素i,j導(dǎo)致訪問存儲(chǔ)器中的storage_offset + stride [0] * i + stride [1] * j元素。 偏移量通常為零; 如果此張量是為容納更大張量而創(chuàng)建的存儲(chǔ)的視圖,則偏移量可能為正值。
張量和存儲(chǔ)之間的這種間接性使某些操作變得不昂貴,例如轉(zhuǎn)置張量或提取子張量,因?yàn)樗鼈儾粫?huì)導(dǎo)致內(nèi)存重新分配。 相反,它們包括分配一個(gè)新的Tensor對(duì)象,該對(duì)象的大小,存儲(chǔ)偏移或跨度的值不同。
當(dāng)我們索引特定點(diǎn)并看到存儲(chǔ)偏移量增加時(shí),我們已經(jīng)提取了一個(gè)張量。 讓我們來看看尺寸和跨度如何變化:
# In[25]:
second_point = points[1]
second_point.size()
# Out[25]:
torch.Size([2])
# In[26]:
second_point.storage_offset()
# Out[26]:
2
# In[27]:
second_point.stride()
# Out[27]:
(1,)
底線是,正如我們所期望的那樣,次張量具有較小的維數(shù),同時(shí)仍索引與原始點(diǎn)張量相同的存儲(chǔ)。 這也意味著更改次張量將對(duì)原始張量產(chǎn)生副作用:
# In[28]:
points = torch.tensor([[4.0, 1.0], [5.0, 3.0], [2.0, 1.0]])
second_point = points[1]
second_point[0] = 10.0
points
# Out[28]:
tensor([[ 4., 1.],
[10., 3.],
[ 2., 1.]])
這可能并不總是理想的,因此我們最終可以將次張量克隆為新的張量:
# In[29]:
points = torch.tensor([[4.0, 1.0], [5.0, 3.0], [2.0, 1.0]])
second_point = points[1].clone()
second_point[0] = 10.0
points
# Out[29]:
tensor([[4., 1.],
[5., 3.],
[2., 1.]])