张量这一概念的核心在于,它是一个数据容器。它包含的数据几乎总是数值数据,因此它是数字的容器。
你可能对矩阵很熟悉, 它是二维张量。 张量是矩阵向任意维度的推广[注意, 张量的维度(dimension)通常叫作轴(axis)]。
张量的维度
- 包含一个数字的张量叫作标量(scalar,也叫标量张量、零维张量、0D 张量)。
张量有 0 个轴( ndim == 0 )。张量轴的个数也叫作阶(rank)。下面是一个 Numpy 标量。
>>> import numpy as np
>>> x = np.array(12)
>>> x array(12)
>>> x.ndim
0
- 向量(1D 张量)
数字组成的数组叫作向量(vector)或一维张量(1D 张量)。一维张量只有一个轴。
>>> x = np.array([12, 3, 6, 14, 7])
>>> x array([12, 3, 6, 14, 7])
>>> x.ndim
1
- 矩阵(2D 张量)
向量组成的数组叫作矩阵(matrix)或二维张量(2D 张量)。矩阵有 2 个轴(通常叫作行和列)
第一个轴上的元素叫作行(row),第二个轴上的元素叫作列(column)。
>>> x = np.array([[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]])
>>> x.ndim
2
- 3D 张量与更高维张量
将多个矩阵组合成一个新的数组,可以得到一个 3D 张量,你可以将其直观地理解为数字 组成的立方体。
>>> x = np.array([[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]]])
>>> x.ndim
3
将多个 3D 张量组合成一个数组,可以创建一个 4D 张量,以此类推。深度学习处理的一般 是 0D 到 4D 的张量,但处理视频数据时可能会遇到 5D 张量。
关键属性
轴的个数(阶)。 例如,3D 张量有 3 个轴, 矩阵有 2 个轴。 这在 Numpy 等 Python 库中也叫张量的 ndim 。 �
形状。 这是一个整数元组, 表示张量沿每个轴的维度大小(元素个数)。 例如, 前面矩阵示例的形状为 (3, 5) ,3D 张量示例的形状为 (3, 3, 5) 。向量的形状只包含一个元素,比如 (5,) ,而标量的形状为空,即 () 。
数据类型(在 Python 库中通常叫作 dtype )。这是张量中所包含数据的类型,例如,张量的类型可以是 float32 、 uint8 、 float64 等。在极少数情况下,你可能会遇到字符 ( char )张量。
张量的切片同python数组的切片一样。
数据批量的概念
通常来说,深度学习中所有数据张量的第一个轴(0 轴,因为索引从 0 开始)都是样本轴 (samples axis,有时也叫样本维度)。
>>> my_slice = train_images[10:100]
>>> print(my_slice.shape) (90, 28, 28)
上面的例子表示 :在MNIST数据集中,将 10~100 个数字(不包括第 100 个), 并将其放在形状为 (90, 28, 28) 的数组中。
>>> my_slice = train_images[10:100, :, :]
>>> my_slice.shape (90, 28, 28)
>>> my_slice = train_images[10:100, 0:28, 0:28]
>>> my_slice.shape (90, 28, 28)
这些代码效果都是等同的。
此外,深度学习模型不会同时处理整个数据集,而是将数据拆分成小批量。
比如下面的每个批量 大小是128.
batch = train_images[:128]
batch = train_images[128:256]
batch = train_images[128 * n:128 * (n + 1)]
对于这种批量张量,第一个轴(0 轴)叫作批量轴(batch axis)或批量维度(batch dimension)。
现实世界中的数据张量
向量数据:2D 张量,形状为 (samples, features) 。
时间序列数据或序列数据:3D 张量,形状为 (samples, timesteps, features) 。
图像:4D 张量,形状为 (samples, height, width, channels) 或 (samples, channels, height, width) 。
视频:5D 张量,形状为 (samples, frames, height, width, channels) 或 (samples, frames, channels, height, width) 。
举例:
-
时间序列组成的3D张量
根据惯例,时间轴始终是第 2 个轴(索引为 1 的轴) -
图像数据组成的4D张量
图像张量的形状有两种约定:通道在后(channels-last)的约定(在 TensorFlow 中使用)和通道在前(channels-first)的约定(在 Theano 中使用)。
Google 的 TensorFlow 机器学习框架将颜色深度轴放在最后: (samples, height, width, color_depth) 。 与此相反,Theano 将图像深度轴放在批量轴之后: (samples, color_depth, height, width) 。 视频数据组成的5D张量
视频数据是现实生活中需要用到 5D 张量的少数数据类型之一。 视频可以看作一系列帧, 每一帧都是一张彩色图像。由于每一帧都可以保存在一个形状为 (height, width, color_ depth) 的 3D 张量中, 因此一系列帧可以保存在一个形状为 (frames, height, width, color_depth) 的 4D 张量中,而不同视频组成的批量则可以保存在一个 5D 张量中,其形状为 (samples, frames, height, width, color_depth) 。
张量变形
张量变形是指改变张量的行和列,以得到想要的形状。变形后的张量的元素总个数与初始张量相同。
>>> x = np.array([[0., 1.],
[2., 3.],
[4., 5.]])
>>> print(x.shape) (3, 2)
>>> x = x.reshape((6, 1))
>>> x
array([[ 0.],
[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.]])
>>> x = x.reshape((2, 3))
>>> x
array([[ 0., 1., 2.],
[ 3., 4., 5.]])
经常遇到的一种特殊的张量变形是转置(transposition)。对矩阵做转置是指将行和列互换, 使 x[i, :] 变为 x[:, i] 。
>>> x = np.zeros((300, 20))
>>> x = np.transpose(x)
>>> print(x.shape)
(20, 300)