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)
posted on 2019-11-20 09:40  Luaser  阅读(779)  评论(0编辑  收藏  举报