Tensorflow之维度理解[ shape、reshape]


一、shape与reshape

1. shape

举个例子来说:

import tensorflow as tf
a = tf.constant([[1.,2.,3.],[4.,5.,6.],[7.,8.,9.]],shape = [3,3])
b = tf.initialize_all_variables()
 
with tf.Session() as sess:
    sess.run(b)
    print(sess.run(a))

运行结果如下:

[[ 1.  2.  3.]
 [ 4.  5.  6.]
 [ 7.  8.  9.]]

可以理解为:

shape[3, 3]的第一个“3”表示:“在第一个中括号以内存在3组元素”,

同理,则shape[3, 3]的第二个“3”表示:“在第二个中括号以内存在3组元素”。

由此我们可以知道[5, 5, 1, 32]这个结构:

  • 是一个四维张量
  • 第一个维度:由5个元素组成
  • 5个元素均是由5个子级元素组成
  • 5个子级元素中只有1个次级元素
  • 一个次级元素中包含了32个子元素

2. reshape

tf.reshape(tensor, shape, name=None)

函数的作用是将tensor变换为参数shape的形式。其中shape为一个列表形式,特殊的一点是列表中可以存在-1

-1代表的含义是不用我们自己指定这一维的大小,函数会自动计算,但列表中只能存在一个-1.

shape可以看着是reshape变换后的矩阵大小,先不管-1的那一个维度,先看其他维度,然后用原矩阵的总元素个数除以确定的维度,就能得到-1维度的值。

下面是例子,自行理解。


# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]
# tensor 't' has shape [9]
reshape(t, [3, 3]) ==> [[1, 2, 3],
                        [4, 5, 6],
                        [7, 8, 9]]
 
# tensor 't' is [[[1, 1], [2, 2]],
#                [[3, 3], [4, 4]]]
# tensor 't' has shape [2, 2, 2]
reshape(t, [2, 4]) ==> [[1, 1, 2, 2],
                        [3, 3, 4, 4]]
 
# tensor 't' is [[[1, 1, 1],
#                 [2, 2, 2]],
#                [[3, 3, 3],
#                 [4, 4, 4]],
#                [[5, 5, 5],
#                 [6, 6, 6]]]
# tensor 't' has shape [3, 2, 3]
# pass '[-1]' to flatten 't'
reshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]
 
# -1 can also be used to infer the shape
 
# -1 is inferred to be 9:
reshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 2:
reshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
                         [4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 3:
reshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1],
                              [2, 2, 2],
                              [3, 3, 3]],
                             [[4, 4, 4],
                              [5, 5, 5],
                              [6, 6, 6]]]
 
# tensor 't' is [7]
# shape `[]` reshapes to a scalar
reshape(t, []) ==> 7

二、Tensor理解

1. 一维张量

tf.constant([1.0 , 2.0 , 3.0])
表示:生成一个一维张量(向量),shape是13

2. 二维张量

x = tf.constant([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]])
x实际上就是:
[ [ 1. 2. 3.]
[ 4. 5. 6.]
[ 7. 8. 9.] ]
shape是(3,3),第一对[ ]中有3个元素,所以第一维是3,3个元素分别是:[ 1. 2. 3.][ 4. 5. 6.][ 7. 8. 9.]
这三维中的每一维,也就是第二个[ ]中也有3个元素,所以第二维也是3。因此shape为(3,3)
这种二维的我们可以理解为,是一个33列矩阵

3. 三维张量

x = tf.constant([ [ [1., 1.], [2., 2.]], [[3., 3.], [4., 4.] ] ])
x实际上是:
[
[ [ 1. 1.]
[ 2. 2.] ]

[ [ 3. 3.]
[ 4. 4.] ]
]
shape(2,2,2)
这种三维的我们也可以理解为是222列的矩阵

4. 超过三维的多维张量

举个例子理解一下:
比如将格子划分成了7x7的大小,每个格子产生2个框,每个框产生4个坐标(x,y,h,w)

