【TensorFlow2.0】(3) 索引与切片操作

各位同学好,今天我和大家分享一下TensorFlow2.0中索引与切片。内容有:

(1) 给定每一维度的索引来获取数据;(2) 切片索引;(3) 省略号应用;(4) tf.gather() 方法;(5) tf.gather_nd() 方法;(6) 布尔索引选数据

那我们开始吧。


1. 给定每一维度的索引获取数据

1.1 变量[ ][ ] 方法

首先定义一个全为1的四维tensor,如:tf.ones([2,3,3,2])。由于整个数据庞大,不利于观察,我们使用.shape来观察取出数据的情况。

#创建一个全为1的四维tensor,默认float32
a = tf.ones([2,3,3,2])
# 返回3,3,2的tensor  
a[0].shape  
#取出3行2列的矩阵tensor
a[0][0].shape  
#返回长度为2列表tensor
a[0][0][0].shape 
#值为标量1,是0维tensor.
a[0][0][0][1].shape  

我们可以把这个四维tensor,[2,3,3,2],理解为,有2个班级,每个班级有3名同学,每名同学有3门科目,每门科目有2份作业。

a[0] 可以理解为,第0个班级的所有数据,它包含3名同学,每名有3门科目,每科目有2份作业。因此,a[0] 是一个三维tensor形状为[3,3,2]

a[0][0] 可以理解为,第0个班级的第0个同学的所有数据,它包含3门科目,每科目有2份作业。因此,a[0][0] 是一个二维tensor形状为[3,2]

同理其他两个


1.2 变量[ , ] 方法

我们创建一个四维随即正态分布的tensor,形状shape为[4,5,6,7],我们同样可以用上一个理解方法来看这个四维tensor。4个班级,每班5个人,每人6门课,每门课7份作业。

#创建一个四维随机正态分布tensor
a = tf.random.normal([4,5,6,7])  
# 
a[1].shape  # 返回[5,6,7]
# 
a[1,2].shape  # 返回[6,7]
#
a[1,2,3].shape  # 返回[7]
# 
a[1,2,3,4]  # 返回值

a[1,2] 代表第1个班级中,第2名学生的所有信息,包含6门功课,每门课7份作业。因此,a[1,2].shape是一个二维tensor,形状为[6,7]该方法a[1,2]等同于上述的a[1][2]。可以少写括号且更直观。

a[1,2,3,4] 代表第1个班级中的第2名学生的第3门功课的第4份作业的信息,返回一个值。


2. 切片索引

2.1 变量[start : end]

使用位置索引切片,顾头不顾尾

# ==1== 方法一
 #从0-9的10个元素组成的tensor
a = tf.range(10)
# 获取3、4、5
a[3:6]
# 获取前3个,0、1、2
a[:3] 
# 获取倒数第4个到倒数第2个,-1代表最后一个
a[-4:-1] 


2.2 多个冒号,变量[A , : , : , B]

首先创建一个四维的tensor,shape为[4,5,6,7]。可以理解为,有4幅图像,每幅图像有5行,每一行包含6列,每一列有7个数据。

# ==2== 方法二
#创建4维tensor
b = tf.ones([4,5,6,7]) 
# 第0张图像有5行,每行有6列,每列有7个数
b[0].shape  
# 取第0张图片的所有数据
b[0,:,:,:].shape 
# 变成单通道,前3个维度全部获取,第四个维度取第2个
b[:,:,:,2].shape  
# 4张图像都取第2行,每行的所有列,每列的所有值,shape[4,6,7]
b[:,2,:,:].shape   

b[0] 和 b[0,:,:,:] 代表相同意思,都是取第0张图像的全部数据,返回的shape都是[5,6,7],即第0张图像有5行,每行有6列,每列有7个数值。

b[:,2,:,:] 代表所有图像的第2行数据,包含4张图像,每张图像有6列,每列有7个数值。因此,shape为[4,6,7]


