TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】

tensorFlow维度变换可分为两个级别,一个是view级,一个是content级。

  • view级维度变换:不改变数据的存储关系,比如[3,28,28,3]变换维度为[3,784,3]之后,数据本身并没有改变,属于哪一行哪一列的元素还是可以确定,可以原模原样的恢复为[3,28,28,3]。
  • content级维度变换:会改变数据的存储关系。content有“目录”的意思,即索引关系,通过[3,28,28,3]这样的索引号能够找到一个元素。当content被改变时,意味着元素之间的索引关系变了。例如[3,28,28,3]变换为[3,3,28,28]后,相当于把最后面的维度数据整个提到了前面。

基本的维度变换包含了改变视图 reshape,插入新维度 expand_dims,删除维 squeeze,交换维度 transpose,复制数据 tile 等。

一、张量的存储和视图(View)概念

张量的视图就是我们理解张量的方式,比如shape 为[2,4,4,3]的张量A,我们从逻辑上可以理解为2 张图片,每张图片4 行4 列,每个位置有RGB 3 个通道的数据;

张量的存储体现在张量在内存上保存为一段连续的内存区域,对于同样的存储,我们可以有不同的理解方式,比如上述A,我们可以在不改变张量的存储下,将张量A 理解为2 个样本,每个样本的特征为长度48 的向量。

这就是存储与视图的关系。

在存储数据时,内存并不支持这个维度层级概念,只能以平铺方式按序写入内存,因此这种层级关系需要人为管理,也就是说,每个张量的存储顺序需要人为跟踪。
为了方便表达,我们把张量shape 中相对靠左侧的维度叫做大维度,shape 中相对靠右侧的维度叫做小维度,比如[2,4,4,3]的张量中,图片数量维度与通道数量相比,图片数量叫做大维度,通道数叫做小维度。
例如:在优先写入小维度的设定下,张量 [2,4,4,3] 的内存布局为
在这里插入图片描述
为了能够正确恢复出数据,必须保证张量的存储顺序与新视图的维度顺序一致,
例如根据图片数量-行-列-通道初始视图保存的张量,按照图片数量-行-列-通道( − ℎ −w − )的顺序可以获得合法数据。

如果按着图片数量-像素-通道(b − h ∗ w − c)的方式恢复视图,也能得到合法的数据。但是如果按着图片数量-通道-像素( − c − h ∗ w)的方式恢复数据,由于内存布局是按着图片数量-行-列-通道的顺序,视图维度与存储维度顺序相悖,提取的数据将是错乱的。

二、Reshape 操作

改变视图是神经网络中非常常见的操作,可以通过串联多个Reshape 操作来实现复杂
逻辑,
但是在通过Reshape 改变视图时,必须始终记住张量的存储顺序,新视图的维度顺序不能与存储顺序相悖,否则需要通过交换维度操作将存储顺序同步过来。
举个例子,对于shape 为[4,32,32,3]的图片数据,通过Reshape 操作将shape 调整为[4,1024,3],此时视图的维度顺序为 − − ,张量的存储顺序为 [, ℎ, w, ]。

在 TensorFlow 中,可以通过张量的ndim 和shape 成员属性获得张量的维度数和形
状:
在这里插入图片描述
通过 tf.reshape(x,new_shape),可以将张量的视图任意的合法改变
TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第1张图片
当不知道填入什么数字合适时,可以选用 -1 来替代,由python通过其他值进行推算得知具体值
例如将shape为 [b,3,4]的输入数据转为 shape为 [b,3*4] 的数据:
TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第2张图片

三、增删维度

1、增加维度

增加一个长度为1 的维度相当于给原有的数据增加一个新维度的概念,维度长度为1,故数据并不需要改变,仅仅是改变数据的理解方式,因此它其实可以理解为改变视图的一种特殊方式

比如:,一张28x28 灰度图片的数据保存为 shape 为[28,28]的张量,在末尾给张量增加一新维度,定义为通道数维度,此时张量的shape 变为[28,28,1]:

通过tf.expand_dims(x, axis)可在指定的axis 轴前可以插入一个新的维度:
TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第3张图片
可以看到插入一个新维度后,数据的存储顺序并没有改变,仅仅改变了数据的视图。
TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第4张图片
需要注意的是,tf.expand_dims 的axis 为正时,表示在当前维度之前插入一个新维度;为负时,表示当前维度之后插入一个新的维度。以[, ℎ, w, ]张量为例,不同axis 参数的实际插入位置如图所示:
TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第5张图片

2、删除维度

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

可以通过tf.squeeze(x, axis)函数,axis 参数为待删除的维度的索引号

在这里插入图片描述
如果不指定维度参数 axis,即 tf.squeeze(x),那么他会默认删除所有长度为1的维度

四、交换维度

在实现算法逻辑时,在保持维度顺序不变的条件下,仅仅改变张量的理解方式是不够的,有时需要直接调整的存储顺序,即交换维度(Transpose)。通过交换维度,改变了张量的存储顺序,同时也改变了张量的视图。

我们以[, ℎ, w, ]转换到[, , ℎ, w]为例,介绍如何使用tf.transpose(x, perm)函数完成维度交换操作,其中 perm 表示新维度的顺序 List。

TensorFlow2-基础(五):Tensor的维度变换【改变:reshape(view级别)、transpose(content级别)】【增加(expand_dims)、删除(squeeze)】_第6张图片
通过tf.transpose完成维度交换后,张量的存储顺序已经改变,视图也随之改变,后续的所有操作必须基于新的存续顺序进行

五、数据复制

tf.tile(x, multiples)函数完成数据在指定维度上的复制操作,multiples 分别指定了每个维度上面的复制倍数,对应位置为1 表明不复制,为2 表明新长度为原来的长度的2 倍,即数据复制一份,以此类推。
在这里插入图片描述




参考资料:
TensorFlow:维度变换
TensorFlow基础(7.维度变换)
【tensorFlow】维度变换
tensorflow(八):维度变换

你可能感兴趣的:(#,TensorFlow,TensorFlow2,维度变换,Reshape)