线性代数基础:标量、向量、矩阵与张量
深入理解线性代数的基本概念,包括标量、向量、矩阵和张量的定义、性质及PyTorch实现

展开文章目录
1. 标量、向量、矩阵与张量
1.1 标量
只有一个元素的张量是标量 (scalar),用普通小写字母表示,如 、 和 等。用 表示所有连续的实数标量空间,即 。
1.2 向量
将标量组织成列表,表示的一维张量是向量 (vector),用粗体的小写字母表示,如 、 和 等。每个向量都由 个实值标量组成,记作 。
1.3 矩阵
从一阶推广到二阶,表示的二维张量是矩阵 (array, matrix),用粗体的大写字母表示,如 、 和 等。每个矩阵都由 行和 列的实值标量组成,记作 。
1.4 张量
进一步推广到更多阶,统称为张量 (tensor),泛指全部的代数对象,用无衬线字体的大写字母表示,如 、 和 等。用于构建具有更多轴的数据。

2. 张量的创建
PyTorch 提供了许多创建张量并初始化的方法:
张量创建方法
torch.zeros():创建指定大小的全零张量torch.ones():创建指定大小的全 1 张量torch.randn():创建指定大小的张量,并用来自标准正态分布的随机数填充torch.arange():创建从起始值到结束值(不含)的等差数列张量torch.eye():创建指定大小的单位矩阵 (identity matrix)torch.linspace():创建从起始值到结束值,以特定步长间距的张量torch.full():创建指定大小,由特定值填充的张量
另外,torch.tensor()函数和torch.Tensor()方法是根据输入创建张量的通用方法:
3. 张量的基本运算
3.1 加减除、数乘与乘法
加减除运算相对简单,这里重点介绍矩阵数乘(逐元素分别相乘,Hadamard 积,数学符号用 表示)和矩阵乘法:
矩阵运算
矩阵数乘(Hadamard积)
a: torch.Tensor = torch.arange(20, dtype=torch.float32).reshape(5, 4)
b: torch.Tensor = torch.arange(20, 40, dtype=torch.float32).reshape(5, 4)
print(f'矩阵数乘:a * b =\n{a * b}')
print(f'矩阵数乘:a.mul(b) =\n{a.mul(b)}')矩阵乘法
符号@原本用于装饰器的定义,Python 3.5 开始,@亦可用于矩阵的乘法运算符。
print(f'矩阵乘法:a @ b.T =\n{a @ b.T}')
print(f'矩阵乘法:a.matmul(b.T) =\n{a.matmul(b.T)}')
print(f'矩阵乘法:a.mm(b.T) =\n{a.mm(b.T)}')查看完整代码示例
a: torch.Tensor = torch.arange(20, dtype=torch.float32).reshape(5, 4)
b: torch.Tensor = torch.arange(20, 40, dtype=torch.float32).reshape(5, 4)
print(f'矩阵数乘:a * b =\n{a * b}')
print(f'矩阵数乘:a.mul(b) =\n{a.mul(b)}')
print(f'矩阵乘法:a @ b.T =\n{a @ b.T}')
print(f'矩阵乘法:a.matmul(b.T) =\n{a.matmul(b.T)}')
print(f'矩阵乘法:a.mm(b.T) =\n{a.mm(b.T)}')输出结果:
矩阵数乘: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.]])矩阵与向量乘法
A = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)
x = torch.tensor([7, 8, 9], dtype=torch.float32)
print(f'矩阵 A ({A.shape}) 与向量 x ({x.shape}) 的乘积:{A.mv(x)}')
3.2 向量的点积

