【TensorFlow2.0】(4) 维度变换、广播

各位同学好,今天我和大家分享一下TensorFlow2.0中有关数学计算的相关操作,主要内容有: 

(1) 改变维度:reshape();(2) 维度转置:transpose();(3) 增加维度:expand_dims();(4) 减少维度:squeeze();(5) 广播:broadcasting_to()

那我们开始吧。


1. 维度变换

假设一张图像有四个维度: [ batch, row, width, channel ]

batch:理解为几张图像

row:图像的行

width:图像的列

channel:通道

图像维度的表示形式也有如下几种:

[b,28,28]   图像b有28行28列

[b,28*28]   不考虑行列信息,考虑整个图像的像素

[b,2,14*28]   将图片分成上下两个部分

[b,28,28,1]   增加一个channel通道,和第一种一样,只是增加一个通道

都没有改变原图像的数据点个数,只是换了一种理解方式


1.1 重新塑造维度

改变维度: tf.reshape(tensor, shape)

根据指定的shape改变tensor的维度。不会改变原tensor的维度,需要有变量去接收。改变图像的shape时,需要保证改变后的图像和原图像的数据点个数相同

# 创建一个四维正态分布tensor
a = tf.random.normal([4,28,28,3])
# 查看形状
a.shape 
# 按指定shape改变原形状
tf.reshape(a,[4,28*28,3]).shape
# 如果不想计算28*28可写成-1,-1这一项自动计算
tf.reshape(a,[4,-1,3]).shape 

对创建的四维tensor改变形状,指定形状为 [4,28*28,3],这三个轴可以理解为 [图像, 像素, 通道],该变换,抹除了行和列的概念,变成784个像素去考虑,这时图像失去了二维信息

如果不想计算28*28的值,还可以使用 '-1' 代替计算,函数碰到-1会自动计算两个数的乘积,注意,一个函数中只能出现一个-1,不然计算机不知道怎么去分配。

将原tensor从[4, 28, 28, 3],转换到 [4, 28*28*3]抹除行和列的概念,同时抹除通道的概念。将这种shape理解为[图像, 数据点],即有4幅图像,每幅图像有2352个数据点。若不想计算28*28*3,可以用-1代替计算。

a = tf.random.normal([4,28,28,3])
a.shape # 查看形状
# 抹除通道概念。理解为4个图像,每个图象有2352个数据点
tf.reshape(a,[4,28*28*3]).shape
# 用-1代替计算
tf.reshape(a,[4,-1]).shape


1.2 重新排列维度

转置: tf.transpose(tensor, perm)

tensor代表需要转置的变量,perm代表重新排列尺寸,不指定perm,默认为全部转置。

该方法会直接改变原图像的尺寸,不需要新变量去接收。

# 定义一个四维tensor
a = tf.random.normal([4,3,2,1])
a.shape
# 不传参数,全部转置
tf.transpose(a).shape
# 指定参数,新shape的0维度放原来的0维度,新shape的2维度放原来的3维度
tf.transpose(a,perm=[0,1,3,2]).shape

若不传参数,默认将tensor全部转置,如在矩阵中的行列互换,从三行两列变成两行三列。

若指定参数,perm=[0,1,3,2] 代表重新指定排列的顺序,新shape的第0个维度放原来的第0个维度,新shape的第1个维度放原来的第1个维度,新shape的第2个维度放原来的第3个维度,新shape的第3个维度放原来的第2个维度。也就是说从原来的[b,h,w,c] 变成 [b,h,c,w]

我们再看一例,加深理解。

# 从b维度转到[4,28,28,2]
b = tf.random.normal([28,2,4,28]) # [w,c,b,h]
tf.transpose(b,perm=[2,3,0,1]).shape # [b,h,w,c]


1.3 增加维度

指定位置增加一个维度: tf.expand_dims(tensor, axis)

tensor为需要增加维度的变量;axis为在哪个轴前面增加维度

不改变原始数据,需要有新变量去接收

