张量的定义
张量(Tensor)理论是数学的一个分支学科,在力学中有重要应用。张量这一术语起源于力学,它最初是用来表示弹性介质中各点应力状态的,后来张量理论发展成为力学和物理学的一个有力的数学工具。张量之所以重要,在于它可以满足一切物理定律必须与坐标系的选择无关的特性。张量概念是矢量概念的推广,矢量是一阶张量。张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数(可以理解成是向量、矩阵以及更高维结构的统称)。
But we don’t have to restrict ourselves to linear algebra. As it turns out, we can move up the mathematical food chain a bit. It has long been known that there are bigger fish in the mathematical abstraction sea than just matrices. One such candidate is called a tensor. Tensors figure prominently in the mathematical underpinnings of general relativity and are fundamental to other branches of physics as well. But just as the mathematical concepts of matrices and vectors can be simplified down to the arrays we use in computers, tensors can also be simplified and represented as multidimensional arrays and some related operations. Unfortunately, things aren’t quite as simple as they were with matrices and vectors, largely because there isn’t an obvious and simple set of operations to be performed on tensors like there were with matrices and vectors.
There is some really good news, though. Even though we can’t write just a few operations on tensors, we can write down a set of patterns of operations on tensors. That isn’t quite enough, however, because programs written in terms of these patterns can’t be executed at all efficiently as they were written. The rest of the good news is that our inefficient but easy to write programs can be transformed (almost) automatically into programs that do execute pretty efficiently.
以下内容基于Tensorflow框架。(下面代码是在notebook写的,所以import tensorflow as tf只写了一次,需要的自行添加)
Tensor基本操作
tensor的数据类型及属性
tensorflow中的数据类型有int、float、double、bool、string。
创建这些数据的相应code例子如下:
tf.constant(1) tf.constant(1.) tf.constant(2.2,dtype=tf.int32) tf.constant(2.,dtype=tf.double) tf.constant([True,False]) tf.constant(‘Hello World‘)
属性
1、device:查看tensor的创建环境
a=tf.range(5) a.device
输出:
‘/job:localhost/replica:0/task:0/device:CPU:0‘
2、numpy:将tensor数据类型转numpy数据类型
a.numpy() 输出: array([0, 1, 2, 3, 4], dtype=int32)
3、ndim:tensor的维度
a.ndim 输出: 1
4、shape:tensor的形状
a.shape 输出: TensorShape([5])
5、rank:tensor的维度,不过返回的是一个tensor
tf.rank(a)
tf.rank(tf.ones([1,2,3])) 输出: <tf.Tensor: id=8, shape=(), dtype=int32, numpy=1> ##numpy是内容
<tf.Tensor: id=12, shape=(), dtype=int32, numpy=3>
6、isinstance/is_tensor:判断是不是tensor
way1:isinstance(a,tf.Tensor)
way2:tf.is_tensor(a)
输出:
True
True
7、dtype:数据类型
a.dtype
输出:
tf.int32
8、convert_to_tensor:numpy转tensor
import numpy as np a=np.arange(5) aa=tf.convert_to_tensor(a,dtype=tf.int32) aa 输出: <tf.Tensor: id=16, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)>
9、cast:数据类型转换
tf.cast(aa,dtype=tf.float32) 输出: <tf.Tensor: id=17, shape=(5,), dtype=float32, numpy=array([0., 1., 2., 3., 4.], dtype=float32)>
10、Variable:赋予参数一些额外的属性
a=tf.range(5) b=tf.Variable(a,name=‘asuka‘) b.name b.trainable #可求导 输出: ‘asuka:0‘ True
注意,
isinstance(b,tf.Tensor) #所以 不推荐使用isinstance这种类型,还是用is_tensor比较好 isinstance(b,tf.Variable)
tf.is_tensor(b)
输出:
False
True
True
创建Tensor
1、tf.convert_to_tensor
tf.convert_to_tensor(np.ones([2,2])) tf.convert_to_tensor([[1],[2.]]) 输出: <tf.Tensor: id=79, shape=(2, 2), dtype=float64, numpy= array([[1., 1.], [1., 1.]])> <tf.Tensor: id=82, shape=(2, 1), dtype=float32, numpy= array([[1.], [2.]], dtype=float32)>
2、tf.zeros/tf.ones
tf.zeros([]) #标量0 tf.zeros([1]) tf.zeros([2,2]) # tf.ones的代码一样,只是0变成了1 输出: <tf.Tensor: id=89, shape=(), dtype=float32, numpy=0.0> <tf.Tensor: id=93, shape=(1,), dtype=float32, numpy=array([0.], dtype=float32)> <tf.Tensor: id=94, shape=(2, 2), dtype=float32, numpy= array([[0., 0.], [0., 0.]], dtype=float32)>
此外,需要补充一下tf.zeros_like(a)/tf.ones_like(a)这种便捷功能。其生成tensor的shape与a一致,相当于tf.zeros(a.shape)/tf.ones(a.shape)
tf.zeros_like(a) tf.ones_like(a) 输出: <tf.Tensor: id=95, shape=(5,), dtype=int32, numpy=array([0, 0, 0, 0, 0], dtype=int32)> <tf.Tensor: id=98, shape=(5,), dtype=int32, numpy=array([1, 1, 1, 1, 1], dtype=int32)>
3、tf.fill
tf.fill([2,2],66) tf.fill([2,2],0.1) 输出: <tf.Tensor: id=104, shape=(2, 2), dtype=int32, numpy= array([[66, 66], [66, 66]], dtype=int32)> <tf.Tensor: id=107, shape=(2, 2), dtype=float32, numpy= array([[0.1, 0.1], [0.1, 0.1]], dtype=float32)>
4、随机初始化
①正态分布:tf.random.normal([2,2], mean=0,stddev=1)
②截断的正态分布:tf.random.truncated_normal([2,2], mean=0,stddev=1)
③均匀分布:tf.random.uniform([2,2],minval=0,maxval=1)
tf.random.normal([2,2], mean=0,stddev=1) tf.random.truncated_normal([2,2], mean=0,stddev=1) tf.random.uniform([2,2],minval=0,maxval=1) 输出: <tf.Tensor: id=113, shape=(2, 2), dtype=float32, numpy= array([[-0.21209939, -0.64754343], [-1.0172042 , 0.41624036]], dtype=float32)> <tf.Tensor: id=119, shape=(2, 2), dtype=float32, numpy= array([[-0.86256725, -0.72628754], [-0.3911226 , 0.64116365]], dtype=float32)> <tf.Tensor: id=126, shape=(2, 2), dtype=float32, numpy= array([[0.92780185, 0.4641881 ], [0.30780447, 0.47879505]], dtype=float32)>
补充:
idx = tf.range(10) idx = tf.random.shuffle(idx) #对idx进行随机打散 a = tf.random.normal([10,784]) a = tf.gather(a,idx) #利用idx索引对a进行随机打散 idx a 输出: <tf.Tensor: id=170, shape=(10,), dtype=int32, numpy=array([6, 3, 1, 4, 8, 9, 5, 7, 2, 0], dtype=int32)> <tf.Tensor: id=178, shape=(10, 784), dtype=float32, numpy= array([[-0.6336075 , 1.4922131 , -2.320528 , ..., 0.2953391 , -0.40848997, 0.9237991 ], [-1.1071885 , 1.8510056 , -0.4211796 , ..., -0.11134891, 0.00801583, 0.42422166], [-0.3443342 , 1.5786427 , -3.8558512 , ..., 0.80399513, 0.36636525, -0.29242495], ..., [-0.45643282, -0.99563426, 2.7573252 , ..., -1.9459194 , -1.8840737 , 0.5211977 ], [ 0.7347293 , 0.59493566, -0.00406144, ..., -1.0898517 , -0.3647101 , 1.9180689 ], [-0.10276955, -0.71196973, 0.779926 , ..., -0.07749026, -0.25664854, 0.7480723 ]], dtype=float32)>
索引
写法一:用框框分隔
a = tf.ones([1,5,5,3]) a[0][0] a[0][0][0] 输出: array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=float32)> <tf.Tensor: id=106, shape=(3,), dtype=float32, numpy=array([1., 1., 1.], dtype=float32)>
写法二:用逗号分隔
a = tf.random.normal([1,5,5,3]) a[0,0] a[0,2].shape 输出: <tf.Tensor: id=130, shape=(5, 3), dtype=float32, numpy= array([[-0.35566926, -0.96789527, -0.930224 ], [-1.1206602 , 0.88065714, -0.07800838], [-0.09039619, 0.03437081, -1.5635891 ], [ 0.20114912, -1.0815347 , 0.30600008], [ 1.9283246 , -0.6195314 , -0.28424558]], dtype=float32)> TensorShape([5, 3])
切片
start : end
a = tf.range(10) a[-2:] a[:2] 输出: <tf.Tensor: id=164, shape=(2,), dtype=int32, numpy=array([8, 9], dtype=int32)> <tf.Tensor: id=176, shape=(2,), dtype=int32, numpy=array([0, 1], dtype=int32)>
start : end : step
a = tf.range(5) a[::-1] a[::-2] a[3:1:-2] 输出: <tf.Tensor: id=200, shape=(5,), dtype=int32, numpy=array([4, 3, 2, 1, 0], dtype=int32)> <tf.Tensor: id=212, shape=(3,), dtype=int32, numpy=array([4, 2, 0], dtype=int32)> <tf.Tensor: id=228, shape=(1,), dtype=int32, numpy=array([3], dtype=int32)>
相关函数
1、tf.gather
进行切片
格式:tf.gather(params, indices, validate_indices=None, name=None, axis=0)
其中,params表示待切的张量,indices表示取出数据的位置,axis指定切片所在的维度。
a = tf.random.normal([6,5,4],mean=1,stddev=1) tf.gather(a,axis=0,indices=[2,3]) 输出: <tf.Tensor: id=237, shape=(2, 5, 4), dtype=float32, numpy= array([[[ 1.5593833 , 1.0110648 , 1.9511329 , 1.2995625 ], [ 1.2551384 , 2.2249537 , 1.9536419 , 2.041832 ], [ 0.9333749 , 1.4165081 , -0.43102372, 2.3897305 ], [ 1.4070803 , 1.4304484 , 0.5074375 , 0.1073221 ], [ 2.384912 , -1.0563302 , 0.6985694 , 1.1213328 ]], [[ 1.8210306 , -0.6484443 , 0.4258331 , 0.88605404], [ 0.6124698 , -0.654827 , 2.163889 , 1.2491949 ], [ 1.1132616 , -0.8744116 , 1.5687683 , 2.0351982 ], [ 0.93111885, 0.4436323 , 1.5315795 , 0.6178591 ], [-0.42866087, 1.9578406 , 1.157727 , 1.241925 ]]], dtype=float32)>
2、tf.gather_nd
也是切片,允许在多维上进行索引。
格式:tf.gather_nd(params, indices, name=None)
a = tf.random.normal([6,5,4],mean=1,stddev=1)
tf.gather_nd(a, [[0,1],[1,1]])
tf.gather_nd(a, [[0,1],[1,1],[2,2]])
输出:
<tf.Tensor: id=265, shape=(2, 4), dtype=float32, numpy=
array([[0.99216527, 1.2477858 , 0.14764303, 0.2085458 ],
[0.65654033, 2.0438895 , 0.3014146 , 0.66133136]], dtype=float32)>
<tf.Tensor: id=285, shape=(3, 4), dtype=float32, numpy=
array([[-1.5789361 , 1.6277008 , 1.1488252 , 1.8736987 ],
[-0.49054933, 1.8427005 , 0.77670544, 0.14120448],
[ 0.41770607, 0.6793497 , -0.94432163, 0.8347257 ]], dtype=float32)>
3、tf.boolean_mask
按mask指定的列进行过滤,默认维度是0。
格式:tf.boolean_mask(params,mask,name=‘boolean_mask‘,axis=None)
a = tf.ones([2,3,4]) tf.boolean_mask(a, mask=[True,True,True,False], axis=2) 输出: <tf.Tensor: id=316, shape=(2, 3, 3), dtype=float32, numpy= array([[[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], [[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]], dtype=float32)>
维度变换
1、tf.reshape
作用:重新排列
a = tf.random.normal([6,4,8,4], mean=1, stddev=1) a.shape a.dim 输出: Tensorshape([6, 4, 8, 4]) 4 tf.reshape(a,[6,4*8,4]).shape tf.reshape(a,[6,-1,4]).shape #位置维度时,可以用-1填充 输出: Tensorshape([6, 32, 4]) Tensorshape([6, 32, 4]) tf.reshape(tf.reshape(a, [6, -1]), [6, 4, -1, 4]).shape 输出: Tensorshape([6, 4, 8, 4])
2、tf.transpose
作用:转置
格式:tf.transpose(a, perm=None, name=‘transpose‘, conjugate=False)
其中,a指需要变换的张量,perm指a的新的维度序列,默认将所有的轴进行转置。
a = tf.random.normal([4,3,2,1]) a.shape tf.transpose(a).shape #默认将所有轴进行转置 tf.transpose(a,perm=[0,1,3,2]).shape 输出: TensorShape([4, 3, 2, 1]) TensorShape([1, 2, 3, 4]) TensorShape([4, 3, 1, 2])
3、tf.expand_dims
作用:扩充维度(对于张量a,在axis轴处为其增加一个为1的维度)
格式:tf.expand_dims(a, axis=None)
a = tf.random.normal([3,4,5]) a.shape tf.expand_dims(a,axis=0).shape 输出: TensorShape([3, 4, 5]) TensorShape([1, 3, 4, 5]) tf.expand_dims(a,axis=-1).shape 输出: TensorShape([3, 4, 5, 1])
4、tf.squeeze
作用:去掉为1的维度,默认检索所有轴。
格式:tf.expand_dims(a, axis=None)
a = tf.zeros([1,2,1,1,3]) a.shape tf.squeeze(a,axis=0).shape tf.squeeze(a,axis=-2).shape tf.squeeze(a).shape 输出: TensorShape([1, 2, 1, 1, 3]) TensorShape([2, 1, 1, 3]) TensorShape([1, 2, 1, 3]) TensorShape([2, 3])
基本运算
1、加(+)、减(-)、乘(*)、除(/)、整除(//)、取余(%)、n次方(**)
a = tf.ones([2,2]) b = tf.fill([2,2],2.) a+b a-b a*b a/b a//b a%b b**3
2、tf.math.log()、tf.math.exp()
a = tf.fill([2,2], 10.) tf.math.log(a) #取对数 tf.math.exp(a) #取指数 tf.math.log(a)/tf.math.log(2.) #计算矩阵对应元素以2为底的对数 输出: <tf.Tensor: id=54, shape=(2, 2), dtype=float32, numpy= array([[2.3025851, 2.3025851], [2.3025851, 2.3025851]], dtype=float32)> <tf.Tensor: id=59, shape=(2, 2), dtype=float32, numpy= array([[22026.465, 22026.465], [22026.465, 22026.465]], dtype=float32)> <tf.Tensor: id=68, shape=(2, 2), dtype=float32, numpy= array([[3.321928, 3.321928], [3.321928, 3.321928]], dtype=float32)>
3、tf.pow()、tf.sqrt()
a = tf.fill([2,2], 2.) tf.pow(a,3) #立方,等效于a**3 tf.sqrt(a) #开方 输出: <tf.Tensor: id=101, shape=(2, 2), dtype=float32, numpy= array([[8., 8.], [8., 8.]], dtype=float32)> <tf.Tensor: id=107, shape=(2, 2), dtype=float32, numpy= array([[1.4142135, 1.4142135], [1.4142135, 1.4142135]], dtype=float32)>
4、矩阵相乘:@/matmul
a = tf.fill([2,2],2.) b = tf.fill([2,2],3.) a @ b #矩阵相乘 tf.matmul(a,b)#矩阵相乘的第二种写法 输出: <tf.Tensor: id=115, shape=(2, 2), dtype=float32, numpy= array([[12., 12.], [12., 12.]], dtype=float32)>
广播
Tensorflow中的广播机制类似于numpy中的广播机制,给出以下例子。
import tensorflow as tf a = tf.reshape(range(12),[4,3]) 输出: <tf.Tensor: id=42, shape=(4, 3), dtype=int32, numpy= array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]], dtype=int32)> b = tf.cast(tf.ones([1,3]),dtype=tf.int32) 输出: <tf.Tensor: id=53, shape=(1, 3), dtype=int32, numpy=array([[1, 1, 1]], dtype=int32)> c = a - b #这种操作是隐式的 输出: <tf.Tensor: id=55, shape=(4, 3), dtype=int32, numpy= array([[-1, 0, 1], [ 2, 3, 4], [ 5, 6, 7], [ 8, 9, 10]], dtype=int32)> 这里举一个广播和的矩阵相乘的例子 a = tf.fill([4,2,3],1.) b = tf.fill([3,5],2.) c = tf.broadcast_to(b,[4,3,5]) a @ c 输出: <tf.Tensor: id=124, shape=(4, 2, 5), dtype=float32, numpy= array([[[6., 6., 6., 6., 6.], [6., 6., 6., 6., 6.]], [[6., 6., 6., 6., 6.], [6., 6., 6., 6., 6.]], [[6., 6., 6., 6., 6.], [6., 6., 6., 6., 6.]], [[6., 6., 6., 6., 6.], [6., 6., 6., 6., 6.]]], dtype=float32)>
高阶操作
合并&分割
1、tf.concat
作用:合并
a = tf.ones([5,10,8]) b = tf.ones([5,10,8]) c = tf.concat([a,b],axis=2) c.shape 输出: TensorShape([5, 10, 16])
2、tf.stack
作用:堆叠(开辟新的维度)
a = tf.ones([5,10,8]) b = tf.ones([5,10,8]) c = tf.stack([a,b],axis=2) c.shape 输出: TensorShape([5, 10, 2, 8])
3、tf.unstack
作用:解堆叠
a = tf.ones([5,10,8]) b = tf.ones([5,10,8]) c = tf.stack([a,b],axis=2) aa,bb = tf.unstack(c,axis=2) aa.shape,bb.shape 输出: (TensorShape([5, 10, 8]), TensorShape([5, 10, 8]))
4、tf.split
作用:分割
a = tf.ones([5,10,8]) b = tf.ones([5,10,8]) c = tf.stack([a,b],axis=2) res=tf.split(c, axis=2, num_or_size_splits=2) res[0].shape,res[1].shape 输出: (TensorShape([5, 10, 1, 8]), TensorShape([5, 10, 1, 8]))
填充
格式:tf.pad(tensor, paddings, mode="CONSTANT", name=None, constant_values=0)
a = range(9) a = tf.reshape(a,[3,3]) # 不填充 tf.pad(a,[[0,0],[0,0]]) 输出: <tf.Tensor: id=564, shape=(3, 3), dtype=int32, numpy= array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=int32)> # 填充 tf.pad(a,[[1,0],[0,0]]) 输出: <tf.Tensor: id=566, shape=(4, 3), dtype=int32, numpy= array([[0, 0, 0], [0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=int32)> tf.pad(a,[[1,1],[1,1]]) 输出: <tf.Tensor: id=568, shape=(5, 5), dtype=int32, numpy= array([[0, 0, 0, 0, 0], [0, 0, 1, 2, 0], [0, 3, 4, 5, 0], [0, 6, 7, 8, 0], [0, 0, 0, 0, 0]], dtype=int32)>
假设输入的tensor有三个维度,paddings参数设置为 paddings = [[a,b], [c,d], [e,f]]
其中,a,b表示为axis=0维度上最前面填充a行,最后面填充b行;c,d表示为axis=1维度上最前面填充c列,最后面填充d列;e,f表示为axis=2维度上最前面填充e,最后面填充f。更高维的以此类推。
复制
格式:tf.tile(a, multiples, name=None)
其中,multiples为在某一维度上复制的次数。
a = tf.range(9) a = tf.reshape(a,[3,3]) # 不复制 tf.tile(a,[1,1]) 输出: <tf.Tensor: id=576, shape=(3, 3), dtype=int32, numpy= array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=int32)> # 复制 tf.tile(a,[2,1]) #在axis=0维度上复制2次 输出: <tf.Tensor: id=578, shape=(6, 3), dtype=int32, numpy= array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=int32)> tf.tile(a,[1,2]) #在axis=1维度上复制2次 输出: <tf.Tensor: id=580, shape=(3, 6), dtype=int32, numpy= array([[0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8]], dtype=int32)> tf.tile(a,[2,2]) #在axis=0和axis=1维度上分别复制2次,先复制小维度,再复制大维度 输出: <tf.Tensor: id=582, shape=(6, 6), dtype=int32, numpy= array([[0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8], [0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8]], dtype=int32)>
与广播机制相比,broadcast_to相当于先expand_dims,再tile。
a = tf.reshape(tf.range(9),[3,3]) # broadcast_to相当于先expand_dims,再tile # way1 aa = tf.expand_dims(a,axis=0)#先扩充维度 bb = tf.tile(aa,[2,1,1]) # way2 cc = tf.broadcast_to(a,[2,3,3]) 输出: <tf.Tensor: id=594, shape=(2, 3, 3), dtype=int32, numpy= array([[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [[0, 1, 2], [3, 4, 5], [6, 7, 8]]], dtype=int32)>
数据统计
1、norm
作用:求范数。
a = tf.ones([2,2])
#求a的二范数
tf.norm(a)#第一种写法
#<tf.Tensor: id=387, shape=(), dtype=float32, numpy=2.0>
tf.sqrt(tf.reduce_sum(tf.square(a))) #第二种写法
#<tf.Tensor: id=399, shape=(), dtype=float32, numpy=2.0>
tf.norm(a,ord=2,axis=1) #求a在轴1方向上的二范数
#<tf.Tensor: id=416, shape=(2,), dtype=float32, numpy=array([1.4142135, 1.4142135], dtype=float32)>
tf.norm(a,ord=1) #求a的一范数
#<tf.Tensor: id=437, shape=(), dtype=float32, numpy=4.0>
tf.norm(a,ord=1,axis=0) #求a在轴0方向上的一范数
#<tf.Tensor: id=462, shape=(2,), dtype=float32, numpy=array([2., 2.], dtype=float32)>
tf.norm(a,ord=1,axis=1) #求a在轴1方向上的一范数
#<tf.Tensor: id=462, shape=(2,), dtype=float32, numpy=array([2., 2.], dtype=float32)>
2、max/min/mean
作用:求最小值、最大值和均值
b = tf.random.normal([4,10]) tf.reduce_min(b) #<tf.Tensor: id=470, shape=(), dtype=float32, numpy=-2.5767317> tf.reduce_max(b) #<tf.Tensor: id=472, shape=(), dtype=float32, numpy=1.5258235> tf.reduce_mean(b) #<tf.Tensor: id=474, shape=(), dtype=float32, numpy=-0.22544508> tf.reduce_min(b,axis=1) #对轴1方向取最小值 #<tf.Tensor: id=476, shape=(4,), dtype=float32, numpy=array([-2.3222475, -2.0107253, -1.5776284, -2.5767317], dtype=float32)> tf.reduce_max(b,axis=1) #对轴1方向取最大值 #<tf.Tensor: id=478, shape=(4,), dtype=float32, numpy=array([1.416933 , 1.5258235, 1.0989064, 1.1648433], dtype=float32)> tf.reduce_mean(b,axis=1) #对轴1方向取均值 #<tf.Tensor: id=480, shape=(4,), dtype=float32, numpy=array([-0.05750545, -0.18739279, -0.3392655 , -0.31761646], dtype=float32)>
3、tf.argmax、tf.argmin
作用:求最大值、最小值位置
c = tf.random.normal([4,10]) tf.argmax(c).shape #TensorShape([10]) tf.argmax(c) #<tf.Tensor: id=490, shape=(10,), dtype=int64, numpy=array([2, 0, 1, 2, 3, 0, 2, 3, 0, 0])> tf.argmin(c).shape #TensorShape([10]) tf.argmin(c) #<tf.Tensor: id=494, shape=(10,), dtype=int64, numpy=array([0, 2, 3, 1, 0, 1, 3, 2, 2, 3])> tf.argmax(c,axis=1) #<tf.Tensor: id=496, shape=(4,), dtype=int64, numpy=array([1, 7, 0, 7])> tf.argmin(c,axis=1) #<tf.Tensor: id=498, shape=(4,), dtype=int64, numpy=array([6, 3, 8, 9])>
4、tf.equal
作用:判断矩阵中数据相等。
d1 = tf.constant([0,2,3,2,4]) d2 = tf.range(5) res = tf.equal(d1,d2) d1,d2,res 输出: (<tf.Tensor: id=499, shape=(5,), dtype=int32, numpy=array([0, 2, 3, 2, 4], dtype=int32)>, <tf.Tensor: id=503, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)>, <tf.Tensor: id=504, shape=(5,), dtype=bool, numpy=array([ True, False, False, False, True])>)
通过比较数据,我们可以计算数据预测的准确度。
e = tf.constant([[0.1,0.2,0.7],[0.9,0.05,0.05],[0.1,0.8,0.1],[0.01,0.99,0]]) pred = tf.cast(tf.argmax(e,axis=1),dtype=tf.int32) e,pred 输出: (<tf.Tensor: id=518, shape=(4, 3), dtype=float32, numpy= array([[0.1 , 0.2 , 0.7 ], [0.9 , 0.05, 0.05], [0.1 , 0.8 , 0.1 ], [0.01, 0.99, 0. ]], dtype=float32)>, <tf.Tensor: id=521, shape=(4,), dtype=int32, numpy=array([2, 0, 1, 1], dtype=int32)>) y = tf.constant([2,0,1,2]) correct_num = tf.reduce_sum(tf.cast(tf.equal(pred,y),dtype=tf.int32)) accuracy = correct_num /e.shape[0] correct_num,accuracy 输出: (<tf.Tensor: id=526, shape=(), dtype=int32, numpy=3>, <tf.Tensor: id=530, shape=(), dtype=float64, numpy=0.75>)
5、tf.unique
作用:找不重复的地方
f1 = tf.range(5) Unique,idx = tf.unique(f1) Unique,idx #(<tf.Tensor: id=535, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)>, #<tf.Tensor: id=536, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)>) f2 = tf.constant([4,2,2,4,3]) Unique,idx = tf.unique(f2) Unique,idx #(<tf.Tensor: id=538, shape=(3,), dtype=int32, numpy=array([4, 2, 3], dtype=int32)>, #<tf.Tensor: id=539, shape=(5,), dtype=int32, numpy=array([0, 1, 1, 0, 2], dtype=int32)>) ff = tf.gather(Unique,idx) ff #<tf.Tensor: id=541, shape=(5,), dtype=int32, numpy=array([4, 2, 2, 4, 3], dtype=int32)>
排序
1、sort/argsort
sort是按照升序或降序对张量进行排序,而argsort是按照升序或者降序对张量进行排序,返回的是索引。
一维排序时,
# 一维 a = tf.range(5) a = tf.random.shuffle(a) 输出: <tf.Tensor: id=599, shape=(5,), dtype=int32, numpy=array([2, 1, 0, 3, 4], dtype=int32)> tf.sort(a,direction=‘ASCENDING‘) #按照升序进行排列 输出: <tf.Tensor: id=610, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)> tf.sort(a,direction=‘DESCENDING‘) #按照降序进行排列 输出: <tf.Tensor: id=618, shape=(5,), dtype=int32, numpy=array([4, 3, 2, 1, 0], dtype=int32)> idx_a = tf.argsort(a,direction=‘ASCENDING‘) #按照升序排列,并返回索引 输出: <tf.Tensor: id=639, shape=(5,), dtype=int32, numpy=array([2, 1, 0, 3, 4], dtype=int32)> idx_d = tf.argsort(a,direction=‘DESCENDING‘) #按照降序排列,并返回索引 输出: <tf.Tensor: id=648, shape=(5,), dtype=int32, numpy=array([4, 3, 0, 1, 2], dtype=int32)> tf.gather(a,idx_a) 输出: <tf.Tensor: id=650, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4], dtype=int32)> tf.gather(a,idx_d) 输出: <tf.Tensor: id=652, shape=(5,), dtype=int32, numpy=array([4, 3, 2, 1, 0], dtype=int32)>
二维排序时,
# 二维 a = tf.random.uniform([3,3],minval=1,maxval=10,dtype=tf.int32) 输出: <tf.Tensor: id=660, shape=(3, 3), dtype=int32, numpy= array([[5, 9, 5], [1, 5, 4], [2, 2, 9]], dtype=int32)> tf.sort(a,direction=‘ASCENDING‘) 输出: <tf.Tensor: id=671, shape=(3, 3), dtype=int32, numpy= array([[5, 5, 9], [1, 4, 5], [2, 2, 9]], dtype=int32)> tf.sort(a,direction=‘DESCENDING‘) 输出: <tf.Tensor: id=679, shape=(3, 3), dtype=int32, numpy= array([[9, 5, 5], [5, 4, 1], [9, 2, 2]], dtype=int32)> idx_a = tf.argsort(a,direction=‘ASCENDING‘) 输出: <tf.Tensor: id=709, shape=(3, 3), dtype=int32, numpy= array([[0, 2, 1], [0, 2, 1], [0, 1, 2]], dtype=int32)> idx_d = tf.argsort(a,direction=‘DESCENDING‘) 输出: <tf.Tensor: id=718, shape=(3, 3), dtype=int32, numpy= array([[1, 0, 2], [1, 2, 0], [2, 0, 1]], dtype=int32)>
2、top_k
作用:返回前k个最大值。
格式:tf.math.top_k(input, k=None, sorted=True, name=None)
a = tf.random.uniform([3,3],minval=0,maxval=10,dtype=tf.int32) res = tf.math.top_k(a,2)#前2个最大值 a,res.indices,res.values #indices是索引,values是值 输出: (<tf.Tensor: id=726, shape=(3, 3), dtype=int32, numpy= array([[3, 5, 6], [7, 8, 2], [6, 4, 5]], dtype=int32)>, <tf.Tensor: id=729, shape=(3, 2), dtype=int32, numpy= array([[2, 1], [1, 0], [0, 2]], dtype=int32)>, <tf.Tensor: id=728, shape=(3, 2), dtype=int32, numpy= array([[6, 5], [8, 7], [6, 5]], dtype=int32)>)
张量限幅
1、tf.clip_by_value
作用:限制张量a的最小值为clip_value_min,最大值为clip_value_max。
格式:tf.clip_by_value(a, clip_value_min, clip_value_max, name=None)
a = tf.range(9) tf.clip_by_value(a,2,8) #限制tensor a中张量最小值为2,最大值为8 输出: <tf.Tensor: id=756, shape=(9,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 8], dtype=int32)>
2、tf.nn.relu()
作用:计算激活函数 relu,大于0的数保持不变,小于0的数置为0
格式:tf.nn.relu(features, name = None)
import numpy as np a = np.arange(9) a = a-5 a tf.nn.relu(a) 输出: <tf.Tensor: id=763, shape=(9,), dtype=int64, numpy=array([0, 0, 0, 0, 0, 0, 1, 2, 3])>
3、tf.clip_by_norm
作用:根据范数进行裁剪。
a = tf.random.normal([2,2], mean=10) 输出: <tf.Tensor: id=892, shape=(2, 2), dtype=float32, numpy= array([[10.600117, 8.955517], [ 9.011888, 8.998526]], dtype=float32)> tf.norm(a) #算一下a的二范数 输出: <tf.Tensor: id=897, shape=(), dtype=float32, numpy=18.834845> aa = tf.clip_by_norm(a, 15) #以15作为其新的二范数进行放缩 #进行放缩是为了保持张量a的方向不变,而只改变数值大小。 输出: <tf.Tensor: id=929, shape=(2, 2), dtype=float32, numpy= array([[8.441894 , 7.13214 ], [7.177034 , 7.1663923]], dtype=float32)> tf.norm(aa) #算一下aa的二范数 输出: <tf.Tensor: id=934, shape=(), dtype=float32, numpy=14.999999>
clip_by_norm的原型是clip_by_global_norm。(梯度裁剪的最直接目的就是防止梯度爆制梯度的最大范式)
格式:tf.clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None)
其中,t_list指常输入梯度,clip_norm指裁剪率,use_norm指使用已经计算规约。$$t\_list[i] = \frac{{t\_list[i]*clip\_norm}}{{max(global\_norm,clip\_norm)}}$$
相关函数与API补充
摘自:https://cloud.tencent.com/developer/article/1489078
函数列表
abs(...)
: 计算张量的绝对值。accumulate_n(...)
: 返回张量列表的元素和。acos(...)
: 计算x元素的acos。acosh(...)
: 计算逆双曲余弦x元素。add(...)
: 返回x + y元素。add_n(...)
: 按元素顺序添加所有输入张量。angle(...)
: 返回复张量(或实张量)的元素参数。argmax(...)
: 返回一个张量在轴上的最大值的指标。 (deprecated arguments)argmin(...)
: 返回一个张量横轴方向上值最小的指标。(deprecated arguments)asin(...)
: 计算x元素的三角反正弦。asinh(...)
: 计算逆双曲正弦x元素。atan(...)
: 计算x元素的三角反切。atan2(...)
: 根据参数的符号计算arctan (y/x)。atanh(...)
: 计算x元素的逆双曲正切。bessel_i0(...)
: 计算x元素的贝塞尔i0函数。bessel_i0e(...)
: 计算x元素的贝塞尔i0e函数。bessel_i1(...)
: 计算x元素的贝塞尔i1函数。bessel_i1e(...)
: 计算x元素的贝塞尔i1e函数。betainc(...)
: 计算正则化不完全积分。bincount(...)
: 计算整数数组中每个值出现的次数。ceil(...)
: 返回元素方向上不小于x的最小整数。confusion_matrix(...)
: 根据预测和标签计算混淆矩阵。conj(...)
: 返回复数的复共轭。cos(...)
: 计算cosx元素。cosh(...)
: 计算x元素的双曲余弦。count_nonzero(...)
: 计算张量维上非零元素的个数。(deprecated arguments) (deprecated arguments)cumprod(...)
: 计算张量x沿轴的累积积。cumsum(...)
: 沿着轴计算张量x的累积和。digamma(...)
: 计算导数绝对值的对数divide(...)
: 计算Python风格的x除以y的除法。divide_no_nan(...)
: 计算一个不安全的除法,如果y为零,该除法返回0。equal(...)
: 返回(x == y)元素的真值。erf(...)
:计算x元素的高斯误差函数。erfc(...)
: 计算x元素的互补误差函数。exp(...)
: 计算x元素的指数。expm1(...)
: 计算x - 1元素的指数。floor(...)
: 返回不大于x的元素最大整数。floordiv(...)
: 除以x / y元素,四舍五入到最负的整数。floormod(...)
: 当x < 0 xor y < 0时,返回除法的元素剩余部分。greater(...)
: 返回元素(x > y)的真值。greater_equal(...)
: 返回元素的真值(x >= y)。igamma(...)
: 计算下正则化不完全函数P(a, x)。igammac(...)
: 计算上正则化不完全函数Q(a, x)。imag(...)
: 返回复张量(或实张量)的虚部。in_top_k(...)
: 表示目标是否在前K个预测中。invert_permutation(...)
: 计算张量的逆置换。is_finite(...)
: 返回x的哪些元素是有限的。is_inf(...)
: 返回x的哪些元素是Inf。is_nan(...)
: 返回x的哪些元素是NaN。is_non_decreasing(...)
: 如果x不递减,则返回True。is_strictly_increasing(...)
: 如果x严格递增,则返回True。l2_normalize(...)
: 使用L2范数沿着维度轴进行标准化。 (deprecated arguments)lbeta(...)
: 计算,沿最后一个维度减小。less(...)
: 返回(x < y)元素的真值。less_equal(...)
: 返回元素的真值(x <= y)。lgamma(...)
: 计算元素(x)绝对值的对数。log(...)
: 计算x元素的自然对数。log1p(...)
: 计算(1 + x)元素的自然对数。log_sigmoid(...)
: 计算x元素的log sigmoid。log_softmax(...)
: 计算对数softmax激活。(deprecated arguments)logical_and(...)
: 返回x和y元素的真值。logical_not(...)
: 返回NOT x element-wise的真值。logical_or(...)
: 返回x或y元素的真值。logical_xor(...)
: 逻辑异或函数。maximum(...)
: 返回x和y的最大值(即x > y ?x: y)元素方面。minimum(...)
: 返回x和y的最小值(即x < y ?x: y)元素方面。mod(...)
: 当x < 0 xor y < 0时,返回除法的元素剩余部分。multiply(...)
: 返回x * y元素。multiply_no_nan(...)
: 计算x和y的乘积,如果y是0,即使x是NaN或无穷大,返回0。negative(...)
: 计算数值负值元素。nextafter(...)
: 返回元素方向上x1的下一个可表示值。not_equal(...)
: 返回元素的真值(x != y)。polygamma(...)
: 计算多元函数。polyval(...)
: 计算多项式的元素值。pow(...)
: 计算一个值对另一个值的幂。real(...)
: 返回复张量(或实张量)的实部。reciprocal(...)
: 计算x元素的倒数。reduce_all(...)
: 计算元素跨张量维数的“逻辑和”。(deprecated arguments)reduce_any(...)
: 计算元素跨张量维数的“逻辑或”。(deprecated arguments)reduce_euclidean_norm(...)
: 计算元素跨张量维数的欧几里德范数。reduce_logsumexp(...)
: 计算log(sum(exp(一个张量的维度上的元素))。 (deprecated arguments)reduce_max(...)
: 计算张量维数中元素的最大值。(deprecated arguments)reduce_mean(...)
: 计算元素跨张量维数的平均值。reduce_min(...)
: 计算张量维数中元素的最小值。(deprecated arguments)reduce_prod(...)
: 计算元素跨张量维数的乘积。 (deprecated arguments)reduce_std(...)
: 计算元素跨张量维数的标准偏差。reduce_sum(...)
: 计算张量维数中元素的和。(deprecated arguments)reduce_variance(...)
: 计算元素跨张量维数的方差。rint(...)
: 返回最接近x的元素整数。round(...)
: 元素方面,将张量的值舍入到最近的整数。rsqrt(...)
: 计算x元素平方根的倒数。scalar_mul(...)
: 将标量乘以张量或索引切片对象。segment_max(...)
: 计算张量沿段的最大值。segment_mean(...)
: 沿张量的段计算平均值。segment_min(...)
: 计算张量沿段的最小值。segment_prod(...)
: 沿着张量的段计算乘积。segment_sum(...)
: 沿着张量的段计算和。sigmoid(...)
: 计算x元素的sigmoid。sign(...)
: 返回数字符号的元素指示。sin(...)
: 计算sin (x)元素。sinh(...)
: 计算x元素的双曲正弦。softmax(...)
: 计算softmax激活。(deprecated arguments)softplus(...)
: 计算softplus:log(exp(features) + 1)
.softsign(...)
: 计算softsign:features / (abs(features) + 1)
.sqrt(...)
: 计算x元素的平方根。square(...)
: 计算x元素的平方。squared_difference(...)
: 返回(x - y)(x - y)元素。subtract(...)
: 返回x - y元素。tan(...)
: 计算x元素的tan值。tanh(...)
: 计算x元素的双曲正切。top_k(...)
: 查找最后一个维度的k个最大项的值和索引。truediv(...)
: 使用Python 3的除法运算符语义来分割x / y元素。unsorted_segment_max(...)
: 计算张量沿段的最大值。unsorted_segment_mean(...)
: 沿张量的段计算平均值。unsorted_segment_min(...)
: 计算张量沿段的最小值。unsorted_segment_prod(...)
: 沿着张量的段计算乘积。unsorted_segment_sqrt_n(...)
: 计算张量沿段的和除以根号N。unsorted_segment_sum(...)
: 沿着张量的段计算和。xdivy(...)
: 如果x == 0返回0,否则返回x / y, elementwise。xlogy(...)
: 如果x == 0返回0,否则返回x * log(y), elementwise。zero_fraction(...)
:返回值中0的分数。zeta(...)
: 计算Hurwitz zeta函数。
重要的API
1、tf.floor
返回不大于x的元素最大整数。
tf.math.floor(
x,
name=None
)
参数:
- x: 张量。必须是以下类型之一:bfloat16、half、float32、float64。
- name: 操作的名称(可选)。
返回值:
- 与x类型相同的张量。
2、tf.log
计算x元素的自然对数。
tf.math.log(
x,
name=None
)
参数:
- x: 张量。必须是以下类型之一:bfloat16、half、float32、float64、complex64、complex128。
- name: 操作的名称(可选)。
返回值:
- 一个与x类型相同的张量。
3、tf.reduce_mean
计算元素跨张量维数的平均值。
tf.math.reduce_mean(
input_tensor,
axis=None,
keepdims=False,
name=None
)
沿着坐标轴给出的维数减少input_张量。除非keepdims为真,否则对于轴上的每一项,张量的秩都会减少1。如果keepdims为真,则使用长度1保留缩减后的维度。如果轴为空,则所有维数都被缩减,并返回一个只有一个元素的张量。
例如:
x = tf.constant([[1., 1.], [2., 2.]])
tf.reduce_mean(x) # 1.5
tf.reduce_mean(x, 0) # [1.5, 1.5]
tf.reduce_mean(x, 1) # [1., 2.]
参数:
input_tensor
: 要减少的张量。应该具有数值类型。axis
: 要缩小的尺寸。如果没有(默认值),则减少所有维度。必须在[-rank(input_张量),rank(input_张量)]范围内。- keepdims: 如果为真,则保留长度为1的缩减维度。
- name: 操作的名称(可选)。
返回值:
- 一个减少的张量。
请注意np.mean有一个dtype参数,可用于指定输出类型。默认情况下,这是dtype=float64。另一方面,tf.reduce_mean有一个来自input_张量的攻击类型推断,例如:
x = tf.constant([1, 0, 1, 0])
tf.reduce_mean(x) # 0
y = tf.constant([1., 0., 1., 0.])
tf.reduce_mean(y) # 0.5
4、tf.reduce_sum
计算张量维数中元素的和。
tf.math.reduce_sum(
input_tensor,
axis=None,
keepdims=None,
name=None,
reduction_indices=None,
keep_dims=None
)
警告:一些参数是不支持的:(keep_dims)。它们将在未来的版本中被删除。
更新说明:不推荐使用keep_dims,而是使用keepdims。
沿着坐标轴给出的维数减少input_张量。除非keepdims为真,否则对于轴上的每一项,张量的秩都会减少1。如果keepdims为真,则使用长度1保留缩减后的维度。如果轴为空,则所有维数都被缩减,并返回一个只有一个元素的张量。
例如:
x = tf.constant([[1, 1, 1], [1, 1, 1]])
tf.reduce_sum(x) # 6
tf.reduce_sum(x, 0) # [2, 2, 2]
tf.reduce_sum(x, 1) # [3, 3]
tf.reduce_sum(x, 1, keepdims=True) # [[3], [3]]
tf.reduce_sum(x, [0, 1]) # 6
x = tf.constant([[1, 2, 4], [8, 16, 32]])
a = tf.reduce_sum(x, -1) # [ 9 18 36]
参数:
input_tensor
:要减少的张量。应该具有数值类型。axis
:要缩小的尺寸。如果没有(默认值),则减少所有维度。必须在[-rank(input_张量),rank(input_张量)]范围内。- keepdims:如果为真,则保留长度为1的缩减维度。
- name:操作的名称(可选)。
- reduction_indices: axis的旧名称(已弃用)。
- keep_dims: keepdims的弃用别名。
返回值:
- 简化张量,与input_tensor具有相同的d型。
5、tf.add_n
按顺序对输入的张量进行求和。
tf.add_n(
inputs,
name=None
)
在添加之前将indexedslice对象转换为密集张量。
例如:
a = tf.constant([[3, 5], [4, 8]])
b = tf.constant([[1, 6], [2, 9]])
tf.math.add_n([a, b, a]) # [[7, 16], [10, 25]]
6、tf.math.top_k
tf.math.top_k(
input,
k=1,
sorted=True,
name=None
)
查找最后一个维度的k个最大项的值和索引。如果输入是一个向量(rank=1),找到向量中k个最大的元素,并将它们的值和索引作为向量输出。因此value [j]是输入的第j个最大的条目,它的索引是index [j]。矩阵(分别地。,计算每一行的前k个条目(resp)。沿着最后一个维度的向量)。因此,
values.shape = indices.shape = input.shape[:-1] + [k]
如果两个元素相等,则首先出现下标元素。
参数:
input
:一维或更高张量,最后维数至少为k。- k: 0-D int32张量。要沿着最后一个维度查找的顶部元素的数量(对于矩阵,沿着每一行查找)。
sorted
:如果为真,则得到的k个元素将按降序排列。- name:操作的可选名称。
返回值:
values
: 沿最后一个维度切片的k个最大元素。indices
: 输入的最后一个维度内的值的索引。
7、tf.math.argmax
返回一个张量在轴上的最大值的指标。
tf.math.argmax(
input,
axis=None,
name=None,
dimension=None,
output_type=tf.dtypes.int64
)
参数:
input:
一个张量。必须是以下类型之一:float32、float64、int32、uint8、int16、int8、complex64、int64、qint8、quint8、qint32、bfloat16、uint16、complex128、half、uint32、uint64。axis:
张量。必须是下列类型之一:int32、int64。int32或int64,必须在[-rank(输入),rank(输入)]范围内。描述输入张量的哪个轴要缩小。对于向量,使用axis = 0。- output_type:一个可选的tf.DType from: tf.int32, tf.int64。默认为tf.int64。
- name:操作的名称(可选)。
返回值:
- 一个输出t_type类型的张量。
<tf.Tensor: id=599, shape=(5,), dtype=int32, numpy=array([2, 1, 0, 3, 4], dtype=int32)>