张量的基本操作就是合并,分裂,降维,升维,切片,索引等等
1、tf.concat(data,concat_dim)
data:[d1,d2..]是一个列表,把d1,d2..的数据按照concat_dim合并起来,不增加也不减少维度
合并的前提是:这些数据除了concat_dim这一个维度外,其他维度都要完全相等才可以。
例子:
t1=tf.ones([2,2,3])
t2=tf.zeros([2,3,3])
t3=tf.ones([2,1,3])
a=tf.concat([t1, t2,t3],1)
sess=tf.Session()
sess.run(a)
array([[[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.], [0., 0., 0.], [1., 1., 1.]], [[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.], [0., 0., 0.], [1., 1., 1.]]], dtype=float32)
最后张量的维度是[2,2+3+1,3]
a[:,0:2,3]就和t1是一样的
2、tf.squeeze(input, squeeze_dims=None, name=None)
这个是一个降维操作,当squeeze_dims=None时,会把所有大小是1的维度,删除。当squeeze_dims不为空时,删除相应axis对应的维度(但这个axis的大小必须为1,否则会报错。)
假设input的维度为[2,1,1,3,1],tf.squeeze(input) 会变成[2,3] 。
tf.squeeze(input,squeeze_dims=1) 会变成[2,1,3,1]
3、tf.expand_dims(input, axis=None, name=None, dim=None)
在axis位置,增加一个大小为1的维度
这个在做广播时非常有用,比如想让维度是[2,3,4,2]和[3,4]的张量相加,由于维度不匹配,没有办法广播。[3,4]应该扩充维度至[1,3,4,1]。
4、tf.slice(input_, begin, size, name=None)
begin, size这两个列表里的元素数应该与维度数一致
5、tf.stack(values, axis=0, name=’stack’)
将一系列维度完全相等的张量合并(这些需要合并的张量名称放在values这个列表里)并在axis处增加一个新的维度
比如 将五个维度大小为[3,4,4]的张量在axis=1上合并,最后的维度变成了[3,5,4,4]
和tf.concat的区分:tf.concat不改变rank,tf.stack会使rank加一
tf.concat需要axis之外的维度完全一样即可,axis维的大小可以不一样。而tf.stack更加严格。
注意:tf 没有numpy的hstack ,vstack
6、tf.unstack(tensor, axis=0)
将张量按照axis维分解为更低阶的。比如将一个大小为[3,4,5]的张量在axis=2上分解,z就变成了5个大小为[3,4]的张量。
7、tf.gather(params, indices, validate_indices=None, name=None)
tf.gather同样也是对张量索引,但和tf.slice相比,它可以不连续索引,但注意这个函数中的params必须是一维的张量。
# Scalar indices, 会降维
output[:, ..., :] = params[indices, :, ... :]
# Vector indices
output[i, :, ..., :] = params[indices[i], :, ... :]
# Higher rank indices,会升维
output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :]
摘自:https://blog.youkuaiyun.com/danlinxue/article/details/78005176
8、tf.gather_nd(params, indices, validate_indices=None, name=None)
indice每一个元素的rank应该小于等于params的rank.
indices.shape[-1]也就是rank。如果indices某个元素为[2,1,3],而params的大小是[4,4,4,4],那么它索引的就是params[2,1,3,:],得到一个一维张量。索引是按照维度顺序来的。
sess = tf.InteractiveSession()
t2 = [[7, 8, 9], [10, 11, 12],[0,0,0]]
indice=[[1],[2],[0]]#第一行,第二行,第0行;如果indice=[1,2],则说明取的是第一行第二列
tf.gather_nd(t2,indice).eval()
结果为:
array([[10, 11, 12], [ 0, 0, 0], [ 7, 8, 9]])
P.S.这个函数的特殊点在于: 如果输入是array,输出依然是array,而不会变成张量
9、tf.greater(x,y)
x,y是两个大小相同的张量,返回的也是和他们大小一样的布尔型张量,x对应位置的元素大于y时,对应位置的输出为True.
注意
本文是基于tensorflow1.9版本的文档进行的总结
tf中和张量相关的函数的输入除了张量之外,还接受np的array以及list,但是一旦经过这些函数作用之后,都会变成张量。
补充会话的一个小知识:
而张量只有在sess.run()之后才能得到它具体的值。不过可以用sess = tf.InteractiveSession(),tensor.eval()也可以获取张量的值,tf.InteractiveSession()默认自己就是用户要使用的会话,所以无需sess.run。它和with tf.Session() as sess:起到了相同的作用,不过with语句更好一些,它会执行完自动关闭这个会话,避免内存泄漏。参考博客:https://www.cnblogs.com/cvtoEyes/p/9035047.html
另外,在使用jupyter notebook时,在with tf.Session() as sess:之后的语句一定要print才能看到值,即print(sess.run()),print(tensor.eval())。单纯的sess.run(),tensor.eval()是无法看到结果的。而在其他情况下,比如,sess=tf.Session(),就不用print