# 4个班级35个学生8门课
a = tf.ones([4,35,8]) 
# 在最前面增加一个维度
tf.expand_dims(a,axis=0).shape
# 在指定位置前面添加一个维度,在课目前加一个维度
tf.expand_dims(a,axis=2).shape

axis=0代表指定第0个轴,即班级维度,在前面添加一个轴,理解为学校维度

如果轴axis为整数时,在指定轴前面增加一个新维度;若轴axis为负数时,在指定轴后面增加一个新维度。

b = tf.zeros([4,35,8])  # 下标为(-3,-2,-1)
# 理解为,在学生维度35后面增加一个维度
tf.expand_dims(b,axis=-2).shape
# 理解为,在课目维度8后面增加一个维度
tf.expand_dims(b,axis=-1).shape


1.4 减少维度

删除当前shape为1的维度: tf.squeeze(tensor, axis)

tensor代表需要减少维度的变量;axis代表指定删除哪一个轴的维度,如果存在多个shape为1的轴,不指定axis时,默认删除所有axis为1的轴。axis指定的轴必须是存在的且该轴的shape为1

不改变原数据,需要有新变量接收

# 创建一个五维tensor
a = tf.ones([1,2,1,1,3])
a.shape
# 不指定轴,默认删除所有维度为1的轴
tf.squeeze(a).shape
# 指定删除第0个轴
tf.squeeze(a,axis=0).shape
# 删除倒数第2个轴
tf.squeeze(a,axis=-2).shape


2. 广播

利用广播将原始tensor成倍增加: tf.broadcasting_to(tensor, shape)

tensor代表需要扩张的变量,shape代表需要扩张成什么样的

是一种张量维度扩张的手段,某一个维度重复n多次,但是没有真正的复制一个数据。是一种优化手段,没有复制数据,但是呈现出数据已经被扩张

不会改变原数据,需要有变量来接收

举个例子说明一下:

计算时,如果a维度和b维度不一致时,在相应的维度上添加一个维度

a.shape = [4,16,16,32]   大维度            b.shape = [32]   小维度

先将小维度和大维度的右端对齐,如果小维度在大维度的相应维度上没有维度,就插入一个维度 

b.shape = [1,1,1,32]

把插入的一维度扩张成相同的size,最终b通过broadcasting会输出

b.shape = [4,16,16,32]

broadcasting没有复制数据,把它理解成已经复制了,用于优化计算

小维度某个轴的shape为1时可以扩张成大维度对应轴的shape,如果为其他shape不可以扩张

如在计算a维度和b维度,a.shape = [4,32,14,14]b.shape = [2,32,14,14],在轴axis=0处,b的shape为2,不可以进行扩张,如果是1可以进行扩张,因此,这两个tensor不可以运算。

下面,我们看一下代码

#(1)不调用函数自动计算
# 定义一个四维tensor
a = tf.random.normal([4,32,32,3])
# 大维度加小维度,先对小维度扩张
(a + tf.random.normal([32,32,1])).shape
# 由于轴axis=1对应的shape不同且不为1,不能扩张
(a + tf.random.normal1([1,4,1,1])).shape  # 不能计算

在计算时,我们选择可以不用调用广播的函数,计算时,计算机会自动执行广播的方法,对小维度扩张。因此,shape为[32,32,1]被扩张成[1,32,32,1],再变成[4,32,32,3],然后这两个tensor就可以进行计算了。

而第二个计算,shape为[1,4,1,1],由于小维度的axis=1对应的shape为4,大维度shape为32,无法进行广播扩张,只有shape是1时才能扩张。

我们也可以调用广播函数tf.broadcast_to(input, shape)进行扩张

# 定义2个需要计算的tensor
a = tf.random.normal([4,32,32,3])
b = tf.random.normal([32,32,1])
# 利用广播函数将b扩张成a,利用新变量x接收扩张后的结果
x = tf.broadcast_to(b,a.shape)
x.shape

对变量a和b计算前,需要将a和b的维度变成一样的,因此需要将小维度的b扩张成和变量a一样的维度。又因为广播函数不会改变原值,所以用新变量x来接收广播完成后的b。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立Sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值