定义:
单个实数,如1,2,3,维度(Dimension)为0,shape为[]
创建一个标量:
a=1.2 #python标准类型
aa=tf.constant(1.2) #tf标量
定义:
n个实数得有序集合,如[1,2,3],维度为1,shape为[n]
创建一个向量:
aa=tf.constant([1,2,3]) #通过传入list类型创建tf向量
定义:
m行n列实数的有序集合,如[[1,2],[3,4]],维度为2,shape[m,n]
创建一个矩阵:
aa=tf.constant([[1,2],[3,4]]) #通过传入2维list类型创建
定义:维度大于2的数组,每个维度也称为轴(Axis),TensorFlow把标量、向量、矩阵也统称为张量
创建一个张量:
aa=tf.constant([[[1,2],[3,4]],[[1,2],[3,4]]]) #通过传入多维list类型创建
a=tf.constant('hello')
a=tf.constant(True)
TensorFlow的数值类型都有python的基本类型与之对应,但是python的基本类型并不与tf类型相同(特别是tf的布尔类型与python的布尔类型),二者无法隐式转换,不过可以通过tf.constant()
显式将python的基本类型转换为tf类型
输出一tf类型变量,可得
<tf.Tensor:id=,shape=,dtype=,numpy=>
其中,id是一个整数,标识TensorFlow中内部索引号;shape是一个集合,表示张量的形状,每个元素表示对应轴的长度;dtype表示张量的精度;numpy表示当使用张量名.numpy()
方法时返回的numpy对象,方便观察张量中的具体数值。
可以通过张量名.属性名
的方法查看具体某一个属性
a=tf.constant([1,2])
a.shape
在创建张量时,可以使用dtype指定张量的保存精度:
tf.constant(12345,dtype=tf.int16)
常用的精度有:tf.int16 , tf.int32 , tf.int64 , tf.float16 , tf.float32 , tf.float64(即tf.double)
一般使用int32和float32即可满足运算需求,对精度要求比较高时(如强化学习)可选择64精度得类型
tf类型之间可以使用,tf.cast()
进行类型转换
a=tf.constant([True,False])
tf.cast(a.tf.int32) #将a的类型转换为int32
布尔类型会被转成1/0,将数值类型转换为布尔类型时,将非0数字视为True
tensorflow可以通过tf.convert_to_tensor
与tf.constant()
方法将Numpy Array与python List转化为tf张量
a=tf.convert_to_tensor([1,2])
b=tf.constant()
a=tf.zeros(shape) #创建全0张量
b=tf.ones(shape) #创建全1张量
#shape为list类型,元素个数即维度个数,元素大小即维度长度,为[]时表示创建标量
a=tf.zeros_like(a) #创建一个与a的shape相同的全0张量
b=tf.ones_like(b)#创建一个与shape相同的全1张量
a=tf.fill(shape,value) #创建一个形为shape,值全都为value的张量
a=tf.random.normal(shape,mean=0.0,stddev=1.0) #创建正态分布张量
b=tf.random.uniform(shape,minval=0,maxval=None,dtype=tf.float32) #创建均匀分布张量
a=tf.range(limit,delta=1) #创建一个在[0,limit)之间,步长为delta的整形序列,不包括limit本身
TensorFlow可将张量近似理解为多维数据,可以通过a[i][j]..
的方式对张量中的元素进行访问,对于shape=[4,3,2,1]的张量a来说,a[0]的shape=[3,2,1]
访问第一维度为0,第二维度为1,第三维度为0,第四维度为0的元素可用a[0][1][0][0]
tf还支持[i,j,…,k]的索引方法
即
a[0,1,0,0]
与上述方法等价
tf支持切片操作,与python切片相同,a[start:end:step]
可以左闭右开的、按照一定步长的提取一段数据,start,end,step可全部省略,全部省略时书写为a[::]
或者a[:]
表示选取该维度上的全部数据,start默认为0,end默认为张量该维度长度,step默认是1
例如:
a[0,::] #第一维度只取0,第二维度全都要
b[:,0:28:2,:] #标识第一维度都取,第二维度取[0,28),步长为2,第三维度都取
切片的自动推断:用...
代替多个..,:,:,;,..
,具体为:当切片方式出现...
符号时,符号左边作用于第一个维度,符号右边作用于最后一个维度,中间的纬度都按[:]
的规则选取,即全部都取
例如
#假设a.shape=(4,3,2,3)
a[0:2,...,1:]#标识第一个维度取0和1,第二个维度与第三个维度都取,最后一个维度取1和2
a=tf.reshape(x,new_shape)
可改变张量x的维度数与维度大小,将改变后的结果返回。
tf张量是逻辑上的多维数组,从存储上讲,它的元素是线性存储于一段连续的内存上的数据,即物理意义上,张量的元素线性有序,所以reshape会改变张量的的shape,但是张量的储存结构与各维度的乘积不会变。
例如:
x=tf.range(96)
x=tf.reshape(x,[2,4,4,-1])#-1为自动推断,因为维度长度积不变,所以这里可自动推断出第四个维度为3
x.ndim #返回x的维度数 4
x.shape #返回x的shape [2,4,4,3]
增删维度,都是操作长度为1的维度,从而保证维度长度总积不变。
x=tf.expand_dims(x,axis) #在x的axis轴(从0开始)前插入一个新维度
x=tf.squeeze(x,axis)#删除x的axis轴(从0开始)维度
x=tf.squeeze(x) #不指定轴,默认删除所有长度为1的维度
x=tf.transpose(x,perm) #交换x的维度,perm内是新维度顺序List,列表内的元素值是原维度索引号,元素顺序即新顺序
例如交换x的第二和第三维度
x=tf.transpose(x,[0,2,1,3])
注意tf.transpose()
并非简单的交换维度长度,而是会改变张量的储存顺序,保证旧shape的x[a][b]
与新维度的x[b][a]
是同一个元素
x=tf.tile(x,multiples) # multiple接受一个list,list中的下标对应元素下标,list中元素数值大小表示倍数
tf.tile()
的复制是指某一维度的内容再复制一边,增加的是维度长度,而非数值本身
例如
b=tf.constant([1,2])
b=tf.expand_dims(b,axis=o)
b.shape #shape=(1,2)
b=tf.tile(b,multiples=[2,1]) #b第一个维度复制1次,第二个纬度不复制
b.shape #shape=(2,2)
BroadCasting也叫广播机制或者自动扩展机制,它在逻辑上扩展张量数据的形状,但是只在需要时才去改变实际存储,比tf.tile
更高效
当进行张量的按元素运算时,如+ - * / 如果两张量形状不同,则会通过Broadcasting隐式扩充至一个公共shape进行运算
扩充扩充规则:
x=tf.broadcast_to(x,shape)
显式的将一个现有张量扩充至新的维度a=tf.random.normal([2,32,32,1])
b=tf.random.normal([32,32])
a+b #扩充至公共shape=(2,32,32,32)
也可以显式转换
a=tf.boradcast_to(a,[2,32,32,32])
b=tf.boradcast_to(b,[2,32,32,32])
张量的合并有拼接与堆叠两种方式,拼接不会产生新的维度,只是在已有的维度上扩充,堆叠会产生新的维度。
可以用x=tf.concat(tensors,axis)
实现拼接,tensors是一个list对象,保存需要拼接的张量,axis指需要拼接的维度,拼接的要求是非拼接维度必须一致
a=tf.random.normal([4,35,8])
b=tf.random.normaal([6,35,8])
c=tf.concat([a,b],axis=0) #合并a和b
c.shape #(10,35,8)
堆叠是将数据在新的维度上合并,所以会创建新的维度,使用tf.stack(tensors,axis)
tensors同样是指需要堆叠的张量列表,堆叠所创建的维度将会插入到axis所指定的维度之前,堆叠的条件也是非堆叠维度长度一致
a=tf.random.normal([35,8])
b=tf.random.normal([35,8])
c=tf.stack([a,b],axis=0)
c.shape #(2,35,8)
分割可以将一个张量拆分成多个张量,返回序列类型。
tensors=tf.split(x,axis,num_or_size_splits)
x是待分割张量
axis是分割的维度索引号
num_or_size_splits如果接受的是单个数值,则表示平均分割为几份,如果接受的是list对象,则每个元素表示每份的长度,如果[2,4,2,2]表示分4份,每份长度分别为2,4,2,2。
为了让不同shape的张量进行运算,需要将其转化成相同的shape,如果不想破坏原有的结构,可以选择用0元素扩充(padding)
x=tf.pad(x,paddings)
可实现上述需求,x为待填充张量,paddings一个两层嵌套的list,最外层list用于决定对哪个维度进行操作,最里层list有两个元素,第一个元素表示左边填充几个单元,第二个元素表示右边填充几个单元。
例如
x=tf.pad(x,[[0,0],[1,2]])
#即为,张量x的第一个维度不填充,第二个纬度,在做左边天一个0,右边填2个0
c=tf.add(a,b) #按元素加
c=a+b #也可以直接用操作符
c=tf.subtract(a,b) #按元素减
c=a-b
c=tf.multiply(a,b) #按元素乘
c=a*b
c=tf.divide(a,b) #按元素除
c=a/b
c=a//b #按元素整除
c=a%b #按元素求模
c=tf.pow(x,a) #按元素乘方,a为指数,a小于1则为开根号
c=x**a
x=tf.square(x) #平方
x=tf.sqrt(x) #平方根
c=tf.pow(a,x) #指数运算,a为底数
c=a**x
c=tf.math.log(x) #e为底的对数运算,即lnx
c=tf.matmul(a,b)
c=a@b
当维度等于2时,张量相乘即矩阵相乘;维度当张量维度大于2时,将最后两个维度视作矩阵,其他维度视为batch维度,对最后两个维度进行矩阵乘法运算。
范数是表示向量“长度”的一种度量方法,在神经网络中,常用来表示张量的权值大小,梯度大小等。
p范数,即为所有元素的绝对值的p次方之和,再开p次根
即
∣ ∣ x ∣ ∣ p = ( ∑ ∣ x i ∣ p ) 1 / p ||x||_p = (\sum{|x_i|^p})^{1/p} ∣∣x∣∣p=(∑∣xi∣p)1/p
故
1范数为向量各元素绝对值之和
2范数为向量各元素平方和再开根号,即距原点的欧式距离
特殊的,无穷范数为向量中所有元素绝对值的最大值。
对于矩阵和张量,也可以进行范数运算,其结果等价于将矩阵、张量打平成向量后的计算结果
tensorflow中,可以使用a=tf.norm(x,ord)
来计算张量x的ord范数,ord可填1,2,np.inf,分别对应1范数,2范数,无穷范数
tf.reduce_max(x,axis) #计算x张量在axis维度上的最大值
tf.reduce_min(x,axis) #计算x张量在axis维度上的最小值
tf.reduce_mean(x,axis) #计算x张量在axis维度上的平均值
tf.reduce_sum(x,axis)#计算x张量在axis上的和
tf.reduce_*
返回一个张量,其统计哪个维度,哪个维度大小变为1,其他维度大小不变,即将其他维度视为批
当tf.reduce_*
不指定axis参数时,则返回一个标量,其值为全局的统计值
比较两个张量是否相等,可以用tf.equal(a,b)
或tf.math,equal(a,b)
,该方法令张量按元素比较,返回true/false张量,返回结果中的true说明a、b中对应位置的元素值相等,false则反之
例如计算分类问题的准确度:
out=tf.equal(pred,y)
out=tf.cast(out,dtype=tf.float32)
correct=tf.reduce_sum(out) #correct即预测正确的数目,除以总数即为准确度
常用比较函数有
tf.math.greater(a,b) #a>b
tf.math.less(a,b) #a=b
tf.math.less_equal(a,b) #a<=b
tf.math.not_equal(a,b) #a!=b
tf.math.is_nan(a,b) # a=nan
它们用法与equal相同,返回true/false矩阵
x=tf.maximum(x,a) #将张量x中大于a的元素替换成a
x=tf.minimum(x,b) #将张量x中小于b的元素替换成b
x=tf.clip_by_value(x,a,b) #合并上述操作,使数据在[a,b]之间
x=tf.gather(x,indices,axis=0)
类似切片,根据indices和axis对张量x进行采样,indices接受一个list对象,list中每个元素值代表下标,axis指定indices中的下标作用的维度
例如
x=tf.gather(x,[0,2,4,6],axis=1) #返回张量,取x张量中,第二维度为0,2,4,6的数据
tf.gather_nd
可以实现对坐标点的采样
x=tf.gather_nd(x,[[1,2,3],[4,5,6]])#即取出x[1,2,3]与x[4,5,6]堆叠为张量返回
tf.boolean_mask(x,mask,axis)
通过掩码进行采样,mask是true/false向量或张量,当mask是向量时,需要指定axis,其结果类似tf.gather,取axis维度里,mask向量中true元素对应位置的数据堆叠成张量;当mask为张量时,类似tf.gather_nd,对mask中true元素对应坐标点采样。
tf.boolean_mask(x,mask=[True,False],axis=0) #x[0][0]
tf.boolean_mask(x,mask=[[True,False],[False,True]]) #x[0][0]与x[1][1]堆叠
通过tf.where(cond,a,b)
操作可以根据cond条件张量的真假,从a或b中读取数据。
其中cond是true/false张量,cond中true元素对应位置取a的对应元素,false元素对应位置,取b的对应元素,当不指定a和b时,tf.where会返回cond张量中所有true元素得索引坐标。
x=tf.where(tf.greater(a,b),a,b) #若a[...]大于b[...]取a[...],若b[...]更大,则取b[...]
《TensorFlow 2.0深度学习算法实战教材》