2.3 指定步长,隔行采样,变量[start : end : step]

正序,定义的四维tensor,shape为[5,6,7,8],可以按上述方法理解它。

# 定义四维且值全为1的tensor
c = tf.ones([5,6,7,8]) 
# 第1、3张图像的所有数据
c[1:5:2,:,:,:].shape  
# 5张图片图片的第1、3行,0、2列的所有数据
c[:,1:5:2,:4:2,:].shape   

c[ 1:5:2 , : , : , : ] 代表第1、3张图像的全部信息,因为1到5张图像,步长为2,顾头不顾尾。因此shape为 [2,6,7,8]

c[:,1:5:2,:4:2,:] 代表所有5张图像,取1、3行信息,和取0、2列信息中的所有数据。因此shape为 [5,2,2,8]

步长为负数时,要求A靠近原数据尾端,B是前端

逆序排序方法: 变量 [A : B : -1]

# ==4== 逆序排序
#创建0-4的tensor
d = tf.range(5)  
# 给d逆序排序
d[::-1] 
# 倒序:4、2、0
d[4::-2] 


3. 省略号 '...' 方法

相比于 变量[ A , : , : , : , B]变量 [ A , ... , B ] 中,省略号自动计算A和B之间有几个':',写起来更方便。

首先创建一个五维tensor,形状shape为[3,10,12,14,8],其中 a[0]a[0 , : , : , : , : ] a[0 , ...] 代表的意思相同,都是指第一张图像的全部数据。shape为[10,12,14,8]

a[0 , ... , 4 , :] 中的省略号代表第3、4维度的全部数据,shape为[10,12,8]

# 创建一个五维tensor
a = tf.random.normal([3,10,12,14,8]) 
# 第0张图像的所有数据
a[0].shape  
a[0,:,:,:,:].shape  # 和上式相同  
a[0,...].shape  # 省略号代表后面的冒号
# 省略号代表中间两维
a[0,...,4,:].shape  


4. tf.gather()函数

指定某一个维度,按照指定索引获取数据

tf.gather(tensor, axis, indices=[ ])

value:代表tensor数据

axis: 代表取哪个维度

indices: 数据收集顺序,指定维度的具体索引

4.1 使用一次 tf.gather()

创建一个三维的data全由0构成,shape为[4,35,8],可以理解为4个班级,每个班级35个人,每个人有8门功课。指定一个维度,获得该维度下其他维度的部分数据

# 假设data三维[班级,学生,科目]
data = tf.zeros([4,35,8])
# indices指定收集顺序,查第2、3个班级的所有数据
tf.gather(data,axis=0,indices=[2,3]).shape
# 指定维度1即学生,收集索引号维30、5、18、2这四个学生的数据
tf.gather(data,axis=1,indices=[30,5,18,2]).shape

axis用来指定维度,axis=0代表班级维度,axis=1代表学生,axis=2代表功课

先指定维度0代表班级维度,获取第2、3个班级的全部数据,返回shape为[2,35,8]。班级维度变成了2个,而而每个班级仍包含35名学生,每名学生,仍有8门课。

若指定维度1代表学生维度,挑选第30、5、18、2这四名同学。这4个班都挑选需要为这四个数的四名学生,获取他们的全部数据,因此,班级维度没有改变,还是4,学生维度指定了只有4个,功课维度没变,仍有8个,最后shape为[4,4,8]


4.2 连续使用几次 tf.gather()

上面是获取指定维度指定索引的全部数据。如果我想获取指定维度指定索引的指定数据怎么办呢。

我们连续使用两次tf.gather()来抽查,所有班级某几位同学的某几门课的成绩

# 获得四个班级指定三名学生的指定的三门课信息
data = tf.zeros([4,35,8])
a1 = tf.gather(data,axis=1,indices=[30,5,18,2])  #获取4名学生的全部信息
a2 = tf.gather(a1,axis=2,indices=[6,1,4]).shape  #axis=2指定科目,获取6,1,4科目信息