在实践中,用非负且权重和为 1 的点积进行加权求和;使用范数乘积计算向量的夹角余弦值,评估它们的相似度。
点积应用
scores = torch.tensor([72, 80, 95, 29, 100], dtype=torch.float)
weights = torch.tensor([0.2, 0.3, 0.1, 0.2, 0.2], dtype=torch.float) # 权重值均非负,且和为一
score = torch.dot(scores, weights)
print(f'用点积计算加权和:{score:.2f}')
# 输出:用点积计算加权和:73.70x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
cosine_similarity = torch.dot(x, y) / (torch.norm(x) * torch.norm(y))
print(f"两向量的余弦相似度:{cosine_similarity.item():.3f}")
# 输出:两向量的余弦相似度:0.9753.3 求和、求均值
x: torch.Tensor = torch.arange(24, dtype=torch.float32).reshape(3, -1)
print(f'x =\n{x}')
print(f'x.numel() = {x.numel()}') # 元素总数
print(f'x.shape = {x.shape}') # 张量形状
print(f'x.sum() = {x.sum()}') # 所有元素求和
print(f'x.sum(dim=0) = {x.sum(dim=0)}') # 按行求和
print(f'x.sum(dim=1) = {x.sum(dim=1)}') # 按列求和
print(f'x.mean() = {x.mean()}') # 所有元素求均值
print(f'x.mean(dim=0) = {x.mean(dim=0)}') # 按行求均值
非降维求和
sum_default = x.sum(dim=1)
sum_keepdim = x.sum(dim=1, keepdim=True)
print(f'x 的维数:{x.dim()}')
print(f'x.sum(dim=1) = {sum_default}')
print(f'x.sum(dim=1) 的维数:{sum_default.dim()}')
print(f'x.sum(dim=1, keepdim=True) = {sum_keepdim}')
print(f'x.sum(dim=1, keepdim=True) 的维数:{sum_keepdim.dim()}')
print(f'x / sum_keepdim =\n{x / sum_keepdim}')
累计求和
print(f'x.cumsum(dim=1) =\n{x.cumsum(dim=1)}')
4. 范数
范数 (norm) 是用于衡量张量大小或长度的量。
4.1 几何角度理解范数
在用向量抽象真实世界的深度学习中,有许多最优化问题:使相似向量间的距离尽可能最小、使异质向量间的距离尽可能最大。而范数成了重要的指标之一。
4.2 向量范数
向量范数类型
- L0 范数:向量的非零元素个数——稀疏度
- L1 范数(曼哈顿范数):向量的所有元素绝对值之和
- L2 范数(欧几里得范数):向量的模,向量元素绝对值平方的和开算术平方根
- ∞ 范数:向量元素中,绝对值的最大值
- -∞ 范数:向量元素中,绝对值的最小值
- p 范数:向量元素中,绝对值的 p 次方和的 1/p 次幂
对于向量 :
- L0 范数:
- L1 范数:
- L2 范数:
- ∞ 范数:
- p 范数:
4.3 矩阵范数
- L1 范数(列和范数):矩阵中,全部列向量绝对值之和的最大值
- L2 范数(谱范数):矩阵的最大奇异值(矩阵的特征值的平方根)
- ∞ 范数(行和范数):矩阵中,全部行向量绝对值之和的最大值
- F 范数(Frobenius 范数):矩阵各元素绝对值平方的和开算数平方根
4.4 重要性质
4.5 代码实现
x = torch.tensor([3.0, -4.0, 2.0])
norm_0 = torch.norm(x, p=0)
norm_1 = torch.norm(x, p=1)
norm_2 = torch.norm(x, p=2)
norm_f = torch.norm(x, p='fro')
norm_inf = torch.norm(x, p=torch.inf)
print(f'向量的 L0 范数: {norm_0.item():.2f}')
print(f'向量的 L1 范数: {norm_1.item():.2f}')
print(f'向量的 L2 范数: {norm_2.item():.2f}')
print(f'向量的 F 范数: {norm_f.item():.2f}')
print(f'向量的无穷范数: {norm_inf.item():.2f}')
查看输出结果
向量的 L0 范数: 3.00
向量的 L1 范数: 9.00
向量的 L2 范数: 5.39
向量的 F 范数: 5.39
向量的无穷范数: 4.00参考资料
如果这篇记录对你有帮助,可以留下一句回应。

DISCUSSION
讨论与回应
欢迎补充细节、指出问题,或分享与这篇文章有关的经验。
昵称与邮箱为必填项,邮箱仅用于头像和回复通知,不会公开。网址可以留空。