张量
基本概念
张量(Tensor)是深度学习中的基本数据结构,可以看做是多维数组的推广。标量(scalar)、行向量(row vector)、矩阵(matrix)都是张量的特例:
- 标量:0 维的张量,例如 $[5]$ ,所属空间为 $\mathbb{R}$ ;
- 向量:1 维的张量,例如 $[1, 2, 3]^\mathsf{T}$ ,所属空间为 $\mathbb{R}^3$ ;
- 矩阵:2 维的张量,例如 $\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6\end{bmatrix}$ ,所属空间为 $\mathbb{R}^{2 \times 3}$ ;
从数学视角来看,一个 $\mathbb{R}^{2 \times 3}$ 张量空间中的张量是由两个张量空间 $ $\mathbb{R}^3$ 按序排列形成的。在 PyTorch 中,用数组 $[2, 3]$ 来标记张量的尺寸。
尺寸和步长
从计算机存储的视角看,像 $\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6\end{bmatrix}$ 这样的张量在内存中是按照 $[1, 2, 3, 4, 5, 6]$ 连续存储的。 当需要从内存中取出各维的数据时,就不可避免地涉及到“一次取出多少”的问题。很显然,对于上面这样简单的例子,要取出张量中的第一个分量(component),就是从内存中取出开始的 3 个数。 对于矩阵这样的简单场景,一次取多少是很直观的。但对于尺寸为 $[9, 8, 7, 6]$ 的高维张量 [^tensor-size],一次取多少就是一个不是那么好定义的问题。 比如:要取出整个张量中第 2 个分量的第 1 个分量,应该怎样取? 为此,我们需要一个通用的规则来定义取多少,这就是 步长 (stride)的概念:取出第 0 维的分量时,间隔为 $9 \times 8 \times 7$ ,共有 $6$ 个这样的分量;取出第 1 维的分量时,间隔为 $9 \times 8$ ,共有 $7 \times 6$ 个这样的分量……从中文翻译的字面上看,我们很容易将步长误认为是一个数,但由上面的例子可以看出,步长实际上是一个张量。
在 PyTorch 中,数学中的维也被称为轴。
在 PyTorch 中,我们可以通过如下的方式来定义并获取一个张量的尺寸和步长:
x = torch.Tensor([[1,2,3],[4,5,6]])
x.size()
x.stride()
微分
考虑多元函数 $\mathbf{f}: \mathbb{R}^m \mapsto \mathbb{R}^n$ ,它一共有 $m$ 个偏导数,每个偏导数都有 $n$ 个分量。若将这些偏导数从左到右依次排列成一个矩阵,我们就得到了雅可比矩阵(Jacobian Matrix)。在这个多元函数可导条件满足的情况下,Jacobian 矩阵就是这个函数的导数。可阅读 Derivatives 进一步了解相关理论。
在多元函数的情形下,无论是偏导数还是导数,实际上已经不再是“数”,而是张量。