3、索引和切片
1、基本索引
索引查找方式单一
1 a = tf.ones([1,5,5,3]) 2 print(a[0][0]) 3 print(a[0][0][0]) 4 print(a[0][0][0][2])
输出:
tf.Tensor( [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.]], shape=(5, 3), dtype=float32)
tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)
2、numpy型索引
将所有的索引写在一个列表中,而不是写多个中括号,且可读性也比较强
1 a = tf.random.normal([4,28,28,3]) 2 print(a[1].shape) #(28, 28, 3) 打印第1张图片的所有行,所有列,所有通道 3 print(a[1,2].shape) # (28, 3) 打印第1张照片的第2行的所有列,所有通道 4 print(a[1,2,3].shape) #(3,) 打印第1张照片的第2行的第2列的所有通道 5 print(a[1,2,3,2].shape) # () 打印第1张照片的第2行的第2列的第2通道
3、start:end,指定开始和结束,不包含end
类似python中切片
1 a = tf.range(10) 2 print(a) # tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32) 3 print(a[-1:]) # tf.Tensor([9], shape=(1,), dtype=int32) 4 print(a[:2]) # tf.Tensor([0 1], shape=(2,), dtype=int32)
4、start:end:step
①一个分号 :,相当于步长为1进行采样,只能连续取
1 #一个分号 2 a = tf.random.normal([4,28,28,3]) 3 print(a.shape) #(4, 28, 28, 3) 4 print(a[0].shape) #取第0张图片 (28, 28, 3) 5 print(a[0,:,:,:].shape) #取第0张图片的所有行所有列所有通道 (28, 28, 3) 6 print(a[:,0,:,:].shape) #取所有图片的第0行的所有列的所有通道 (4, 28, 3)
②两个分号 ::可以实现跳着取(可以通过逗号,进行维数划分)
1 #两个分号 2 a = tf.random.normal([4,28,28,3]) 3 print(a.shape) #(4, 28, 28, 3) 4 print(a[0:2,:,:,:]) #第0,1张图片的所有行所有列所有通道 5 print(a[:,0:28:2,0:28:2,:]) #所有图片的第0,2,4....行,第0,2,4...列的所有通道
③逆序采样,a[end : start : step]
1 #逆序采样 2 a = tf.range(10) 3 print(a) #tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32) 4 print(a[::-1]) # 从开头到结尾逆序 tf.Tensor([9 8 7 6 5 4 3 2 1 0], shape=(10,), dtype=int32) 5 print(a[::-2]) # tf.Tensor([9 7 5 3 1], shape=(5,), dtype=int32) 6 print(a[2::-2]) # tf.Tensor([2 0], shape=(2,), dtype=int32) 说明这种方式是从第end(即2)位开始到开头
③省略号采样,只要在逻辑上能推断出省略号代表的冒号的数量,就是可行的
1 #省略号采样 2 a = tf.random.normal([2,4,28,28,3]) 3 print(a[0].shape) #(4, 28, 28, 3) 4 print(a[0,:,:,:,:].shape) #(4, 28, 28, 3) 5 print(a[0,...].shape) #(4, 28, 28, 3) 6 print(a[...,0].shape) #(2, 4, 28, 28)
5、选择性索引
前面的切片是基于start:end:step模式实现的,它在整体上来说,是基于步长的有规律性的一种采样方式,而选择性采样具有随意性,由程序员自己确定,如在tensor[4,28,28,3]上,要想取行维度上的样,只需要给出确定的索引号即可,如[2,3,9,22,6,27,15]这些行
(1)tf.gather
假设有数据data:[classes,students,subjects] ,[4,35,8]即4个班级,每个班级35个人,每个人8门课成绩
1 #收集tf.gather 2 a = tf.random.normal([4,25,8]) 3 print(a.shape) #(4, 25, 8) 4 5 b = tf.gather(a, axis=0, indices=[2,3]) #收集第2,3个班级所有学生所有科目成绩 6 print(b.shape) #(2, 25, 8)
(2)tf.gather_nd
假设不是希望取3名学生8门功课的成绩(只有一个维度),而是希望取第二个学生的第0门课的成绩,第三个学生的第四们课的成绩等
1 #收集tf.gather_nd 2 a = tf.random.normal([4,35,8]) 3 print(a.shape) #(4, 25, 8) 4 5 b = tf.gather_nd(a,[0]) #第0个班级的所有学生的所有成绩 6 print(b.shape) #(35, 8) 7 8 b = tf.gather_nd(a,[0,1]) #第0个班级的第1个学生的所有成绩 9 print(b.shape) # (8,) 10 11 b = tf.gather_nd(a,[0,1,2]) #第0个班级的第1个学生的第2门成绩 12 print(b.shape) # ()成绩标量 13 14 #多个查询,将内层括号看作是一个整体用来进行索引,然后外层括号组成相应的数组 15 b = tf.gather_nd(a,[[0,0],[1,1],[2,2]]).shape #第0个班级第0个学生的所有成绩,第1个班级第1个学生的所有成绩,第2个班级第个学生的所有成绩,二维数组 16 print(b) # (3, 8) 17 18 b = tf.gather_nd(a,[[0,0,0],[1,1,1],[2,2,2]]).shape #返回三个成绩,组成长度为3的向量[成绩a,成绩b,成绩c].shape为(3) 19 print(b) # (3,) 20 21 b = tf.gather_nd(a,[[[0,0,0],[1,1,1],[2,2,2]]]).shape #返回三个成绩,[[成绩a,成绩b,成绩c]],shape为(1,3) 22 print(b) # (1,3)
(3)tf.boolean_mask
1 # tf.boolean_mask
2 a = tf.convert_to_tensor(np.ones([4,28,28,3]))
3 print(a.shape) #(4, 28, 28, 3)
4
5 #mask的个数要与相应的axis中维数相同
6 a = tf.boolean_mask(a, mask=[True,True,False,False]) #axis默认是0,取第0维的属性,即张数,取第0,1张图片
7 print(a.shape) #(2, 28, 28, 3)
8
9 a = tf.boolean_mask(a, mask=[True,True,False],axis=3) #取第三维的通道,即第一个和第二个通道是真Ture,则取样
10 print(a.shape) #(2, 28, 28, 2)