3.8.1 其他张量存储的视图
我们可以通过提供相应的索引来获得张量中的第二个点:
# 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])
结果张量在存储中的偏移量为2(因为我们需要跳过第一个点,该点有两个项目),并且由于张量是一维的,因此size是包含一个元素的Size类的实例。 请务必注意,这与张量对象的shape属性中包含的信息相同:
# In[23]:
second_point.shape
# Out[23]:
torch.Size([2])
步幅是一个元组,指示当索引在每个维度上增加1时必须跳过的存储中元素的数量。 例如,我们的点张量的步幅为(2,1):
# In[24]:
points.stride()
# Out[24]:
(2, 1)
在2D张量中访问元素i,j导致访问存储器中的storage_offset + stride [0] * i + stride [1] * j元素。 偏移量通常为零; 如果此张量是为容纳更大张量而创建的存储的视图,则偏移量可能为正值。
张量和存储之间的这种间接性使某些操作变得不昂贵,例如转置张量或提取子张量,因为它们不会导致内存重新分配。 相反,它们包括分配一个新的Tensor对象,该对象的大小,存储偏移或跨度的值不同。
当我们索引特定点并看到存储偏移量增加时,我们已经提取了一个张量。 让我们来看看尺寸和跨度如何变化:
# 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,)
底线是,正如我们所期望的那样,次张量具有较小的维数,同时仍索引与原始点张量相同的存储。 这也意味着更改次张量将对原始张量产生副作用:
# 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.]])
网友评论