【tensorflow2.0】张量的结构操作
张量的操作主要包括张量的结构操作和张量的数学运算。 张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。 张量数学运算主要有:标量运算,向量运算,矩阵运算。另外我们会介绍张量运算的广播机制。 本篇我们介绍张量的结构操作。 一,创建张量张量创建的许多方法和numpy中创建array的方法很像。 import tensorflow as tf numpy as np a = tf.constant([1,2,3],dtype = tf.float32) tf.print(a)
b = tf.range(1,10,delta = 2) tf.print(b)
c = tf.linspace(0.0,2*3.14,100print(c)
d = tf.zeros([3,3]) tf.print(d)
a = tf.ones([3,1)">]) b = tf.zeros_like(a,dtype=print(a) tf.print(b)
b = tf.fill([3,2],5print(b)
# 均匀分布随机 tf.random.set_seed(1.0) a = tf.random.uniform([5],minval=0,maxval=10print(a)
正态分布随机 b = tf.random.normal([3,mean=0.0,stddev=1.0print(b)
正态分布随机,剔除2倍方差以外数据重新生成 c = tf.random.truncated_normal((5,5),stddev=1.0,1)">tf.float32) tf.print(c)
特殊矩阵 I = tf.eye(3,3) 单位矩阵 tf.(I) tf.print(" ") t = tf.linalg.diag([1,3]) 对角阵 tf.print(t)
二,索引切片张量的索引切片方式和numpy几乎是一样的。切片时支持缺省参数和省略号。 对于tf.Variable,可以通过索引和切片对部分元素进行修改。 对于提取张量的连续子区域,也可以使用tf.slice. 此外,对于不规则的切片提取,可以使用tf.gather,tf.gather_nd,tf.boolean_mask。 tf.boolean_mask功能最为强大,它可以实现tf.gather,tf.gather_nd的功能,并且tf.boolean_mask还可以实现布尔索引。 如果要通过修改张量的某些元素得到新的张量,可以使用tf.where,tf.scatter_nd。 tf.random.set_seed(3) t = tf.random.uniform([5,5],maxval=10,1)">tf.int32) tf.print(t)
第0行 tf.print(t[0])
倒数第一行 tf.print(t[-1])
第1行第3列 tf.print(t[1,1)">print(t[1][3])
第1行至第3行 tf.print(t[1:4,:]) tf.print(tf.slice(t,[1,0],[3,5])) tf.slice(input,begin_vector,size_vector)
第1行至最后一行,第0列到最后一列每隔两列取一列 tf.print(t[1:4,:4:2])
对变量来说,还可以使用索引和切片修改部分元素 x = tf.Variable([[1,4]],1)"> tf.float32) x[1,:].assign(tf.constant([0.0,0.0])) tf.print(x)
a = tf.random.uniform([3,3,1)">print(a)
省略号可以表示多个冒号 tf.print(a[...,1])
以上切片方式相对规则,对于不规则的切片提取,tf.boolean_mask。 考虑班级成绩册的例子,有4个班级,每个班级10个学生,每个学生7门科目成绩。可以用一个4?10?7的张量来表示。 scores = tf.random.uniform((4,7),maxval=100,1)">print(scores)
抽取每个班级第0个学生,第5个学生,第9个学生的全部成绩 p = tf.gather(scores,[0,5,9],axis=1print(p)
抽取每个班级第0个学生,第5个学生,第9个学生的第1门课程,第3门课程,第6门课程成绩 q = tf.gather(tf.gather(scores,axis=1),6],axis=2print(q)
抽取第0个班级第0个学生,第2个班级的第4个学生,第3个班级的第6个学生的全部成绩 # indices的长度为采样样本的个数,每个元素为采样位置的坐标 s = tf.gather_nd(scores,indices = [(0,0),(2,4),(3,6)])
以上tf.gather和tf.gather_nd的功能也可以用tf.boolean_mask来实现。 抽取每个班级第0个学生,第5个学生,第9个学生的全部成绩 p = tf.boolean_mask(scores,[True,False,True,True],axis=1 抽取第0个班级第0个学生,第2个班级的第4个学生,第3个班级的第6个学生的全部成绩 s =print(s)
利用tf.boolean_mask可以实现布尔索引 找到矩阵中小于0的元素 c = tf.constant([[-1,1,-1],[2,-2],-3,3]],1)">print(c,"n) tf.print(tf.boolean_mask(c,c<0),1)">) tf.print(c[c<0]) 布尔索引,为boolean_mask的语法糖形式
以上这些方法仅能提取张量的部分元素值,但不能更改张量的部分元素值得到新的张量。 如果要通过修改张量的部分元素值得到新的张量,可以使用tf.where和tf.scatter_nd。 tf.where可以理解为if的张量版本,此外它还可以用于找到满足条件的所有元素的位置坐标。 tf.scatter_nd的作用和tf.gather_nd有些相反,tf.gather_nd用于收集张量的给定位置的元素, 而tf.scatter_nd可以将某些值插入到一个给定shape的全0的张量的指定位置处。 找到张量中小于0的元素,将其换成np.nan得到新的张量 tf.where和np.where作用类似,可以理解为if的张量版本 c = tf.constant([[-1,1)">tf.float32) d = tf.where(c<0,tf.fill(c.shape,np.nan),c)
如果where只有一个参数,将返回所有满足条件的位置坐标 indices = tf.where(c<0) indices
将张量的第[0,0]和[2,1]两个位置元素替换为0得到新的张量 d = c - tf.scatter_nd([[0,1]],[c[0,c[2,1]],c.shape)
scatter_nd的作用和gather_nd有些相反 可以将某些值插入到一个给定shape的全0的张量的指定位置处。 indices = tf.where(c<0) tf.scatter_nd(indices,tf.gather_nd(c,indices),?numpy= 三,维度变换维度变换相关函数主要有 tf.reshape,tf.squeeze,tf.expand_dims,tf.transpose. tf.reshape 可以改变张量的形状。 tf.squeeze 可以减少维度。 tf.expand_dims 可以增加维度。 tf.transpose 可以交换维度。 tf.reshape可以改变张量的形状,但是其本质上不会改变张量元素的存储顺序,所以,该操作实际上非常迅速,并且是可逆的。 a = tf.random.uniform(shape=[1,2],minval=0,maxval=255,1)">(a.shape) tf.print(a)
改成 (3,6)形状的张量 b = tf.reshape(a,6(b.shape) tf.print(b)
改回成 [1,2] 形状的张量
c = tf.reshape(b,1)">print(c)
如果张量在某个维度上只有一个元素,利用tf.squeeze可以消除这个维度。 和tf.reshape相似,它本质上不会改变张量元素的存储顺序。 张量的各个元素在内存中是线性存储的,其一般规律是,同一层级中的相邻元素的物理地址也相邻。 s = tf.squeeze(a) tf.(s.shape) tf.print(s)
d = tf.expand_dims(s,axis=0) 在第0维插入长度为1的一个维度
tf.transpose可以交换张量的维度,与tf.reshape不同,它会改变张量元素的存储顺序。 tf.transpose常用于图片存储格式的变换上。 Batch,Height,Width,Channel a = tf.random.uniform(shape=[100,600,4],1)">(a.shape) 转换成 Channel,Batch s= tf.transpose(a,perm=[3,0]) tf.print(s.shape)
四,合并分割和numpy类似,可以用tf.concat和tf.stack方法对多个张量进行合并,可以用tf.split方法把一个张量分割成多个张量。 tf.concat和tf.stack有略微的区别,tf.concat是连接,不会增加维度,而tf.stack是堆叠,会增加维度。 a = tf.constant([[1.0,2.0],[3.0,4.0]]) b = tf.constant([[5.0,6.0],[7.0,8.0]]) c = tf.constant([[9.0,10.0],[11.0,12.0]]) tf.concat([a,b,c],axis = 0)
tf.concat([a,axis = 1)
tf.stack([a,c])
tf.stack([a,axis=1)
a = tf.constant([[1.0,1)">]]) c = tf.concat([a,axis = 0) tf.split是tf.concat的逆运算,可以指定分割份数平均分割,也可以通过指定每份的记录数量进行分割。 tf.split(value,num_or_size_splits,axis) tf.split(c,axis = 0) 指定分割份数,平均分割
tf.split(c,axis = 0) 指定每份的记录数量
参考: 开源电子书地址:https://lyhue1991.github.io/eat_tensorflow2_in_30_days/ GitHub 项目地址:https://github.com/lyhue1991/eat_tensorflow2_in_30_days (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |