TensorFlow2.0中Tensor的维度变换

在张量的操作中,维度变换是最重要的操作之一,为了满足不同场景的运算需求,可以任意切换数据的形式。现列举一些常用方法,以方便查看。


张量变形

在总数据量不变的情况下,将其变换为不同的组合形式,且将此数据平铺时排列顺序不改变

举个例子:

>>> import tensorflow as tf
>>> x = tf.range(24)	# 生成一组连续整数向量
>>> x = tf.reshape(x, [2, 3, 4])	# 改变x的视图,得到3D张量
>>> x
<tf.Tensor: id=11, shape=(2, 3, 4), dtype=int32, numpy=
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])>
>>> y = tf.reshape(x, [3, 2, 2, 2])    # 将x变形为4D张量
>>> y
<tf.Tensor: id=13, shape=(3, 2, 2, 2), dtype=int32, numpy=
array([[[[ 0,  1],
         [ 2,  3]],

        [[ 4,  5],
         [ 6,  7]]],


       [[[ 8,  9],
         [10, 11]],

        [[12, 13],
         [14, 15]]],


       [[[16, 17],
         [18, 19]],

        [[20, 21],
         [22, 23]]]])>

数据在创建时按着初始的维度顺序写入,改变张量的视图仅仅是改变了张量的理解方式,并不需要改变张量的存储顺序,张量只需要满足新视图的元素总量与存储区域大小相等即可

像上面: 2 3 4 = 3 2 2 2 2*3*4 = 3*2*2*2 ,总量没变;且张量的存储顺序始终没有改变,数据仍是按照 0 , 1 , 2 , . . . , 23 0,1,2,...,23 的顺序保存


增加维度

增加一个长度为 1 的维度相当于给原有的数据添加一个新维度的概念,因为维度长度为 1,所以数据并没有改变

举个例子:

>>> x = tf.random.normal([5, 5])	# 建立正态随机数据
>>> x
<tf.Tensor: id=19, shape=(5, 5), dtype=float32, numpy=
array([[ 0.4133979 ,  1.0672395 ,  2.5727544 , -0.0975351 ,  0.73670894],
       [-1.429659  , -0.3630027 , -0.11651681, -1.108655  ,  1.494843  ],
       [ 2.884822  , -0.3095457 , -0.6037164 ,  2.190964  , -0.38418463],
       [ 1.1569734 ,  0.1284009 , -0.24746007,  0.17708912,  0.4348358 ],
       [ 0.06045027, -0.9997665 , -0.43566772, -0.56748384, -1.4990594 ]],
      dtype=float32)>
>>> y = tf.expand_dims(x, axis=2)	# 在特定位置增加维度
>>> y
<tf.Tensor: id=21, shape=(5, 5, 1), dtype=float32, numpy=
array([[[ 0.4133979 ],
        [ 1.0672395 ],
        [ 2.5727544 ],
        [-0.0975351 ],
        [ 0.73670894]],

       [[-1.429659  ],
        [-0.3630027 ],
        [-0.11651681],
        [-1.108655  ],
        [ 1.494843  ]],

       [[ 2.884822  ],
        [-0.3095457 ],
        [-0.6037164 ],
        [ 2.190964  ],
        [-0.38418463]],

       [[ 1.1569734 ],
        [ 0.1284009 ],
        [-0.24746007],
        [ 0.17708912],
        [ 0.4348358 ]],

       [[ 0.06045027],
        [-0.9997665 ],
        [-0.43566772],
        [-0.56748384],
        [-1.4990594 ]]], dtype=float32)>

插入一个新维度后,数据的存储顺序并没有变化,只改变了数据的视图


删除维度

是增加维度的逆操作,只能删除长度为 1 的维度,也不会改变张量的存储

举个例子(接上一节数据):

>>> z = tf.squeeze(y, axis=2)
>>> z
<tf.Tensor: id=22, shape=(5, 5), dtype=float32, numpy=
array([[ 0.4133979 ,  1.0672395 ,  2.5727544 , -0.0975351 ,  0.73670894],
       [-1.429659  , -0.3630027 , -0.11651681, -1.108655  ,  1.494843  ],
       [ 2.884822  , -0.3095457 , -0.6037164 ,  2.190964  , -0.38418463],
       [ 1.1569734 ,  0.1284009 , -0.24746007,  0.17708912,  0.4348358 ],
       [ 0.06045027, -0.9997665 , -0.43566772, -0.56748384, -1.4990594 ]],
      dtype=float32)>

如果不指定维度参数 axis,那么它会默认删除所有长度为 1 的维度,例如:

>>> w = tf.squeeze(y)
>>> w
<tf.Tensor: id=23, shape=(5, 5), dtype=float32, numpy=
array([[ 0.4133979 ,  1.0672395 ,  2.5727544 , -0.0975351 ,  0.73670894],
       [-1.429659  , -0.3630027 , -0.11651681, -1.108655  ,  1.494843  ],
       [ 2.884822  , -0.3095457 , -0.6037164 ,  2.190964  , -0.38418463],
       [ 1.1569734 ,  0.1284009 , -0.24746007,  0.17708912,  0.4348358 ],
       [ 0.06045027, -0.9997665 , -0.43566772, -0.56748384, -1.4990594 ]],
      dtype=float32)>

可以看到效果一样


交换维度

前面的操作都不会影响张量的存储,而交换维度操作可以改变张量的存储顺序,同时也改变了张量的视图

举个例子:

>>> x = tf.random.normal([2, 3])
>>> x
<tf.Tensor: id=44, shape=(2, 3), dtype=float32, numpy=
array([[ 1.5357795 , -1.3758559 ,  0.6500945 ],
       [-0.6790089 ,  0.04826049,  0.8853354 ]], dtype=float32)>
>>> y = tf.transpose(x, perm=[1, 0])	# 将0维度与1维度互换
>>> y
<tf.Tensor: id=46, shape=(3, 2), dtype=float32, numpy=
array([[ 1.5357795 , -0.6790089 ],
       [-1.3758559 ,  0.04826049],
       [ 0.6500945 ,  0.8853354 ]], dtype=float32)>

完成维度交换后,张量的存储顺序已经改变,视图也随之改变,后续的所有操作必须基于新的存续顺序和视图进行

猜你喜欢

转载自blog.csdn.net/weixin_44613063/article/details/103828673