如果你曾经在餐厅支付餐费,那么你已经知道一些基本的线性代数,比如在数字间相加或相乘。 例如,北京的温度为
5
2
∘
F
52^{\circ}F
52∘F(除了摄氏度外,另一种温度计量单位)。 严格来说,我们称仅包含一个数值的叫标量(scalar)。 如果要将此华氏度值转换为更常用的摄氏度, 则可以计算表达式
c
=
5
9
(
f
−
32
)
c=\frac{5}{9}(f-32)
c=95(f−32),并将
f
f
f赋为
52
52
52。 在此等式中,每一项(
5
5
5、
9
9
9和
32
32
32)都是标量值。 符号
c
c
c和
f
f
f称为变量(variable),它们表示未知的标量值。
在本书中,我们采用了数学表示法,其中标量变量由普通小写字母表示(例如,
x
x
x、
y
y
y和
z
z
z)。 我们用
R
\mathbb{R}
R表示所有(连续)实数标量的空间。 我们之后将严格定义空间(space)是什么, 但现在你只要记住表达式
x
∈
R
x\in\mathbb{R}
x∈R是表示
x
x
x是一个实值标量的正式形式。 符号
∈
\in
∈称为“属于”,它表示“是集合中的成员”。 我们可以用
x
,
y
∈
{
0
,
1
}
x, y \in \{0,1\}
x,y∈{0,1}来表明
x
x
x和
y
y
y是值只能为
0
0
0或
1
1
1的数字。
[你可以将向量视为标量值组成的列表]。 我们将这些标量值称为向量的元素(element)或分量(component)。 当向量表示数据集中的样本时,它们的值具有一定的现实意义。 例如,如果我们正在训练一个模型来预测贷款违约风险,我们可能会将每个申请人与一个向量相关联, 其分量与其收入、工作年限、过往违约次数和其他因素相对应。 如果我们正在研究医院患者可能面临的心脏病发作风险,我们可能会用一个向量来表示每个患者, 其分量为最近的生命体征、胆固醇水平、每天运动时间等。 在数学表示法中,我们通常将向量记为粗体、小写的符号 (例如,
x
\mathbf{x}
x、
y
\mathbf{y}
y和
z
)
\mathbf{z})
z))。
我们通过一维张量处理向量。一般来说,张量可以具有任意长度,取决于机器的内存限制。
x = torch.arange(4)
x
tensor([0, 1, 2, 3])
我们可以使用下标来引用向量的任一元素。 例如,我们可以通过
x
i
x_i
xi来引用第
i
i
i个元素。 注意,元素
x
i
x_i
xi是一个标量,所以我们在引用它时不会加粗。 大量文献认为列向量是向量的默认方向,在本书中也是如此。 在数学中,向量
x
\mathbf{x}
x可以写为:
x
=
[
x
1
x
2
⋮
x
n
]
,
\mathbf{x} =\begin{bmatrix}x_{1} \\x_{2} \\ \vdots \\x_{n}\end{bmatrix},
x=⎣⎢⎢⎢⎡x1x2⋮xn⎦⎥⎥⎥⎤, :eqlabel:eq_vec_def
其中
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)。
正如向量将标量从零阶推广到一阶,矩阵将向量从一阶推广到二阶。 矩阵,我们通常用粗体、大写字母来表示 (例如,
X
\mathbf{X}
X、
Y
\mathbf{Y}
Y和
Z
\mathbf{Z}
Z), 在代码中表示为具有两个轴的张量。
在数学表示法中,我们使用
A
∈
R
m
×
n
\mathbf{A} \in \mathbb{R}^{m \times n}
A∈Rm×n 来表示矩阵
A
\mathbf{A}
A,其由
m
m
m行和
n
n
n列的实值标量组成。 我们可以将任意矩阵
A
∈
R
m
×
n
\mathbf{A} \in \mathbb{R}^{m \times n}
A∈Rm×n视为一个表格, 其中每个元素
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
]
.
\mathbf{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⎦⎥⎥⎥⎤. :eqlabel:eq_matrix_def
对于任意
A
∈
R
m
×
n
\mathbf{A} \in \mathbb{R}^{m \times n}
A∈Rm×n,
A
\mathbf{A}
A的形状是(
m
m
m,
n
n
n)或
m
×
n
m \times n
m×n。 当矩阵具有相同数量的行和列时,其形状将变为正方形; 因此,它被称为方阵(square matrix)。
当调用函数来实例化张量时, 我们可以[通过指定两个分量
m
m
m和
n
n
n来创建一个形状为
m
×
n
m \times n
m×n的矩阵]。
我们可以通过行索引(
i
i
i)和列索引(
j
j
j)来访问矩阵中的标量元素
a
i
j
a_{ij}
aij, 例如
[
A
]
i
j
[\mathbf{A}]_{ij}
[A]ij。 如果没有给出矩阵
A
\mathbf{A}
A的标量元素,如在 :eqref:eq_matrix_def那样, 我们可以简单地使用矩阵
A
\mathbf{A}
A的小写字母索引下标
a
i
j
a_{ij}
aij 来引用
[
A
]
i
j
[\mathbf{A}]_{ij}
[A]ij。 为了表示起来简单,只有在必要时才会将逗号插入到单独的索引中, 例如
a
2
,
3
j
a_{2,3j}
a2,3j和
[
A
]
2
i
−
1
,
3
[\mathbf{A}]_{2i-1,3}
[A]2i−1,3。
当我们交换矩阵的行和列时,结果称为矩阵的转置(transpose)。 我们用
a
⊤
\mathbf{a}^\top
a⊤来表示矩阵的转置,如果
B
=
A
⊤
\mathbf{B}=\mathbf{A}^\top
B=A⊤, 则对于任意
i
i
i和
j
j
j,都有
b
i
j
=
a
j
i
b_{ij}=a_{ji}
bij=aji。 因此,在 :eqref:eq_matrix_def中的转置是一个形状为
n
×
m
n \times m
n×m的矩阵:
A
⊤
=
[
a
11
a
21
…
a
m
1
a
12
a
22
…
a
m
2
⋮
⋮
⋱
⋮
a
1
n
a
2
n
…
a
m
n
]
.
\mathbf{A}^\top = \begin{bmatrix} a_{11} & a_{21} & \dots & a_{m1} \\ a_{12} & a_{22} & \dots & a_{m2} \\ \vdots & \vdots & \ddots & \vdots \\ a_{1n} & a_{2n} & \dots & a_{mn} \end{bmatrix}.
A⊤=⎣⎢⎢⎢⎡a11a12⋮a1na21a22⋮a2n……⋱…am1am2⋮amn⎦⎥⎥⎥⎤.
[就像向量是标量的推广,矩阵是向量的推广一样,我们可以构建具有更多轴的数据结构]。 张量(本小节中的“张量”指代数对象)为我们提供了描述具有任意数量轴的
n
n
n维数组的通用方法。 例如,向量是一阶张量,矩阵是二阶张量。 张量用特殊字体的大写字母表示(例如,
X
\mathsf{X}
X、
Y
\mathsf{Y}
Y和
Z
\mathsf{Z}
Z), 它们的索引机制(例如
x
i
j
k
x_{ijk}
xijk和
[
X
]
1
,
2
i
−
1
,
3
[\mathsf{X}]_{1,2i-1,3}
[X]1,2i−1,3)与矩阵类似。
当我们开始处理图像时,张量将变得更加重要,图像以
n
n
n维数组形式出现, 其中3个轴对应于高度、宽度,以及一个通道(channel)轴, 用于表示颜色通道(红色、绿色和蓝色)。 现在,我们先将高阶张量暂放一边,而是专注学习其基础知识。
具体而言,[两个矩阵的按元素乘法称为Hadamard积(Hadamard product)(数学符号
⊙
\odot
⊙)]。 对于矩阵
B
∈
R
m
×
n
\mathbf{B} \in \mathbb{R}^{m \times n}
B∈Rm×n, 其中第
i
i
i行和第
j
j
j列的元素是
b
i
j
b_{ij}
bij。 矩阵
A
\mathbf{A}
A(在 :eqref:eq_matrix_def中定义)和
B
\mathbf{B}
B的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
]
.
\mathbf{A} \odot \mathbf{B} = \begin{bmatrix} a_{11} b_{11} & a_{12} b_{12} & \dots & a_{1n} b_{1n} \\ a_{21} b_{21} & a_{22} b_{22} & \dots & a_{2n} b_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} b_{m1} & a_{m2} b_{m2} & \dots & a_{mn} b_{mn} \end{bmatrix}.
A⊙B=⎣⎢⎢⎢⎡a11b11a21b21⋮am1bm1a12b12a22b22⋮am2bm2……⋱…a1nb1na2nb2n⋮amnbmn⎦⎥⎥⎥⎤.
我们已经学习了按元素操作、求和及平均值。 另一个最基本的操作之一是点积。 给定两个向量
x
,
y
∈
R
d
\mathbf{x},\mathbf{y}\in\mathbb{R}^d
x,y∈Rd, 它们的点积(dot product)
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=1dxiyi。
[点积是相同位置的按元素乘积的和]
y = torch.ones(4, dtype = torch.float32)
x, y, torch.dot(x, y)
点积在很多场合都很有用。 例如,给定一组由向量
x
∈
R
d
\mathbf{x} \in \mathbb{R}^d
x∈Rd表示的值, 和一组由
w
∈
R
d
\mathbf{w} \in \mathbb{R}^d
w∈Rd表示的权重。
x
\mathbf{x}
x中的值根据权重
w
\mathbf{w}
w的加权和, 可以表示为点积
x
⊤
w
\mathbf{x}^\top \mathbf{w}
x⊤w。 当权重为非负数且和为1(即
(
∑
i
=
1
d
w
i
=
1
)
\left(\sum_{i=1}^{d}{w_i}=1\right)
(∑i=1dwi=1))时, 点积表示加权平均(weighted average)。 将两个向量规范化得到单位长度后,点积表示它们夹角的余弦。 我们将在本节的后面正式介绍长度(length)的概念。
矩阵-向量积
现在我们知道如何计算点积,我们可以开始理解矩阵-向量积(matrix-vector product)。 回顾分别在 :eqref:eq_matrix_def和 :eqref:eq_vec_def中定义的矩阵
A
∈
R
m
×
n
\mathbf{A} \in \mathbb{R}^{m \times n}
A∈Rm×n和向量
x
∈
R
n
\mathbf{x} \in \mathbb{R}^n
x∈Rn。 让我们将矩阵
A
\mathbf{A}
A用它的行向量表示:
A
=
[
a
1
⊤
a
2
⊤
⋮
a
m
⊤
]
,
\mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix},
A=⎣⎢⎢⎢⎡a1⊤a2⊤⋮am⊤⎦⎥⎥⎥⎤,
其中每个
a
i
⊤
∈
R
n
\mathbf{a}^\top_{i} \in \mathbb{R}^n
ai⊤∈Rn都是行向量,表示矩阵的第
i
i
i行。 [矩阵向量积
A
x
\mathbf{A}\mathbf{x}
Ax是一个长度为
m
m
m的列向量, 其第
i
i
i个元素是点积
a
i
⊤
x
\mathbf{a}^\top_i \mathbf{x}
ai⊤x]:
A
x
=
[
a
1
⊤
a
2
⊤
⋮
a
m
⊤
]
x
=
[
a
1
⊤
x
a
2
⊤
x
⋮
a
m
⊤
x
]
.
\mathbf{A}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_m \\ \end{bmatrix}\mathbf{x} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{x} \\ \mathbf{a}^\top_{2} \mathbf{x} \\ \vdots\\ \mathbf{a}^\top_{m} \mathbf{x}\\ \end{bmatrix}.
Ax=⎣⎢⎢⎢⎡a1⊤a2⊤⋮am⊤⎦⎥⎥⎥⎤x=⎣⎢⎢⎢⎡a1⊤xa2⊤x⋮am⊤x⎦⎥⎥⎥⎤.
我们可以把一个矩阵
A
∈
R
m
×
n
\mathbf{A} \in \mathbb{R}^{m \times n}
A∈Rm×n乘法看作是一个从
R
n
\mathbb{R}^{n}
Rn到
R
m
\mathbb{R}^{m}
Rm向量的转换。 这些转换是非常有用的。例如,我们可以用方阵的乘法来表示旋转。 我们将在后续章节中讲到,我们也可以使用矩阵-向量积来描述在给定前一层的值时, 求解神经网络每一层所需的复杂计算。
假设我们有两个矩阵
A
∈
R
n
×
k
\mathbf{A} \in \mathbb{R}^{n \times k}
A∈Rn×k和
B
∈
R
k
×
m
\mathbf{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
]
.
\mathbf{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 \mathbf{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
i
⊤
∈
R
k
\mathbf{a}^\top_{i} \in \mathbb{R}^k
ai⊤∈Rk表示矩阵
A
\mathbf{A}
A的第
i
i
i行,并让列向量
b
j
∈
R
k
\mathbf{b}_{j} \in \mathbb{R}^k
bj∈Rk作为矩阵
B
\mathbf{B}
B的第
j
j
j列。要生成矩阵积
C
=
A
B
\mathbf{C} = \mathbf{A}\mathbf{B}
C=AB,最简单的方法是考虑
A
\mathbf{A}
A的行向量和
B
\mathbf{B}
B的列向量:
A
=
[
a
1
⊤
a
2
⊤
⋮
a
n
⊤
]
,
B
=
[
b
1
b
2
⋯
b
m
]
.
\mathbf{A}= \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix}, \quad \mathbf{B}=\begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix}.
A=⎣⎢⎢⎢⎡a1⊤a2⊤⋮an⊤⎦⎥⎥⎥⎤,B=[b1b2⋯bm].
当我们简单地将每个元素
c
i
j
c_{ij}
cij计算为点积
a
i
⊤
b
j
\mathbf{a}^\top_i \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
]
.
\mathbf{C} = \mathbf{AB} = \begin{bmatrix} \mathbf{a}^\top_{1} \\ \mathbf{a}^\top_{2} \\ \vdots \\ \mathbf{a}^\top_n \\ \end{bmatrix} \begin{bmatrix} \mathbf{b}_{1} & \mathbf{b}_{2} & \cdots & \mathbf{b}_{m} \\ \end{bmatrix} = \begin{bmatrix} \mathbf{a}^\top_{1} \mathbf{b}_1 & \mathbf{a}^\top_{1}\mathbf{b}_2& \cdots & \mathbf{a}^\top_{1} \mathbf{b}_m \\ \mathbf{a}^\top_{2}\mathbf{b}_1 & \mathbf{a}^\top_{2} \mathbf{b}_2 & \cdots & \mathbf{a}^\top_{2} \mathbf{b}_m \\ \vdots & \vdots & \ddots &\vdots\\ \mathbf{a}^\top_{n} \mathbf{b}_1 & \mathbf{a}^\top_{n}\mathbf{b}_2& \cdots& \mathbf{a}^\top_{n} \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
\mathbf{AB}
AB看作是简单地执行
m
m
m次矩阵-向量积,并将结果拼接在一起,形成一个
n
×
m
n \times m
n×m矩阵]。 在下面的代码中,我们在A和B上执行矩阵乘法。 这里的A是一个5行4列的矩阵,B是一个4行3列的矩阵。 两者相乘后,我们得到了一个5行3列的矩阵。
∀
i
,
[
x
]
i
=
0
⇔
f
(
x
)
=
0.
\forall i, [\mathbf{x}]_i = 0 \Leftrightarrow f(\mathbf{x})=0.
∀i,[x]i=0⇔f(x)=0.
你可能会注意到,范数听起来很像距离的度量。 如果你还记得欧几里得距离和毕达哥拉斯定理,那么非负性的概念和三角不等式可能会给你一些启发。 事实上,欧几里得距离是一个
L
2
L_2
L2范数: 假设
n
n
n维向量
x
\mathbf{x}
x中的元素是
x
1
,
…
,
x
n
x_1,\ldots,x_n
x1,…,xn,其[
L
2
L_2
L2范数是向量元素平方和的平方根:]
(
∥
x
∥
2
=
∑
i
=
1
n
x
i
2
,
\|\mathbf{x}\|_2 = \sqrt{\sum_{i=1}^n x_i^2},
∥x∥2=i=1∑nxi2,)
其中,在
L
2
L_2
L2范数中常常省略下标
2
2
2,也就是说
∥
x
∥
\|\mathbf{x}\|
∥x∥等同于
∥
x
∥
2
\|\mathbf{x}\|_2
∥x∥2。 在代码中,我们可以按如下方式计算向量的
L
2
L_2
L2范数。
u = torch.tensor([3.0,-4.0])
torch.norm(u)
tensor(5.)
在深度学习中,我们更经常地使用
L
2
L_2
L2范数的平方。 你还会经常遇到[
L
1
L_1
L1范数,它表示为向量元素的绝对值之和:]
(
∥
x
∥
1
=
∑
i
=
1
n
∣
x
i
∣
.
\|\mathbf{x}\|_1 = \sum_{i=1}^n \left|x_i \right|.
∥x∥1=i=1∑n∣xi∣.)
与
L
2
L_2
L2范数相比,
L
1
L_1
L1范数受异常值的影响较小。 为了计算
L
1
L_1
L1范数,我们将绝对值函数和按元素求和组合起来。
torch.abs(u).sum()
tensor(7.)
L
2
L_2
L2范数和
L
1
L_1
L1范数都是更一般的
L
p
L_p
Lp范数的特例:
∥
x
∥
p
=
(
∑
i
=
1
n
∣
x
i
∣
p
)
1
/
p
.
\|\mathbf{x}\|_p = \left(\sum_{i=1}^n \left|x_i \right|^p \right)^{1/p}.
∥x∥p=(i=1∑n∣xi∣p)1/p.
类似于向量的
L
2
L_2
L2范数,[矩阵]
X
∈
R
m
×
n
\mathbf{X} \in \mathbb{R}^{m \times n}
X∈Rm×n(的Frobenius范数(Frobenius norm)是矩阵元素平方和的平方根:)
(
∥
X
∥
F
=
∑
i
=
1
m
∑
j
=
1
n
x
i
j
2
.
\|\mathbf{X}\|_F = \sqrt{\sum_{i=1}^m \sum_{j=1}^n x_{ij}^2}.
∥X∥F=i=1∑mj=1∑nxij2.)
Frobenius范数满足向量范数的所有性质,它就像是矩阵形向量的
L
2
L_2
L2范数。 调用以下函数将计算矩阵的Frobenius范数。
在深度学习中,我们经常使用范数,如
L
1
L_1
L1范数、
L
2
L_2
L2范数和Frobenius范数。
我们可以对标量、向量、矩阵和张量执行各种操作。
练习
证明一个矩阵
A
\mathbf{A}
A的转置的转置是
A
\mathbf{A}
A,即
(
A
⊤
)
⊤
=
A
(\mathbf{A}^\top)^\top = \mathbf{A}
(A⊤)⊤=A。
给出两个矩阵
A
\mathbf{A}
A和
B
\mathbf{B}
B,证明“它们转置的和”等于“它们和的转置”,即
A
⊤
+
B
⊤
=
(
A
+
B
)
⊤
\mathbf{A}^\top + \mathbf{B}^\top = (\mathbf{A} + \mathbf{B})^\top
A⊤+B⊤=(A+B)⊤。
给定任意方阵
A
\mathbf{A}
A,
A
+
A
⊤
\mathbf{A} + \mathbf{A}^\top
A+A⊤总是对称的吗?为什么?