所以在坐标那里的代码维度假设考虑为向量,那么向量shape就应该是(7,7,2,4)

第一个[ ]中会有7[ ]作为第一维度的向量[ [ ] , [ ] , [ ] , [ ] , [ ] , [ ] , [ ] ]
如果取第一维度为0的元素,那么实际上就可以理解为,取走所有第一行的网格格子(7个网格)产生的方框(7x2个方框),每个方框4个坐标,也就是取走了7x2x4个元素

然后每一个[ ]中又有7个[ ],再有2个[ ],最后再有4个数字,其实就是一个套一个。

代码中经常取的是[:,:,:,:,0] ,意味着,取走最后一维向量中的第1个元素,最后一维是坐标(x,y,h,w),取走第一个元素,也就意味着取走所有框7x7x2个框的x元素。

其实也就是,你取某一行,那就是取走所有这一行的信息,你取某一列,也就取走所有关于这一列的信息,你取某一个坐标,那就是取走所有关于这个坐标的信息。

三、API理解

1. 关于reduce_xxx的维度问题

对于ktensor

tf.reduce_xxx(x, axis=k-1)的结果:是对最里面一维所有元素进行求和

tf.reduce_xxx(x, axis=k-2):是对倒数第二层里的向量对应的元素进行求和

tf.reduce_xxx(x, axis=k-3):把倒数第三层的每个向量对应元素相加

…………

tf.reduce_mean

tf.reduce_mean是 计算Tensor各个维度元素的均值。这个方法根据输入参数axis的维度上减少输入input_tensor的维度。
该API的结构如下:

reduce_mean(
    input_tensor,
    axis=None,
    keep_dims=False,
    name=None,
    reduction_indices=None
)

举个二维的例子说明一下:

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.]

x是二维数组[[1.0,1.0],[2.0, 2.0]]

  • axis参数取默认值时,计算整个数组的均值:(1.+1.+2.+2.)/4=1.5
  • 当axis取0,即:k-2,对倒数第二层里的向量对应的元素进行求和取均值,那么在这意味着对列取均值[1.5, 1.5]
  • 当axis取1,即:k-1,对最里面一维所有元素进行求和取均值,那么在这就意味着对行取均值[1.0, 2.0]

再举一个三维的例子

推测一下,前面二维的经过处理都变成一维的,也就是经历了一次降维,那么现在三维的或许应该变成二维。但现在多了一维,应该从哪个方向做计算呢?

sess = tf.Session()
x = tf.constant([[[1., 1.], [2., 2.]], [[3., 3.], [4., 4.]]]) # 2*2*2
print(sess.run(x))
#[[[ 1.  1.]
#  [ 2.  2.]]
#
# [[ 3.  3.]
#  [ 4.  4.]]]
print(sess.run(tf.reduce_mean(x)))
print(sess.run(tf.reduce_mean(x, 0)))#[[2 2][3 3]]
print(sess.run(tf.reduce_mean(x, 1)))#[[1.5 1.5][3.5 3.5]]
print(sess.run(tf.reduce_mean(x, 2)))#[[1. 2.][3. 4.]]
  • axis参数取默认值时,依然计算整个数组的均值:(float)(1+2+3+4+1+2+3+4)/8=2.5
  • axis0,计算方式是:
    [[(1+3)/2, (1+3)/2],
    [(2+4)/2, (2+4)/2]]
  • axis1,计算方式是:
    [[(1+2)/2, (1+2)/2],
    [(3+4)/2, (3+4)/2]]
  • axis2,计算方式是:
    [[(1+1)/2, (2+2)/2],
    [(3+3)/2, (4+4)/2]]

参考

  1. https://blog.csdn.net/weixin_43384257/article/details/102290159
  2. https://blog.csdn.net/kakangel/article/details/88641251
  3. https://blog.csdn.net/lipku/article/details/103169833
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值