可能图灵或者乔姆斯基这些上一代的大师会想象包含世界知识的高度复杂的数据也应该具有高度复杂的结构。然而现在的大规模深度神经网络的数据在人类看来却恰恰相反,是高度同质,高度非结构化的。当然这种非结构化实际上并不是没有结构,而是人类的理性思维难以感知这种结构。我们这里就不谈那些理论,从结果上来看,张量就是对这种非结构化数据的一种有效的表示。
从开发者的视角看,张量就是高维数组在深度神经网络程序中的别名。例如 C 语言中这样表示一个数组:
T arr[m][n];
读作“m 行 n 列的 T 数组 arr”,或者“m 乘 n 的二维数组 arr”。从这个声明中,我们可以看到这个数组最基本的信息,数据类型 T,形状 m x n
,维数 2。同时我们可以意识到当我们读写这个数组时,我们实际上读写的是一个 m x n x sizeof(T)
的连续存储区域。
3x4 数组
\------------/ | 1 2 3 4 | | 5 6 7 8 | | 9 10 11 12 | /------------\
在深度神经网络中,最基本的张量定义就是将这个数组动态化起来的一种数据结构。
C++ 表示:
struct Tensor {
DataType data_type; // 数据类型
std::vector<size_t> shape; // 形状
std::vector<uint8_t> data; // 底层数据存储
};
Rust 表示:
struct Tensor {
data_type: DataType, // 数据类型
shape: Vec<usize>, // 形状
data: Vec<u8>, // 底层数据存储
}
事实上,有不少真实可用的深度神经网络程序里真是这样定义张量的,比如 RefactorGraph。可以看到这个张量定义的主体就是数据类型、形状和数据。
在深度神经网络程序中,大部分数据实际上会直接统一到这样的张量定义:
比如:
-
数字,作为变量可能称为“代数类型变量”,在深度学习程序中称为“标量”,表示为一个形状为空——或者说阶数为 0——的张量;
BTW,高维数组的维数在张量中称为“阶数”(
order
)。shape: [] --------- x
-
数组,在深度学习程序中称为“向量”,表示为一个阶数为 1 的张量;
shape: [x] = 6 -------------- [1, 2, 3, 4, 5, 6]
-
二维数组,在深度学习程序中称为“矩阵”,表示为一个阶数为 2 的张量;
shape: [y x] = 3 x 4 -------------------- \------------/ | 1 2 3 4 | | 5 6 7 8 | | 9 10 11 12 | /------------\
-
3 阶到 5 阶的张量在深度神经网络程序中都很常见,尤其 4 阶张量在卷积神经网络中非常常见,以至于英伟达提供的 GPU 算子库 cuDNN 中直接为 4 阶张量的初始化提供了专门的 API;
shape: [z y x] = 2 x 3 x 4 -------------------------- / z *--x ____________ | / /| y / 13 14 15 16| /----------/20| ... |1 2 3 4|24| |5 6 7 8| / |9 10 11 12|/ /----------/
-
更大阶数的张量也偶尔出现;
在高阶的张量中索引数据,就会用到步长(Stride)。步长定义在张量的每一个维度上,表示这一个维度上第 i 个数据和第 i+1 个数据在底层存储上的距离。所以对于 3x4 的二阶张量(矩阵),步长为 [4,1]
:
shape: [ y x] = 3 x 4
strides: [(n) sy sx] = (12) 4 1
-------------------------------
\------------/ \----------/
| 1 2 3 4 | | O → +1 |
| 5 6 7 8 | -> | ↓ |
| 9 10 11 12 | | +4 |
/------------\ /----------\
shape: [ z y x] = 2 x 3 x 4
strides: [(n) sz sy sx] = (24) 12 4 1
-------------------------------------
/ z
*--x ____________ ___________
| / /| / /|
y / 13 14 15 16| / +12 / |
/----------/20| /--/------/ |
|1 2 3 4|24| -> | O → +1 | /
|5 6 7 8| / | ↓ | /
|9 10 11 12|/ |+4 |/
/----------/ /---------/