一维、二维、三维张量的符号索引
张量作为有序的序列,也是具备数值索引的功能,并且基本的索引方法和Python原生的列表、numpy中的数组基本一致。也有不同的,其是pytorch中还定义了一种采用函数来进行索引的方式。
而作为PyTorch中基本数据类型,张量即具备了列表、数组的基本功能,同时还充当着向量、矩阵、甚至是数据框等重要数据结构,因此PyTorch中也设置了非常完备的张量合并与变换的操作。
张量的符号索引
张量也是有序序列,我们可以根据每个元素在系统内的顺序“编号”,来找出特定的元素,也就是索引。
(1)一维张量索引
一维张量的索引过程和Python原生对象类型的索引一致,基本格式遵循[start: end: step],索引的基本要点回顾如下。
t1 = torch.arange(1, 11)
#结果为:tensor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
t1[0]
#结果为:tensor(1)------零维张量
注:张量索引出来的结果还是零维张量, 而不是单独的数。要转化成单独的数,需要使用item()方法
t1[1: 8] # 索引其中2-9号元素,并且左包含右不包含
#结果为:tensor([2, 3, 4, 5, 6, 7, 8])
t1[1: 8: 2] # 索引其中2-9号元素,左包含右不包含,且隔两个数取一个
#结果为:tensor([2, 4, 6, 8])
t1[1: : 2] # 从第二个元素开始索引,一直到结尾,并且每隔两个数取一个
tensor([ 2, 4, 6, 8, 10])
t1[: 8: 2] # 从第一个元素开始索引到第9个元素(不包含),并且每隔两个数取一个
tensor([1, 3, 5, 7])
注意:在张量的索引中,step位必须大于0,不然会报错
(2)二维张量索引
二维张量的索引逻辑和一维张量的索引逻辑基本相同,二维张量可以视为两个一维张量组合而成,而在实际的索引过程中,需要用逗号进行分隔,分别表示对哪个一维张量进行索引、以及具体的一维张量的索引,如果没有逗号则表示索引对应的整行或整列(逗号在前)。
t2 = torch.arange(1, 10).reshape(3, 3)
#结果为:tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
t2[0, 1] # 表示索引第一行、第二个(第二列的)元素
#结果为:tensor(2)------零维张量
t2[0, ::2] # 表示索引第一行、每隔两个元素取一个
#结果为:tensor([1, 3])
t2[0, [0, 2]] # 索引结果同上
结果为:tensor([1, 3])
t2[::2, ::2] # 表示每隔两行取一行、并且每一行中每隔两个元素取一个
#结果为:tensor([[1, 3],
[7, 9]])
t2[[0, 2], 1] # 索引第一行、第三行、第二列的元素
#结果为:tensor([2, 8])
理解:对二维张量来说,基本可以视为是对矩阵的索引,并且行、列的索引遵照相同的索引规范,并用逗号进行分隔。如果没有逗号则表示索引对应的整行或整列(逗号在前)
(3)三维张量索引
在二维张量索引的基础上,三维张量拥有三个索引的维度。我们将三维张量视作矩阵组成的序列,则在实际索引过程中拥有三个维度,分别是索引矩阵、索引矩阵的行、索引矩阵的列。
t3 = torch.arange(1, 28).reshape(3, 3, 3)
#结果为:tensor([[[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]],
[[10, 11, 12],
[13, 14, 15],
[16, 17, 18]],
[[19, 20, 21],
[22, 23, 24],
[25, 26, 27]]])
t3[1, 1, 1] # 索引第二个矩阵中,第二行、第二个元素
#结果为:tensor(14)------零维张量
t3[1, ::2, ::2] # 索引第二个矩阵,行和列都是每隔两个取一个
#结果为:tensor([[10, 12],
[16, 18]])
t3[:: 2, :: 2, :: 2] # 每隔两个取一个矩阵,对于每个矩阵来说,行和列都是每隔两个取一个
#结果为:tensor([[[ 1, 3],
[ 7, 9]],
[[19, 21],
[25, 27]]])
理解:更为本质的角度去理解高维张量的索引,其实就是围绕张量的“形状”进行索引
t3.shape
#结果为:torch.Size([3, 3, 3])
t3[1, 1, 1] # 与shape一一对应
#结果为:tensor(14)
以上是本人的浅显见解,还请大家多多指教。