- TensorFlow深度学习从入门到进阶
- 张德丰编著
- 1788字
- 2021-03-23 18:05:54
2.1 张量
TensorFlow 中 Tensor 的意思是“张量”,Flow 的意思是“流或流动”。任意维度的数据可以称作“张量”,如一维数组、二维数组、N维数组。它最初想要表达的含义是保持计算节点不变,让数据在不同的计算设备上传输并计算。
2.1.1 张量的概念
张量可以被简单理解为多维阵列,其中零阶张量表示标量,也就是一个数。一阶张量表示为一个一维阵列,n阶张量表示n维阵列。
张量在 TensorFlow 中的不是直接采用阵列的形式实现的,它只是对 TensorFlow 中运算结果的引用。张量中并没有真正储存数字,它储存的是如何得到这些数字的计算过程。例如:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_26_02.jpg?sign=1739361496-jI3FDjvXRvhfuUZooXenTt3M2olVW7QZ-0-e5872be6026a6e785587f85248652583)
TensorFlow 中的张量和 Numpy 中的阵列不同,TensorFlow 的计算结果不是一个具体的数字,而是一个张量的结构。一个张量储存了3个属性:名字、维度和型别。表2-2列出了张量的数据类型。
表2-2 张量数据类型
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_27_01.jpg?sign=1739361496-KjVdcmdws0JxgNgq9RzgHDxV2PpegBIF-0-8b8d1790f1a9a461e65412de8ad581b2)
2.1.2 张量的使用
张量的使用可以总结为两大类。
第一类用途是对中间计算结果的引用。当一个计算包含很多计算结果时,使用张量可以提高代码的可读性。下面为使用张量和不使用张量记录中间结果来完成向量相加的代码对比。
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_27_02.jpg?sign=1739361496-kLNvUkurweHIihUH0DDSIxbOpqkooDCW-0-62b265b03ce3890d2ab38e3cfedfe637)
从上面的程序样例可以看到,a 和 b 其实就是对常量生成这个运算结果的引用,这样在做加法时可以直接使用这两个变量,而不需要再去生成这些常量。同时通过张量来存储中间结果,这样可以很方便地获取中间结果。比如在卷积神经网络中,卷积层或者池化层有可能改变张量的维度,通过result.get_shape函数来获取结果张量的维度信息可以免去人工计算的麻烦。
第二类用途是当完成计算图构造之后,张量可以来获得计算结果,也就是得到真实的数字。虽然张量本身没有存储具体的数字,但可以通过会话session得到这些具体的数字。比如使用tf.Session().run(result)语句来得到计算结果。
2.1.3 Numpy库
TensorFlow的数据类型是基于NumPy的数据类型,如:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_27_03.jpg?sign=1739361496-VJYASOxgizRxaVsTYxBpavWFfsPWjEPq-0-523989a20c47fbf188f3de2e24c72e2d)
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_28_01.jpg?sign=1739361496-53K37fanJXC9MwDstmgCZFsQEMtVYYnv-0-2bbeb9d8f9230d0672ba485d0e387345)
任何一个NumPy数组均可传递给TensorFlow对象。
对于数值类型和布尔类型,TensorFlow和NumPy dtype属性是完全一致的。然而,在NumPy中并无与tf.string精确对应的类型,即TensorFlow可以从NumPy中完美地导入字符串数组,只是不要在NumPy中显式指定dtype。
在运行数据流图之前之后,都可以利用NumPy库的功能,因为从Session.run方法返回的张量均为NumPy数组。如:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_28_02.jpg?sign=1739361496-rCDOTyuirpTggQuEYXUYT1VNumnBAzUA-0-4cb7ef6e1b663a1f79c7d897fdc06cc1)
虽然TensorFlow是为理解NumPy原生数据类型而设计的,但不要贸然尝试用tf.int32去初始化一个NumPy数组。
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_28_03.jpg?sign=1739361496-qADATiYlR4jS6IlOIvVANT0QHbBH98rD-0-c644c3ce4804a515a4c0ec6dec4e6d37)
手工指定张量对象时,常被推荐的是使用NumPy的方式。
2.1.4 张量的阶
张量的阶(rank)表征了张量的维度,但是跟矩阵的秩(rank)不一样。它表示张量的维度的质量。
阶为1的张量等价于向量,阶为2的向量等价于矩阵。对于一个阶为2的张量,通过t[i, j]就能获取它的每个元素。对于一个阶为 3 的张量,需要通过t[i, j,k]进行寻址,以此类推,见表2-3。
表2-3 张量的阶
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_29_01.jpg?sign=1739361496-1qoAoPWfKP4DciY5v0NtM0x72W0RgX7f-0-2db7d2a3a26c7beaeb5779718c889b7b)
在下面的例子中,可创建一个张量来获取其结果:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_29_02.jpg?sign=1739361496-7qIuRLndliuKAyEUeZDmT8lvLxAN64OH-0-f8b3f98bd4f9d4f23530d0bb477ed286)
这个张量的阶是3,因为该张量包含的矩阵中的每个元素都是一个向量。
2.1.5 张量的形状
TensorFlow 文档使用3个术语来描述张量的维度:阶(rank)、形状(shape)和维数(dimension number)。表2-4展示了它们彼此之间的关系。
表2-4 三者之间的关系
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_29_03.jpg?sign=1739361496-Y1qk2DjLFahP3FZxTjbdKaMoJLN6gxC8-0-ded4e9825761c2194bbf501f3c3415d0)
如下代码创建了一个三阶张量,并打印出了它的形状。
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_29_04.jpg?sign=1739361496-qJDoJyKRUOeDDZBfHF7VT0afU8J8qbk4-0-f7c36b633f950dd0bfc4f301b25aa3f1)
2.1.6 张量应用实例
下面直接通过一个实例来进一步理解张量的概念。代码为:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_29_05.jpg?sign=1739361496-jmiC8zgXvH1N3pY7J3gORJIpT1s9Ap1d-0-6c9221eb20ce25e1134c00bfc06cee4c)
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_30_01.jpg?sign=1739361496-ryEFk5eXqYDfHmBWsvWqhWnqLbFL9Imx-0-2786b04681eec878651d815a3198e249)
运行程序,输出如下:
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_30_02.jpg?sign=1739361496-7usgmMzGECXIDwjnrM6UrEETQGeoxN8a-0-414ef91d2f88ba5dedc83eff8a11ec26)
(1)图像张量的分析
下面就来分析一下。
首先说明的是在TensorFlow中数据定义格式是NHWC,即N代表个数、H代表高、W代表宽、C代表通道数。
img=tf.Variable(tf.constant([1.0,2.0,3.0,4.,5.0],shape=[2,4,5,3]))
从shape上来看,维度是[2,4,5,3],表示2个4×5的3通道图像。也就是模拟生成2张图片,每张图片大小是4行5列,通道数是3。因为常量值提供了5个,当初始化数据不够时,TensorFlow默认选择最后一个数据重用。
这幅图代表的是第一张图片的内容,对应的是img输出虚线上面的部分,下面具体分析。
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_30_03.jpg?sign=1739361496-s3X7o3VTAmSUWbo5edXNtGkK2dnr4xGw-0-03338f9eb94004d8c9c32ec4f3ee5858)
1.,2.,3.分别代表第一张图片的第一个像素位置3个通道上的值,在第二行代表的是第二个位置3个通道的值,依次类推,这里有5行数据,说明这个图片有5列。那么上面这个矩阵就代表了3个通道第一行的内容。虚线上的那个矩阵有4个部分,那么也就是这张计算图有4行,如图2-1所示。
![](https://epubservercos.yuewen.com/C16494/19573973401151406/epubprivate/OEBPS/Images/978-7-111-65263-2_31_01.jpg?sign=1739361496-CzIgqJZ6fkywBSKXpn1cBhN4dgkI87Oz-0-0d5389dc328aa7735952ccf4d1aee20d)
图2-1 3个通道
上面定义了两张图片,第二张图片放置在第二个位置,3个通道的数据全部是 5,这里就不画出来了。其次还要关注一点,这两个图像本身是三维的张量,最后又放在一个矩阵当中并列的位置,构成了四维张量。
(2)滤波器张量的分析
首先是TensorFlow中滤波器的定义格式,filter相当于CNN中的卷积核,它要求是一个Tensor具有[filter_height,filter_width,in_channels,out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels就是参数input的第四维。
filter=tf.Variable(tf.constant([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,0],shape=[2,3,3,5]))
在上述代码中,定义了高为2、宽为3、通道数为3、卷积核个数为5的滤波器。