获得四个班级,每个班的30、5、18、2这个四名同学的6、1、4这3门功课的信息,因此结果shape为[4,4,3]


5. tf.gather_nd() 函数

tf.gather_nd(tensor, indices)

按照 indices 的格式从传入的tensor中抽取切片(合并为一个Tensor)indices是一个K维整数Tensor

首先创建一个三维且值全为0的tensor,可按上述方法理解这三维。

# 指定2个维度,取第三个维度的所有值
data = tf.zeros([4,35,8])
# 获取第[[0]]个班级所有数据,返回值减少一维度
a1 = tf.gather_nd(data,[0]).shape  
# 取0号班级第1个学生的数据,返回值少两个维度
a2 = tf.gather_nd(data,[0,1]).shape
# 取0号班级第1个学生的第2门课的数据,返回值少三个维度
a3 = tf.gather_nd(data,[0,1,2]).shape

tf.gather_nd(data,[0,1,2]) 代表从data中获取第0个班级的第1个学生的第2门课的数据,是一个值,因此返回的shape为 []

注意参数indices的括号使用方法,如a5,首先获取第0个班级的第1个学生的功课数据(一维),第1个班级第5个学生的功课数据(一维),2个列表组合放到一个列表里,组成二维列表,再在外面加一个中括号,生成三维,理解为这是第1次抽取结果,因此返回的shape为[1,2,8]

再如a6,获取的是指定班级指定学生的功课信息,[0,4]指第0个班级第4位同学的所有功课数据,返回一个列表(一维),由8门功课组成。三个一维列表外面加一个中括号,构成二维列表。shape维[3,8]。指有3位同学,每位同学有8门课。

# 取第0个班级的第1名学生的第2门课成绩,和第1个班级的第5名学生的第7门课成绩,放在一个列表中
a4 = tf.gather_nd(data,[[0,1,2],[1,5,7]]).shape
# 取第0个班级的第1名学生的所有课成绩,和第1个班级的第5名学生的所有课成绩
a5 = tf.gather_nd(data,[[[0,1],[1,5]]]).shape 
# 将二维的成绩信息放在一个三维tensor中,
# 第一维表示第一次记录,第二维表示哪些学生,第三维表示每个学生的所有科目
a6 = tf.gather_nd(data,[[0,4],[1,7],[3,5]]).shape
# 第0个班级的第4个学生的所有科目,第1个班级第7个学生所有科目。。。组合成一个二维tensor


6. 布尔索引选数据

tf.boolean_mask(tensor, mask=布尔标记, axis=指定维度)

mask的shape要和指定维度的tensor的shape相同。输出mask标记维True的值。

# 选择输出mask为True的值
a = tf.ones([3,35,5,10]) # 3个班级35名学生5门课各有10份作业
# 对第0维的3个班级生成mask,即值要第0、1个班级的数据
tf.boolean_mask(a,mask=[True,True,False]).shape  #默认axis=0,即第一个维度
# 对第2维的课目生成mark,要第2、3门课的所有信息
tf.boolean_mask(a,mask=[False,False,True,True,False],axis=2).shape

tf.boolean_mask(a,mask=[True,True,False]).shape 对班级维度的三个班级进行选择,第0、1个班级为True,第2个班级为False,因此输出第0、1个班级的全部信息,即shape为[2,35,5,10]

生成一个三维的值全为1的tensor,没有指定axis,可看出是对班级维度和学生维度的筛选。输出结果的第一行是第0个班级第0个学生的4项信息,结果的第二三行是第1个班级第1、2个学生的四项信息。

b = tf.ones([2,3,4])
# mask对应b的前两维度,第0维度取第0列的所有数据,第维度取第1、2列的所有数据
tf.boolean_mask(b,mask=[[True,False,False],[False,True,True]])

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立Sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值