【深度学习】— 线性代数基础-标量、向量、矩阵、张量、张量算法的基本性质、按元素运算示例、Hadamard积、标量与张量运算、广播机制、降维、点积、矩阵-向量积、矩阵-矩阵乘法、范数
标量
标量是仅包含一个数值的量,如温度52°F。在将其转换为摄氏温度时,公式
c
=
5
9
(
f
−
32
)
c=\frac{5}{9}(f-32)
c=95(f−32)
中,
5
5
5、
9
9
9、
32
32
32都是标量,而
c
c
c和
f
f
f是变量。用数学表示,
x
∈
R
x \in \mathbb{R}
x∈R 表示
x
x
x是实数标量,符号
∈
\in
∈表示“属于”。
标量可以用一个元素的张量表示,代码示例如下:
import torch
x = torch.tensor(3.0)
y = torch.tensor(2.0)
x + y, x * y, x / y, x**y
# 输出: (tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))
向量
向量可以视为标量值组成的列表,这些标量称为向量的元素或分量。在数据集中,向量的每个分量通常代表现实中的特征。例如,在预测贷款违约风险时,向量可能表示一个申请人的收入、工作年限、违约次数等信息。在数学中,向量通常用粗体小写字母(如 x x x、 y y y、 z z z)表示。
我们使用一维张量来处理向量。张量的长度取决于计算机的内存限制。例如:
import torch
x = torch.arange(4)
x
# 输出: tensor([0, 1, 2, 3])
向量中的任一元素可以通过下标引用,如 x i x_i xi表示第 i i i个元素。在数学中,列向量通常表示为:
x = [ x 1 x 2 ⋮ x n ] \mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} x= x1x2⋮xn
其中, x 1 , … , x n x_1, \ldots, x_n x1,…,xn是向量的元素。在代码中,可以通过索引访问向量元素,例如:
x[3]
# 输出: tensor(3)
长度、维度和形状
向量是一个数字数组,每个向量都有一个长度。在数学表示中,如果一个向量 x \mathbf{x} x由 n n n个实值标量组成,则表示为 x ∈ R n \mathbf{x} \in \mathbb{R}^n x∈Rn。向量的长度通常称为维度(dimension)。
与Python数组类似,我们可以通过len()
函数获取张量的长度:
len(x)
# 输出: 4
当用张量表示一个向量(只有一个轴)时,可以通过.shape
属性访问其长度。形状(shape)是一个包含张量沿每个轴的长度的元组,对于只有一个轴的张量,形状只有一个元素:
x.shape
# 输出: torch.Size([4])
请注意,“维度”在不同上下文中可能有不同含义。为了避免混淆:
- 向量或轴的维度:表示向量或轴的长度,即元素的数量。
- 张量的维度:表示张量的轴数。张量的某个轴的维数就是该轴的长度。
矩阵
矩阵是向量的扩展,可以看作是由标量组成的二维数组。我们通常用粗体、大写字母(如 X X X、 Y Y Y、 Z Z Z)表示矩阵。在代码中,矩阵是具有两个轴的张量。
在数学表示中,一个矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A∈Rm×n 表示由 m m m 行 n n n 列的实值标量组成的矩阵 A A A,其中每个元素 a i j a_{ij} aij位于第 i i i行第 j j j列:
A = [ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯ a m n ] A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} A= a11a21⋮am1a12a22⋮am2⋯⋯⋱⋯a1na2n⋮amn
对于任意矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A∈Rm×n,它的形状为 ( m , n ) (m, n) (m,n),当行和列相等时,矩阵称为方阵。我们可以在代码中创建一个5×4的矩阵:
import torch
A = torch.arange(20).reshape(5, 4)
A
# 输出:
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11],
# [12, 13, 14, 15],
# [16, 17, 18, 19]])
可以通过行索引 i i i和列索引 j j j访问矩阵中的元素 a i j a_{ij} aij。矩阵的转置(transpose)将行和列互换,表示为 A ⊤ A^\top A⊤。例如, B = A ⊤ B = A^\top B=A⊤表示转置矩阵 B B B,代码如下:
A.T
# 输出:
# tensor([[ 0, 4, 8, 12, 16],
# [ 1, 5, 9, 13, 17],
# [ 2, 6, 10, 14, 18],
# [ 3, 7, 11, 15, 19]])
对称矩阵(symmetric matrix)是方阵的一种特殊类型,满足 A = A ⊤ A = A^\top A=A⊤。示例如下:
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B
# 输出:
# tensor([[1, 2, 3],
# [2, 0, 4],
# [3, 4, 5]])
B == B.T
# 输出:
# tensor([[True, True, True],
# [True, True, True],
# [True, True, True]])
矩阵是非常有用的数据结构,可以用于组织不同模式的数据。通常,矩阵的行代表不同样本,列代表属性,这在深度学习和表格数据处理中非常常见。
张量
张量是对具有更多轴的数据结构的推广,可以看作是 n n n维数组的通用描述方式。向量是一阶张量,矩阵是二阶张量,而更高阶的张量可以拥有更多的轴。通常用特殊字体的大写字母(如 X X X、 Y Y Y、 Z Z Z)来表示张量,索引方式与矩阵类似(如 x i j k x_{ijk} xijk或 [ X ] 1 , 2 i − 1 , 3 [X]_{1,2i-1,3} [X]1,2i−1,3)。
当处理图像时,张量非常重要,图像可以用一个三维张量表示,三个轴分别对应于高度、宽度和通道(例如红色、绿色和蓝色通道)。我们可以通过以下代码构建一个三维张量:
import torch
X = torch.arange(24).reshape(2, 3, 4)
X
# 输出:
# tensor([[[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]],
# [[12, 13, 14, 15],
# [16, 17, 18, 19],
# [20, 21, 22, 23]]])
这里的张量 X X X是一个三阶张量,形状为 ( 2 , 3 , 4 ) (2, 3, 4) (2,3,4),分别对应于张量的三个轴。高阶张量将帮助我们处理更复杂的数据结构。
张量算法的基本性质
标量、向量、矩阵和任意数量轴的张量都具有一些常见的性质。例如,任何按元素的一元操作(如取负、平方)不会改变张量的形状。同样,对于两个具有相同形状的张量,按元素的二元运算(如加法、乘法)的结果也将是相同形状的张量。
按元素运算示例
以下代码展示了两个形状相同的矩阵按元素相加的结果:
import torch
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone() # 通过分配新内存,将A的一个副本分配给B
A, A + B
# 输出:
# (tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.],
# [12., 13., 14., 15.],
# [16., 17., 18., 19.]]),
# tensor([[ 0., 2., 4., 6.],
# [ 8., 10., 12., 14.],
# [16., 18., 20., 22.],
# [24., 26., 28., 30.],
# [32., 34., 36., 38.]]))
Hadamard积
两个矩阵的按元素乘法称为Hadamard积(Hadamard product),记作 A ⊙ B A \odot B A⊙B。对于矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A∈Rm×n 和 B ∈ R m × n B \in \mathbb{R}^{m \times n} B∈Rm×n,其Hadamard积为:
A ⊙ B = [ a 11 b 11 a 12 b 12 ⋯ a 1 n b 1 n a 21 b 21 a 22 b 22 ⋯ a 2 n b 2 n ⋮ ⋮ ⋱ ⋮ a m 1 b m 1 a m 2 b m 2 ⋯ a m n b m n ] A \odot B = \begin{bmatrix} a_{11}b_{11} & a_{12}b_{12} & \cdots & a_{1n}b_{1n} \\ a_{21}b_{21} & a_{22}b_{22} & \cdots & a_{2n}b_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1}b_{m1} & a_{m2}b_{m2} & \cdots & a_{mn}b_{mn} \end{bmatrix} A⊙B= a11b11a21b21⋮am1bm1a12b12a22b22⋮am2bm2⋯⋯⋱⋯a1nb1na2nb2n⋮amnbmn
在代码中,使用*
运算符实现Hadamard积:
A * B
# 输出:
# tensor([[ 0., 1., 4., 9.],
# [16., 25., 36., 49.],
# [64., 81., 100., 121.],
# [144., 169., 196., 225.],
# [256., 289., 324., 361.]])
标量与张量运算
将张量与标量相乘或相加不会改变张量的形状,张量的每个元素都会与标量进行运算。例如:
a = 2
X = torch.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape
# 输出:
# (tensor([[[ 2, 3, 4, 5],
# [ 6, 7, 8, 9],
# [10, 11, 12, 13]],
# [[14, 15, 16, 17],
# [18, 19, 20, 21],
# [22, 23, 24, 25]]]),
# torch.Size([2, 3, 4]))
广播机制
在前面的部分中,我们介绍了如何对相同形状的两个张量进行按元素操作。但在某些情况下,即使张量形状不同,我们仍然可以使用广播机制来执行按元素操作。
广播机制的工作原理
- 通过适当复制元素,将一个或两个张量扩展为相同的形状。
- 对扩展后的张量进行按元素操作。
通常,广播沿着长度为1的轴进行。以下示例展示了这一机制:
import torch
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
# 输出:
# (tensor([[0],
# [1],
# [2]]),
# tensor([[0, 1]]))
在这个例子中, a a a 是一个 3 × 1 3 \times 1 3×1 的矩阵, b b b 是一个 1 × 2 1 \times 2 1×2 的矩阵。它们的形状不匹配,但通过广播机制,矩阵 a a a 的列被复制,矩阵 b b b 的行被复制,形成一个 3 × 2 3 \times 2 3×2 的矩阵,随后进行按元素相加:
a + b
# 输出:
# tensor([[0, 1],
# [1, 2],
# [2, 3]])
降维
张量的一个常用操作是计算其元素的和,表示为
∑
\sum
∑。对于长度为
d
d
d 的向量
x
\mathbf{x}
x,其元素和可记为
∑
i
=
1
d
x
i
\sum_{i=1}^{d} x_i
∑i=1dxi。在代码中,我们可以使用 sum()
函数:
import torch
x = torch.arange(4, dtype=torch.float32)
x, x.sum()
# 输出: (tensor([0., 1., 2., 3.]), tensor(6.))
对于任意形状的张量,我们也可以计算其元素和。例如,矩阵 A A A 的元素和表示为 ∑ i = 1 m ∑ j = 1 n a i j \sum_{i=1}^{m} \sum_{j=1}^{n} a_{ij} ∑i=1m∑j=1naij:
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
A.shape, A.sum()
# 输出: (torch.Size([5, 4]), tensor(190.))
默认情况下,sum()
会沿所有轴求和,使张量变为一个标量。可以通过指定 axis
参数来沿特定轴求和。例如,axis=0
将对所有行进行求和(沿轴0降维):
A_sum_axis0 = A.sum(axis=0)
A_sum_axis0, A_sum_axis0.shape
# 输出: (tensor([40., 45., 50., 55.]), torch.Size([4]))
指定 axis=1
将对所有列求和(沿轴1降维):
A_sum_axis1 = A.sum(axis=1)
A_sum_axis1, A_sum_axis1.shape
# 输出: (tensor([ 6., 22., 38., 54., 70.]), torch.Size([5]))
对矩阵所有元素求和相当于对矩阵的所有行和列求和:
A.sum(axis=[0, 1]) # 等同于 A.sum()
# 输出: tensor(190.)
平均值
平均值(mean)通过将总和除以元素总数计算,可使用 mean()
函数:
A.mean(), A.sum() / A.numel()
# 输出: (tensor(9.5000), tensor(9.5000))
平均值也可沿特定轴计算:
A.mean(axis=0), A.sum(axis=0) / A.shape[0]
# 输出: (tensor([ 8., 9., 10., 11.]), tensor([ 8., 9., 10., 11.]))
非降维求和
有时,我们希望在求和时保持张量的轴数不变,可使用 keepdims=True
:
sum_A = A.sum(axis=1, keepdims=True)
sum_A
# 输出: tensor([[ 6.],
# [22.],
# [38.],
# [54.],
# [70.]])
保持维度不变后,我们可以通过广播将
A
A
A 除以 sum_A
:
A / sum_A
# 输出: tensor([[0.0000, 0.1667, 0.3333, 0.5000],
# [0.1818, 0.2273, 0.2727, 0.3182],
# [0.2105, 0.2368, 0.2632, 0.2895],
# [0.2222, 0.2407, 0.2593, 0.2778],
# [0.2286, 0.2429, 0.2571, 0.2714]])
累积总和
如果要沿某个轴计算元素的累积总和,可以使用 cumsum()
函数,例如沿 axis=0
:
A.cumsum(axis=0)
# 输出: tensor([[ 0., 1., 2., 3.],
# [ 4., 6., 8., 10.],
# [12., 15., 18., 21.],
# [24., 28., 32., 36.],
# [40., 45., 50., 55.]])
点积(Dot Product)
除了按元素操作、求和和平均值外,点积也是一个基本操作。给定两个向量 x , y ∈ R d \mathbf{x}, \mathbf{y} \in \mathbb{R}^d x,y∈Rd,它们的点积 x ⊤ y \mathbf{x}^\top \mathbf{y} x⊤y (或 ⟨ x , y ⟩ \langle \mathbf{x}, \mathbf{y} \rangle ⟨x,y⟩)是对应位置元素乘积的和:
x ⊤ y = ∑ i = 1 d x i y i \mathbf{x}^\top \mathbf{y} = \sum_{i=1}^{d} x_i y_i x⊤y=i=1∑dxiyi
在代码中可以通过 torch.dot()
计算点积:
import torch
x = torch.arange(4, dtype=torch.float32)
y = torch.ones(4, dtype=torch.float32)
x, y, torch.dot(x, y)
# 输出: (tensor([0., 1., 2., 3.]), tensor([1., 1., 1., 1.]), tensor(6.))
点积也可以通过按元素乘法后求和实现:
torch.sum(x * y)
# 输出: tensor(6.)
点积的应用
点积在许多场合非常有用。例如,对于向量 x ∈ R d \mathbf{x} \in \mathbb{R}^d x∈Rd 和权重向量 w ∈ R d \mathbf{w} \in \mathbb{R}^d w∈Rd, x ⊤ w \mathbf{x}^\top \mathbf{w} x⊤w 表示 x \mathbf{x} x 中的值根据权重 w \mathbf{w} w 的加权和。当权重 w \mathbf{w} w 为非负数且和为1(即 ∑ i = 1 d w i = 1 \sum_{i=1}^{d} w_i = 1 ∑i=1dwi=1)时,点积表示加权平均。此外,将两个向量规范化为单位长度后,点积表示它们夹角的余弦。
矩阵-向量积
在理解了点积之后,我们可以进一步讨论矩阵-向量积(matrix-vector product)。给定矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A∈Rm×n 和向量 x ∈ R n \mathbf{x} \in \mathbb{R}^n x∈Rn,可以将矩阵 A A A 表示为它的行向量的集合:
A = [ a 1 ⊤ a 2 ⊤ ⋮ a m ⊤ ] A = \begin{bmatrix} \mathbf{a}_1^\top \\ \mathbf{a}_2^\top \\ \vdots \\ \mathbf{a}_m^\top \end{bmatrix} A= a1⊤a2⊤⋮am⊤
其中, a i ⊤ ∈ R n \mathbf{a}_i^\top \in \mathbb{R}^n ai⊤∈Rn 是矩阵 A A A 的第 i i i 行。矩阵-向量积 A x A\mathbf{x} Ax 是一个长度为 m m m 的列向量,其第 i i i 个元素是 a i ⊤ x \mathbf{a}_i^\top \mathbf{x} ai⊤x 的点积:
A x = [ a 1 ⊤ x a 2 ⊤ x ⋮ a m ⊤ x ] A\mathbf{x} = \begin{bmatrix} \mathbf{a}_1^\top \mathbf{x} \\ \mathbf{a}_2^\top \mathbf{x} \\ \vdots \\ \mathbf{a}_m^\top \mathbf{x} \end{bmatrix} Ax= a1⊤xa2⊤x⋮am⊤x
矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A∈Rm×n 的乘法可以视为一个从 R n \mathbb{R}^n Rn 到 R m \mathbb{R}^m Rm 的向量转换。这在各种应用中非常有用,例如,方阵的乘法可以表示旋转操作。在神经网络中,矩阵-向量积用于描述从一层到下一层的计算。
代码示例
在代码中,可以使用 torch.mv()
计算矩阵-向量积。请注意,矩阵
A
A
A 的列数(轴1的长度)必须与向量
x
\mathbf{x}
x 的维数(长度)相同:
import torch
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
x = torch.arange(4, dtype=torch.float32)
A.shape, x.shape, torch.mv(A, x)
# 输出: (torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.]))
矩阵-矩阵乘法
在掌握了点积和矩阵-向量积后,理解矩阵-矩阵乘法(matrix-matrix multiplication)会更加容易。
假设我们有两个矩阵 A ∈ R n × k A \in \mathbb{R}^{n \times k} A∈Rn×k 和 B ∈ R k × m B \in \mathbb{R}^{k \times m} B∈Rk×m:
A = [ a 11 a 12 ⋯ a 1 k a 21 a 22 ⋯ a 2 k ⋮ ⋮ ⋱ ⋮ a n 1 a n 2 ⋯ a n k ] , B = [ b 11 b 12 ⋯ b 1 m b 21 b 22 ⋯ b 2 m ⋮ ⋮ ⋱ ⋮ b k 1 b k 2 ⋯ b k m ] A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1k} \\ a_{21} & a_{22} & \cdots & a_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nk} \end{bmatrix}, \quad B = \begin{bmatrix} b_{11} & b_{12} & \cdots & b_{1m} \\ b_{21} & b_{22} & \cdots & b_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ b_{k1} & b_{k2} & \cdots & b_{km} \end{bmatrix} A= a11a21⋮an1a12a22⋮an2⋯⋯⋱⋯a1ka2k⋮ank ,B= b11b21⋮bk1b12b22⋮bk2⋯⋯⋱⋯b1mb2m⋮bkm
矩阵 A A A 的第 i i i 行向量表示为 a i ⊤ ∈ R k \mathbf{a}_i^\top \in \mathbb{R}^k ai⊤∈Rk,矩阵 B B B 的第 j j j 列向量表示为 b j ∈ R k \mathbf{b}_j \in \mathbb{R}^k bj∈Rk。为了生成矩阵积 C = A B C = AB C=AB,我们可以将每个元素 c i j c_{ij} cij 表示为 a i ⊤ b j \mathbf{a}_i^\top \mathbf{b}_j ai⊤bj 的点积:
C = A B = [ a 1 ⊤ a 2 ⊤ ⋮ a n ⊤ ] ⋅ [ b 1 b 2 ⋯ b m ] = [ a 1 ⊤ b 1 a 1 ⊤ b 2 ⋯ a 1 ⊤ b m a 2 ⊤ b 1 a 2 ⊤ b 2 ⋯ a 2 ⊤ b m ⋮ ⋮ ⋱ ⋮ a n ⊤ b 1 a n ⊤ b 2 ⋯ a n ⊤ b m ] C = AB = \begin{bmatrix} \mathbf{a}_1^\top \\ \mathbf{a}_2^\top \\ \vdots \\ \mathbf{a}_n^\top \end{bmatrix} \cdot \begin{bmatrix} \mathbf{b}_1 & \mathbf{b}_2 & \cdots & \mathbf{b}_m \end{bmatrix} {=} \begin{bmatrix} \mathbf{a}_1^\top \mathbf{b}_1 & \mathbf{a}_1^\top \mathbf{b}_2 & \cdots & \mathbf{a}_1^\top \mathbf{b}_m \\ \mathbf{a}_2^\top \mathbf{b}_1 & \mathbf{a}_2^\top \mathbf{b}_2 & \cdots & \mathbf{a}_2^\top \mathbf{b}_m \\ \vdots & \vdots & \ddots & \vdots \\ \mathbf{a}_n^\top \mathbf{b}_1 & \mathbf{a}_n^\top \mathbf{b}_2 & \cdots & \mathbf{a}_n^\top \mathbf{b}_m \end{bmatrix} C=AB= a1⊤a2⊤⋮an⊤ ⋅[b1b2⋯bm]= a1⊤b1a2⊤b1⋮an⊤b1a1⊤b2a2⊤b2⋮an⊤b2⋯⋯⋱⋯a1⊤bma2⊤bm⋮an⊤bm
矩阵-矩阵乘法 A B AB AB 可以看作是对矩阵 B B B 的 m m m 个列向量分别执行 m m m 次矩阵-向量积,并将结果拼接成一个 n × m n \times m n×m 矩阵。
代码示例
在代码中,可以使用 torch.mm()
执行矩阵-矩阵乘法。例如,
A
A
A 是一个 5×4 的矩阵,
B
B
B 是一个 4×3 的矩阵,两者相乘后得到一个 5×3 的矩阵:
import torch
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = torch.ones(4, 3)
torch.mm(A, B)
# 输出:
# tensor([[ 6., 6., 6.],
# [22., 22., 22.],
# [38., 38., 38.],
# [54., 54., 54.],
# [70., 70., 70.]])
请注意,矩阵-矩阵乘法是矩阵乘法的标准定义,与之前提到的Hadamard积不同。
范数
在线性代数中,范数(norm)是用于测量向量大小的函数,表示向量有多大。它将向量映射到标量并满足一些属性:
-
缩放不变性:给定常数因子 α \alpha α,向量 x x x 的范数满足:
f ( α x ) = ∣ α ∣ f ( x ) f(\alpha x) = |\alpha| f(x) f(αx)=∣α∣f(x) -
三角不等式:两个向量 x x x 和 y y y 的范数满足:
f ( x + y ) ≤ f ( x ) + f ( y ) f(x + y) \leq f(x) + f(y) f(x+y)≤f(x)+f(y) -
非负性:范数总是非负的:
f ( x ) ≥ 0 f(x) \geq 0 f(x)≥0 -
零向量的范数为0:只有当向量所有元素都为0时,范数才为0:
∀ i , [ x ] i = 0 ⟺ f ( x ) = 0 \forall i, [x]_i = 0 \iff f(x) = 0 ∀i,[x]i=0⟺f(x)=0
L2范数
L2范数(Euclidean norm)是最常用的范数,表示为:
∥
x
∥
2
=
∑
i
=
1
n
x
i
2
\|x\|_2 = \sqrt{\sum_{i=1}^{n} x_i^2}
∥x∥2=i=1∑nxi2
在代码中,我们可以使用 torch.norm()
来计算L2范数:
import torch
u = torch.tensor([3.0, -4.0])
torch.norm(u)
# 输出: tensor(5.)
L1范数
L1范数是向量元素绝对值的和:
∥
x
∥
1
=
∑
i
=
1
n
∣
x
i
∣
\|x\|_1 = \sum_{i=1}^{n} |x_i|
∥x∥1=i=1∑n∣xi∣
计算L1范数的代码如下:
torch.abs(u).sum()
# 输出: tensor(7.)
Lp范数
Lp范数是L1和L2范数的推广,定义为:
∥
x
∥
p
=
(
∑
i
=
1
n
∣
x
i
∣
p
)
1
/
p
\|x\|_p = \left(\sum_{i=1}^{n} |x_i|^p \right)^{1/p}
∥x∥p=(i=1∑n∣xi∣p)1/p
Frobenius范数
对于矩阵
X
∈
R
m
×
n
X \in \mathbb{R}^{m \times n}
X∈Rm×n,Frobenius范数定义为:
∥
X
∥
F
=
∑
i
=
1
m
∑
j
=
1
n
x
i
j
2
\|X\|_F = \sqrt{\sum_{i=1}^{m} \sum_{j=1}^{n} x_{ij}^2}
∥X∥F=i=1∑mj=1∑nxij2
在代码中,可以通过 torch.norm()
计算矩阵的Frobenius范数:
torch.norm(torch.ones((4, 9)))
# 输出: tensor(6.)
范数与目标
在深度学习中,范数常用于表示目标函数,帮助我们解决优化问题,例如最大化观测数据的概率或最小化预测与真实观测之间的距离。
小结
- 标量、向量、矩阵和张量是线性代数中的基本数学对象。
- 向量是对标量的泛化,矩阵是对向量的泛化。
- 标量、向量、矩阵和张量分别具有零、一、二和任意数量的轴。
- 通过
sum
和mean
函数,张量可以沿指定轴降低维度。 - 两个矩阵的按元素乘法称为Hadamard积,它与矩阵乘法不同。
- 在深度学习中,常用的范数包括 L1范数、L2范数和Frobenius范数。
- 我们可以对标量、向量、矩阵和张量执行各种操作。
练习
- 证明:一个矩阵 A A A 的转置的转置等于 A A A,即 ( A ⊤ ) ⊤ = A (A^\top)^\top = A (A⊤)⊤=A。
证明:
设矩阵 A A A 的元素为 A i j A_{ij} Aij,则其转置矩阵 A ⊤ A^\top A⊤ 的元素为:
( A ⊤ ) i j = A j i (A^\top)_{ij} = A_{ji} (A⊤)ij=Aji
再对 A ⊤ A^\top A⊤ 取转置:
( A ⊤ ) i j ⊤ = ( A ⊤ ) j i = A i j (A^\top)^\top_{ij} = (A^\top)_{ji} = A_{ij} (A⊤)ij⊤=(A⊤)ji=Aij
因此, ( A ⊤ ) ⊤ = A (A^\top)^\top = A (A⊤)⊤=A。
- 证明:给定两个矩阵 A A A 和 B B B,它们转置的和等于它们和的转置,即 A ⊤ + B ⊤ = ( A + B ) ⊤ A^\top + B^\top = (A + B)^\top A⊤+B⊤=(A+B)⊤。
证明:
对于任意元素 i , j i, j i,j,有:
( A ⊤ + B ⊤ ) i j = A i j ⊤ + B i j ⊤ = A j i + B j i ( A + B ) i j ⊤ = ( A + B ) j i = A j i + B j i \begin{aligned} (A^\top + B^\top)_{ij} &= A^\top_{ij} + B^\top_{ij} = A_{ji} + B_{ji} \\ (A + B)^\top_{ij} &= (A + B)_{ji} = A_{ji} + B_{ji} \end{aligned} (A⊤+B⊤)ij(A+B)ij⊤=Aij⊤+Bij⊤=Aji+Bji=(A+B)ji=Aji+Bji
因此:
A ⊤ + B ⊤ = ( A + B ) ⊤ A^\top + B^\top = (A + B)^\top A⊤+B⊤=(A+B)⊤
- 问题:给定任意方阵 A A A, A + A ⊤ A + A^\top A+A⊤ 总是对称的吗?为什么?
回答:
是的,任意方阵 A A A 与其转置之和 A + A ⊤ A + A^\top A+A⊤ 总是对称矩阵。
证明:
计算 A + A ⊤ A + A^\top A+A⊤ 的转置:
( A + A ⊤ ) ⊤ = A ⊤ + ( A ⊤ ) ⊤ = A ⊤ + A (A + A^\top)^\top = A^\top + (A^\top)^\top = A^\top + A (A+A⊤)⊤=A⊤+(A⊤)⊤=A⊤+A
由于矩阵加法满足交换律:
A ⊤ + A = A + A ⊤ A^\top + A = A + A^\top A⊤+A=A+A⊤
因此:
( A + A ⊤ ) ⊤ = A + A ⊤ (A + A^\top)^\top = A + A^\top (A+A⊤)⊤=A+A⊤
这表明 A + A ⊤ A + A^\top A+A⊤ 是对称矩阵。
- 问题:在本节中,我们定义了形状为 (2, 3, 4) 的张量
X
X
X,
len(X)
的输出结果是什么?
回答:
len(X)
的输出结果是 2,即张量
X
X
X 在第 0 轴(第一个维度)的长度。
- 问题:对于任意形状的张量
X
X
X,
len(X)
是否总是对应于 X X X 特定轴的长度?这个轴是什么?
回答:
是的,len(X)
总是返回张量
X
X
X 在 第 0 轴(第一个维度)的长度。
- 实验:运行
A / A.sum(axis=1)
,看看会发生什么。你能分析原因吗?
回答:
运行 A / A.sum(axis=1)
会将矩阵
A
A
A 的每个元素除以其所在行的元素之和。
分析:
A.sum(axis=1)
计算矩阵 A A A 每一行的元素之和,得到一个形状为 ( n , ) (n,) (n,) 的一维数组,其中 n n n 是 A A A 的行数。- 当执行
A / A.sum(axis=1)
时,利用了广播机制,将每一行的元素分别除以对应的行和。 - 结果是对矩阵 A A A 进行行归一化,使得每一行的元素之和为 1。
- 问题:考虑一个形状为 (2, 3, 4) 的张量,在轴 0、1、2 上的求和输出是什么形状?
回答:
- 轴 0 求和:输出形状为 (3, 4)
- 轴 1 求和:输出形状为 (2, 4)
- 轴 2 求和:输出形状为 (2, 3)
解释:
- 轴 0:消除了第一个维度(大小为 2),剩余维度为 (3, 4)。
- 轴 1:消除了第二个维度(大小为 3),剩余维度为 (2, 4)。
- 轴 2:消除了第三个维度(大小为 4),剩余维度为 (2, 3)。
- 实验:为
linalg.norm
函数提供一个有 3 个或更多轴的张量,并观察其输出。对于任意形状的张量,这个函数计算得到什么?
回答:
当将一个具有 3 个或更多轴的张量传递给 linalg.norm
函数时,它将计算张量所有元素的平方和的平方根,即弗罗贝尼乌斯范数。
解释:
-
linalg.norm
默认计算 2-范数,对于多维张量,会将其展平成一维向量后计算范数。 -
计算公式为:
∥ X ∥ = ∑ i , j , k , … ∣ X i , j , k , … ∣ 2 \|X\| = \sqrt{\sum_{i,j,k,\dots} |X_{i,j,k,\dots}|^2} ∥X∥=i,j,k,…∑∣Xi,j,k,…∣2
-
这表示对张量中所有元素进行平方求和,然后取平方根。