线性代数基础:标量、向量、矩阵与张量
本文基于d2l项目内容整理,介绍线性代数的基础概念及其在PyTorch中的实现。
1. 标量、向量、矩阵与张量
1.1 标量
只有一个元素的张量是标量 (scalar),用普通小写字母表示,如 $a$、$b$ 和 $c$ 等。用 $\mathbb{R}$ 表示所有连续的实数标量空间,即 $a \in \mathbb{R}$。
1.2 向量
将标量组织成列表,表示的一维张量是向量 (vector),用粗体的小写字母表示,如 $\mathbf{x}$、$\mathbf{y}$ 和 $\mathbf{z}$ 等。每个向量都由 $n$ 个实值标量组成,记作 $\mathbf{x} \in \mathbb{R}^n$。
向量的重要特性:
此时的标量作为向量的元素或分量
“列”是向量的默认方向
向量的维度即为向量的长度(张量的维度指的是张量具有的轴数,张量某个轴的维数指的是该轴长度)
1.3 矩阵
从一阶推广到二阶,表示的二维张量是矩阵 (array, matrix),用粗体的大写字母表示,如 $\mathbf{A}$、$\mathbf{B}$ 和 $\mathbf{C}$ 等。每个矩阵都由 $m$ 行和 $n$ 列的实值标量组成,记作 $\mathbf{A} \in \mathbb{R}^{m \times n}$。
矩阵的重要概念:
行列数量相等的矩阵称为方阵
交换矩阵行列的过程称为转置 (transpose),记作 $\mathbf{A}^T$
若转置前后矩阵相等,即 $\mathbf{A} = \mathbf{A}^T$,该矩阵被称为对称矩阵
1.4 张量
进一步推广到更多阶,统称为张量 (tensor),泛指全部的代数对象,用无衬线字体的大写字母表示,如 $\mathsf{X}$、$\mathsf{Y}$ 和 $\mathsf{Z}$ 等。用于构建具有更多轴的数据。
2. 张量的创建
PyTorch 提供了许多创建张量并初始化的方法:
torch.zeros()
:创建指定大小的全零张量torch.ones()
:创建指定大小的全 1 张量torch.randn()
:创建指定大小的张量,并用来自标准正态分布的随机数填充torch.arange()
:创建从起始值到结束值(不含)的等差数列张量torch.eye()
:创建指定大小的单位矩阵 (identity matrix)torch.linspace()
:创建从起始值到结束值,以特定步长间距的张量torch.full()
:创建指定大小,由特定值填充的张量
另外,torch.tensor()
函数和torch.Tensor()
方法是根据输入创建张量的通用方法:
推荐使用 torch.tensor()
- 接收多种类型的数据作为输入,并自动推断张量的数据类型
- 始终以拷贝的形式创建张量,不共享内存
- 由于数据类型明确、总是执行初始化,而成为更被推荐的选择
谨慎使用 torch.Tensor()
- 接收
torch.Tensor
类型的数据作为输入,根据设备选择默认的数据类型(一般是浮点型) - 直接使用对现有数据的引用而不拷贝数据,或创建未初始化、具有随机数据的张量
3. 张量的基本运算
3.1 加减除、数乘与乘法
加减除运算相对简单,这里重点介绍矩阵数乘(逐元素分别相乘,Hadamard 积,数学符号用 $\odot$ 表示)和矩阵乘法:
矩阵数乘(Hadamard积)
1 | a: torch.Tensor = torch.arange(20, dtype=torch.float32).reshape(5, 4) |
矩阵乘法
符号@
原本用于装饰器的定义,Python 3.5 开始,@
亦可用于矩阵的乘法运算符。
1 | print(f'矩阵乘法:a @ b.T =\n{a @ b.T}') |
查看完整代码示例
1 | a: torch.Tensor = torch.arange(20, dtype=torch.float32).reshape(5, 4) |
输出结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18矩阵数乘:a * b =
tensor([[ 0., 21., 44., 69.],
[ 96., 125., 156., 189.],
[224., 261., 300., 341.],
[384., 429., 476., 525.],
[576., 629., 684., 741.]])
矩阵数乘:a.mul(b) =
tensor([[ 0., 21., 44., 69.],
[ 96., 125., 156., 189.],
[224., 261., 300., 341.],
[384., 429., 476., 525.],
[576., 629., 684., 741.]])
矩阵乘法:a @ b.T =
tensor([[ 134., 158., 182., 206., 230.],
[ 478., 566., 654., 742., 830.],
[ 822., 974., 1126., 1278., 1430.],
[1166., 1382., 1598., 1814., 2030.],
[1510., 1790., 2070., 2350., 2630.]])
PyTorch 中,以下划线_
结尾的方法通常是原地操作,将直接修改调用该方法的张量,而不是返回一个新的张量,如add_()
、mul_()
等。
矩阵与向量乘法
1 | A = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32) |
mv()
方法比@
运算符、matmul()
和mm()
更专注于矩阵与向量的乘法。
3.2 向量的点积
在实践中,用非负且权重和为 1 的点积进行加权求和;使用范数乘积计算向量的夹角余弦值,评估它们的相似度。
余弦相似度的取值范围为 $[-1, 1]$:
- 1 表示向量同向
- -1 表示向量反向
- 0 表示向量垂直
1 | scores = torch.tensor([72, 80, 95, 29, 100], dtype=torch.float) |
1 | x = torch.tensor([1.0, 2.0, 3.0]) |
3.3 求和、求均值
参数命名差异:
- 对于轴或维,NumPy 中使用
axis
,PyTorch 中使用dim
- 对于维度保持,NumPy 中使用
keepdims
,PyTorch 中使用keepdim
虽然它们在运行时是兼容的,但为了在 PyCharm 等 IDE 中有更好的代码提示体验,应规范这些参数的使用。
1 | x: torch.Tensor = torch.arange(24, dtype=torch.float32).reshape(3, -1) |
非降维求和
1 | sum_default = x.sum(dim=1) |
使用 keepdim=True
可以保持原始张量的维度,便于后续的广播运算。
累计求和
1 | print(f'x.cumsum(dim=1) =\n{x.cumsum(dim=1)}') |
4. 范数
范数 (norm) 是用于衡量张量大小或长度的量。
4.1 几何角度理解范数
几何视角的范数理解:
在低维空间以内,函数是几何图形的概括,几何图形是函数的形象化。由于高维空间难以想象,于是从函数泛化出映射的概念,实现从一个集合到另一个集合的转换。为了更好地表达(线性)映射关系,以矩阵作为工具表征这些映射。最终,这些集合/向量,通过矩阵的映射关系,得到了另一个集合/向量。在整个过程中,向量的范数表示集合的大小,矩阵的范数是对变化大小的度量。
在用向量抽象真实世界的深度学习中,有许多最优化问题:使相似向量间的距离尽可能最小、使异质向量间的距离尽可能最大。而范数成了重要的指标之一。
4.2 向量范数
- L0 范数:向量的非零元素个数——稀疏度
- L1 范数(曼哈顿范数):向量的所有元素绝对值之和
- L2 范数(欧几里得范数):向量的模,向量元素绝对值平方的和开算术平方根
- ∞ 范数:向量元素中,绝对值的最大值
- -∞ 范数:向量元素中,绝对值的最小值
- p 范数:向量元素中,绝对值的 p 次方和的 1/p 次幂
对于向量 $\mathbf{x} = [x_1, x_2, \ldots, x_n]^T$:
- L0 范数:$|\mathbf{x}|0 = \sum{i=1}^n \mathbf{1}(x_i \neq 0)$
- L1 范数:$|\mathbf{x}|1 = \sum{i=1}^n |x_i|$
- L2 范数:$|\mathbf{x}|2 = \sqrt{\sum{i=1}^n x_i^2}$
- ∞ 范数:$|\mathbf{x}|_\infty = \max_i |x_i|$
- p 范数:$|\mathbf{x}|p = \left(\sum{i=1}^n |x_i|^p\right)^{1/p}$
4.3 矩阵范数
L1 范数(列和范数):矩阵中,全部列向量绝对值之和的最大值
L2 范数(谱范数):矩阵的最大奇异值(矩阵的特征值的平方根)
∞ 范数(行和范数):矩阵中,全部行向量绝对值之和的最大值
F 范数(Frobenius 范数):矩阵各元素绝对值平方的和开算数平方根
4.4 重要性质
范数的重要性质:
- “L”指的是范数满足线性 (linear) 条件
- $L_n$ 范数亦可记作 $\ell_n$ 范数
- $L_2$ 范数比 $L_1$ 范数更容易受异常值的影响
- 对于 $L_2$ 范数,常常简称为 $\ell$ 范数。深度学习更常使用的是 $|\mathbf{x}|$
- $L_1$ 和 $L_2$ 范数都是 $L_p$ 范数的特例
4.5 代码实现
1 | x = torch.tensor([3.0, -4.0, 2.0]) |
查看输出结果
1 | 向量的 L0 范数: 3.00 |
总结
本文介绍了线性代数的基础概念,包括标量、向量、矩阵和张量的定义与性质,以及它们在PyTorch中的实现方法。这些概念是深度学习的数学基础,理解它们对于后续学习神经网络和机器学习算法至关重要。