线性代数基础
在深度学习中,数据存储和操作的核心是线性代数。无论是图像、文本还是音频,最终都会被转化为数字数组进行处理。本文基于 PyTorch 框架,简要回顾线性代数中的基本对象(标量、向量、矩阵、张量)及其常用运算。
基本数学对象
标量
标量是仅包含一个数值的量(零阶张量)。
数学符号 :x∈Rx \in \mathbb{R}x∈R
应用 :温度 52∘F52^{\circ}F52∘F、房屋价格。
python
import torch
x = torch.tensor(3.0)
y = torch.tensor(2.0)
print(x + y, x * y, x / y, x**y)
输出为:
(tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))
向量
向量是由标量值组成的列表(一阶张量)。
数学符号 :x∈Rn\mathbf{x} \in \mathbb{R}^nx∈Rn
维度 :向量的长度,即元素的数量。
应用:数据样本的特征集(如:[收入, 年龄, 信用分])。
python
x = torch.arange(4)
print(x) # tensor([0, 1, 2, 3])
print(x[3]) # 访问第3个元素: tensor(3)
print(len(x)) # 向量长度: 4
print(x.shape) # 形状: torch.Size([4])
在深度学习中,"维度"一词有时容易混淆。
向量的维度 :指向量的长度(元素个数)。
张量的维度:指轴的数量(比如矩阵是2维张量)。
矩阵
矩阵是向量的推广,具有行和列(二阶张量)。
数学符号 :A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n}A∈Rm×n
应用:表格数据,其中行代表样本,列代表特征。
python
# 创建一个 5行4列 的矩阵
A = torch.arange(20).reshape(5, 4)
print(A)
转置
交换矩阵的行和列。
对称矩阵 :A=A⊤\mathbf{A} = \mathbf{A}^\topA=A⊤,即矩阵等于其转置。
python
print(A.T) # A的转置
# 验证对称矩阵
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
print(B == B.T) # 所有元素均为 True
张量
张量是描述具有任意数量轴的 nnn 维数组的通用方法。
python
X = torch.arange(24).reshape(2, 3, 4)
# 这是一个 2x3x4 的三维张量
张量的基本运算
按元素运算
两个形状相同的张量进行二元运算时,是针对对应位置的元素进行的。
Hadamard积 (⊙\odot⊙):两个矩阵按元素相乘。
python
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone() # 分配新内存
# 按元素加法
print(A + B)
# 按元素乘法 (Hadamard积)
print(A * B)
广播机制
如果将标量与张量运算,标量会作用于张量的每个元素。
python
a = 2;
X = torch.arange(24).reshape(2, 3, 4);
print(a + X)
降维与求和
我们可以对张量求和,默认会汇总所有元素得到一个标量,也可以指定 axis 沿特定轴求和。
axis=0:沿行轴(纵向)操作,行数消失,保留列数。axis=1:沿列轴(横向)操作,列数消失,保留行数。
python
x = torch.arange(4, dtype=torch.float32)
print(x.sum()) # 全部求和
# 矩阵求和
print(A.sum(axis=0)) # 沿轴0降维 (得到长度为4的向量)
print(A.sum(axis=1)) # 沿轴1降维 (得到长度为5的向量)
# 平均值
print(A.mean())
print(A.mean(axis=0))
非降维求和 (keepdims=True)
有时我们需要保持轴数不变(变成 1),这在广播运算中非常有用。
python
sum_A = A.sum(axis=1, keepdims=True)
print(sum_A.shape) # (5, 1),而不是 (5,)
# 利用广播机制计算各行元素的占比
print(A / sum_A)
线性代数运算
这是机器学习中最常用的部分,务必区分 按元素乘法 和 矩阵乘法。
点积
两个向量的按元素乘积之和。
x⊤y=∑i=1dxiyi \mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i x⊤y=i=1∑dxiyi
python
x = torch.arange(4, dtype=torch.float32)
y = torch.ones(4, dtype=torch.float32)
print(torch.dot(x, y)) # 结果为标量 6.0
print(torch.sum(x * y)) # 等价写法
矩阵-向量积
矩阵 A\mathbf{A}A 和向量 x\mathbf{x}x 相乘。
Ax \mathbf{A}\mathbf{x} Ax
要求 :A 的列数必须等于 x 的长度。
python
print(torch.mv(A, x))
矩阵-矩阵乘法
C=AB \mathbf{C} = \mathbf{AB} C=AB
注意不是 Hadamard 积 (A * B)。
python
B = torch.ones(4, 3) # 4行3列
print(torch.mm(A, B)) # A是5x4,结果是 5x3
范数
范数用于衡量向量或矩阵的"大小"。在优化问题(如正则化)中非常重要。
L2L_2L2 范数
向量元素平方和的平方根(欧几里得距离)。
∥x∥2=∑i=1nxi2 \|\mathbf{x}\|2 = \sqrt{\sum{i=1}^n x_i^2} ∥x∥2=i=1∑nxi2
python
u = torch.tensor([3.0, -4.0])
print(torch.norm(u)) # 结果 5.0
L1L_1L1 范数
向量元素绝对值之和。
∥x∥1=∑i=1n∣xi∣ \|\mathbf{x}\|1 = \sum{i=1}^n \left|x_i \right| ∥x∥1=i=1∑n∣xi∣
python
print(torch.abs(u).sum()) # 结果 7.0
Frobenius 范数
矩阵元素的平方和的平方根(类似于矩阵的 L2L_2L2 范数)。
∥X∥F=∑i=1m∑j=1nxij2 \|\mathbf{X}\|F = \sqrt{\sum{i=1}^m \sum_{j=1}^n x_{ij}^2} ∥X∥F=i=1∑mj=1∑nxij2
python
print(torch.norm(torch.ones((4, 9)))) # sqrt(1^2 * 36) = 6.0
总结
- 标量、向量、矩阵、张量是深度学习的数据基石。
- 常用运算方法 :
*按元素乘法。torch.mm矩阵乘法。torch.mv矩阵向量乘法。torch.dot向量点积。
- 利用
keepdims=True可以方便地进行广播操作。 - L1L_1L1 和 L2L_2L2 范数常用于损失函数和正则化项。