这个方法是numpy的方法。不再赘述,需要说明的是,reshape虽然应用起来非常灵活。但是会造成一些问题。比如说,一个28乘以14的图片,你一不小心,把长宽的参数给搞反了,那么很容易就出bug。
而且,如果你真的想把长宽属性给颠倒一下,那么你就总得记住我哪个地方换了,那个地方没换,这样也很麻烦
这个意思是:转置。这个单词其实本意是“交换,转换”。但实际上,转置也就意味着交换(英文真奇妙)
假设我这个长宽像素信息是按照[高度,宽度]存储的,我对这个矩阵转置,自然而然的就变成了[宽度,长度]。
在tensorFlow当中,tf.transpose的相关参数如下:
tf.transpose(
a,
perm=None,
name='transpose',
conjugate=False
) # 置换 a,根据 perm 重新排列尺寸
Squeeze的英文含义:挤压。所以,从名称就可以知道,这是用来缩小维度的。
而Expand_dims从名字就可以看出,是用来升维的。
我们还以之前的,4个班级,每个班级35个学生,每个学生修8门课的示例为例:
关于squeeze,你可以像Expand_dims那样指定要操作的轴。除此之外呢,它还有一个特点,你若啥都不指定,那么会默认把所有的shape=1的维度给去掉(即:In[115]的部分)。
在Numpy当中就有Broadcasting,tensorFlow无缝继承了Numpy的Broadcasting,而且还进行了拓展了。总的来说,这是一种在不更新数据本身的情况下,对维度进行扩展的方法。
在掌握Broadcasting的时候务必要知道以下要点:
首先,只适用于加减法。这是一个重要前提。
其次,知道如下步骤:
step1:首先,把两个数组,进行“右对齐”。比如说a.shape = [1,2,3,4], b.shape=[3,4]那么就首先把右侧的[3,4]部分对齐。
step2:如果二者维度相同,那么小的向大的靠拢,比如说:a.shape=[4,32,14,14],b.shape=[14,14]。
那么,右对齐之后,(a+b).shape = [4,32,14,14]。这也算是一个要点:以短的为中心,必要的情况下,短的那个array,不断往前添1维。
step3:不过,对于step2这种情况下,也就只是1维的地方可以扩展。step2的时候,b的shape扩展为[1,1,14,14],正是因为前面两个是1,所以才能扩展。如果a.shape=[4,32,14,14],b.shape=[2,32,14,14]。那么不可以进行Broadcasting,因为b的第一维是2.
有一幅图,很好的反映了Broadcasting:
首先,Broadcasting不会额外占用内存,所以,更加的节省空间
其次,现实确实需要这种需求,比如说,我有一组数据[classes, students, courses] = [4,32,8]。存在一个数组a当中代表一共4个班级,每个班级32个学生,每个学生修8门课程。我现在要把每个学生的每个课程的分数都加五分。
那么我大可以写[4,32,8] +[5.0](当然了,后面这个5.0是个8列的数据)
In [1]: import tensorflow as tf
In [2]: import numpy as np
In [3]: x = tf.random.normal([4,32,32,3])
In [4]: (x+tf.random.normal([3])).shape
Out[4]: TensorShape([4, 32, 32, 3])
In [5]: (x+tf.random.normal([32,32,1])).shape
Out[5]: TensorShape([4, 32, 32, 3])
In [6]: (x+tf.random.normal([4,1,1,1])).shape
Out[6]: TensorShape([4, 32, 32, 3])
In [7]: x.shape
Out[7]: TensorShape([4, 32, 32, 3])
In [8]: (x+tf.random.normal([4,1,1,1])).shape
Out[8]: TensorShape([4, 32, 32, 3])
In [9]: b = tf.broadcast_to(tf.random.normal([4,1,1,1]),[4,32,32,3])
# 把shape为[4,1,1,1]的broadcast称为[4,32,32,3],如果不能Broadcasting,那么会报错
In [10]: b.shape
Out[10]: TensorShape([4, 32, 32, 3])