当前位置: 代码迷 >> 综合 >> Tensorflow之维度理解[ shape、reshape]
  详细解决方案

Tensorflow之维度理解[ shape、reshape]

热度:96   发布时间:2023-12-15 05:46:11.0

文章目录

  • 一、shape与reshape
    • 1. shape
    • 2. reshape
  • 二、Tensor理解
    • 1. 一维张量
    • 2. 二维张量
    • 3. 三维张量
    • 4. 超过三维的多维张量
  • 三、API理解
    • 1. 关于reduce_xxx的维度问题
      • tf.reduce_mean
  • 参考


一、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