为什么索引张量会保留原始张量的步幅?

时间:2020-07-15 19:53:33

标签: python pytorch

我对步幅的理解是跳到轴的下一部分所需的步数。因此,如果跨度为(3,1),则需要3个步骤才能到达下一行,而又需要1个步骤才能到达下一列(假设第一个轴为行,第二个轴为列)。

但是,当我索引到火炬张量时,b[1:, 1:]的形状为(3,3),从第一行倾斜 第一列,然后查询其跨度,我得到(3,1)而不是(2,1)

为什么会这样?

import unittest
import torch
class TestChapter3(unittest.TestCase):
    def setUp(self):
        self.a = torch.tensor(list(range(9)))
        self.b = self.a.view(3,3)
        self.c = self.b[1:, 1:]

    def test_index_of_view(self):
        print(self.c)
        self.assertEqual(self.c.size(), torch.Size([2, 2]))
        self.assertEqual(self.c.storage_offset(), 4)
        self.assertEqual(self.c.stride(), (2, 1)) # self.c.stride() is actually (3,1)


if __name__ == "__main__":
    unittest.main()

1 个答案:

答案 0 :(得分:1)

self.c张量仍使用与self.aself.b相同的底层数据存储。它们都是同一存储上的不同视图。

self.c.storage_offset()告诉您self.c的视图从何处开始(传递第一整行和第二行的第一元素=总共4个元素),但数据仍作为一个存储在内存中长数组。

由于底层存储仍然相同,因此向下一行向下的内存地址仍然是3*sizeof(float)个字节或另外三个元素,这就是self.c.stride()[0]所说的。

在您的示例中,我们有:

self.a = (visible=[0, 1, 2, 3, 4, 5, 6, 7, 8], data=[0, 1, 2, 3, 4, 5, 6, 7, 8])
self.b = (visible=[
    [0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8]
], data=[0, 1, 2, 3, 4, 5, 6, 7, 8])
self.c = (visible=[

       [4, 5], 
       [7, 8]
], data=[4, 5, 6, 7, 8])

是的,最后一个数据数组中的6不是错误。最后一个数据数组只是self.aself.b所引用的同一内存的偏移视图。