AI 数学课程 · 第 34 课,共 180

线性映射保留 AI 模型所需的组合

检验变换是否保留求和与缩放,说明输入空间和输出空间,并区分神经网络层与其激活函数。

分享这篇文章

神经网络会反复把一种表示转换成另一种表示。要理解一层做了什么,可以先问两个问题:哪些向量可以作为输入,哪些向量可以作为输出?线性映射回答这两个问题,同时保留向量彼此组合的方式。这样,我们就能把矩阵权重看作不同空间之间的变换,并准确辨认网络在哪一步引入了非线性行为。

学完本课后,你将能够检验一个映射是否线性,说明它的输入空间和输出空间,并区分神经网络层中的矩阵变换与激活函数。

**学习目标:**检验线性,并描述映射的输入空间和输出空间。

本课建立在第 027 课介绍的向量空间规则之上。Mathematics for Machine Learning第 2.7 节在向量组合开始连接坐标与矩阵之处引入线性映射。这里的计算、神经网络层示例、图示和练习均为原创。

变换应尊重输入的组合方式

向量可以相加,也可以缩放。对于两个实向量空间 VV 和 WW,当映射 T:V→WT:V\to W 同时保留这两种运算时,它就是线性的:

这里 u,v∈Vu,v\in V,且 a,b∈Ra,b\in\mathbb{R}。结果属于 WW,右侧的系数分别缩放对应的输出。

可以直接检验这个组合规则,也可以拆成两项检查:

T(u+v)=T(u)+T(v),T(au)=aT(u).T(u+v)=T(u)+T(v), \qquad T(au)=aT(u).

第一项表示:先把两个输入相加再变换,结果应与分别变换后再相加相同。第二项表示:先缩放输入再变换,结果应与用相同倍数缩放输出相同。两项都必须对每个有效输入和每个实数标量成立,包括负数。

线性映射把和映射为像的和对于 T(x₁, x₂) = (2x₁ + x₂, −x₁ + x₂),e₁ + e₂ 的像等于 e₁ 的像与 e₂ 的像之和。

输入空间 ℝ²

输入空间 ℝ²三支箭头从原点出发:e₁ = (1, 0)、e₂ = (0, 1) 和 e₁ + e₂ = (1, 1)。e₁e₂e₁ + e₂x₁x₂
  • e₁ = (1, 0)
  • e₂ = (0, 1)
  • e₁ + e₂ = (1, 1)

输出空间 ℝ²

输出空间 ℝ²对应的箭头为 T(e₁) = (2, −1)、T(e₂) = (1, 1) 和 T(e₁ + e₂) = (3, 0)。第三个输出等于前两个输出之和。T(e₁)T(e₂)T(e₁ + e₂)y₁y₂
  • T(e₁) = (2, −1)
  • T(e₂) = (1, 1)
  • T(e₁ + e₂) = (3, 0)

组合检验:T(e₁ + e₂) = T(e₁) + T(e₂)

这三支箭头展示了一次具体的加法检验。这里,T(e1+e2)=(3,0)T(e_1+e_2)=(3,0),而 T(e1)+T(e2)=(2,−1)+(1,1)=(3,0)T(e_1)+T(e_2)=(2,-1)+(1,1)=(3,0)。图示提供了几何直观;公式所表达的一般要求必须对所有向量和标量成立,而不仅仅是这两个基向量。

矩阵说明映射连接哪些空间

设 AA 是一个 m×nm\times n 矩阵,也就是有 mm 行和 nn 列。它与一个含 nn 个坐标的列向量相乘,得到一个含 mm 个坐标的列向量:

T:Rn→Rm,T(x)=Ax.T: \mathbb{R}^n\to\mathbb{R}^m, \qquad T(x)=Ax.

定义域是映射允许的输入集合;陪域是它承诺输出所在的空间。对这个矩阵规则,输入属于 Rn\mathbb{R}^n,输出属于 Rm\mathbb{R}^m。两边维数不必相同:映射可以把向量扩展为更多坐标,也可以压缩为更少坐标。

矩阵乘法是线性的,因为它对加法和标量乘法都满足分配律。对于任意长度为 nn 的向量 u,vu,v 以及标量 a,ba,b,

T(au+bv)=A(au+bv)=aAu+bAv=aT(u)+bT(v).T(au+bv)=A(au+bv)=aAu+bAv=aT(u)+bT(v).

来看一个小型数值例子:

偏置会平移原点;激活函数会改变规则

在机器学习代码中,“线性层”是常见的简写。从数学角度看,具体细节决定了运算是否线性。对于按行组织的批次,PyTorch 的 torch.nn.Linear 计算 xAT+bxA^\mathsf{T}+b,并且默认包含偏置 bb。当偏置非零时,这个规则是仿射的:它保留系数和为一的组合,但通常不保留任意缩放或求和。PyTorch 文档将其称为仿射变换,也允许通过 bias=False 禁用偏置(torch.nn.Linear 文档)。当权重之和为一时,它仍会保留加权配对:

F(λu+(1−λ)v)=λAu+(1−λ)Av+b=λ(Au+b)+(1−λ)(Av+b).F(\lambda u+(1-\lambda)v) =\lambda Au+(1-\lambda)Av+b =\lambda(Au+b)+(1-\lambda)(Av+b).

最后一个等式成立,是因为 λb+(1−λ)b=b\lambda b+(1-\lambda)b=b。普通向量加法使用的系数是 11 和 11,它们的和不是一,因此在 F(u+v)F(u+v) 中偏置不会抵消。

零向量是一个快速诊断方法。每个线性映射都必须把零映射到零,因为 T(0)=T(0⋅x)=0⋅T(x)=0T(0)=T(0\cdot x)=0\cdot T(x)=0。对于仿射规则 F(x)=Ax+bF(x)=Ax+b,

F(0)=A0+b=b.F(0)=A0+b=b.

如果 b≠0b\ne0,那么 FF 就不是线性的。偏置并不会让这一层变得错误;它让模型即使在输入为零时也能平移输出。

神经网络还会在权重变换之后执行另一种运算。常见形式是 h=ReLU⁡(Ax+b)h=\operatorname{ReLU}(Ax+b),其中 ReLU 将每个负坐标替换为零。它是非线性的。例如,令 r(t)=max⁡(0,t)r(t)=\max(0,t)。那么 r(−1+1)=r(0)=0r(-1+1)=r(0)=0,但 r(−1)+r(1)=0+1=1r(-1)+r(1)=0+1=1。加法检验失败了。PyTorch 文档将 torch.nn.ReLU 定义为这个逐元素取最大值的运算(ReLU 文档)。

这个差异解释了网络为何要组合这些步骤。如果两层都只是线性映射,它们的复合仍然是一个线性映射:B(Ax)=(BA)xB(Ax)=(BA)x。增加层数会改变矩阵,但不会产生非线性的输入输出规则。激活函数会阻止这种合并,使网络能够表示更多样的关系。权重矩阵混合输入特征;激活函数改变作用于结果坐标的规则。

用代码检查变换

可以使用 NumPy 检查同样的计算。列向量使“矩阵在左侧”的约定与上面的推导一致:

import numpy as np

A = np.array([[2, 1],
              [-1, 1]])
u = np.array([1, 0])
v = np.array([0, 1])

def T(x):
    return A @ x
print(T(u + v))              # [3 0]
print(T(u) + T(v))           # [3 0]
print(T(-2 * u))             # [-4  2]
print(-2 * T(u))             # [-4  2]

在 PyTorch 中处理批次时,向量通常按行存储,所以库中的权重矩阵会以显示公式中的转置形式出现。批次维度保持不变,最后的特征维度则从 in_features 变为 out_features:

import torch
from torch import nn

x = torch.tensor([[1.0, 0.0], [0.0, 1.0]])  # shape: (2 examples, 2 features)
linear_part = nn.Linear(2, 3, bias=False)
activation = nn.ReLU()

pre_activation = linear_part(x)  # shape: (2, 3); a linear map
hidden = activation(pre_activation)  # shape: (2, 3); nonlinear elementwise step

这里的线性映射把每个 R2\mathbb{R}^2 特征向量映射到 R3\mathbb{R}^3 中的向量。这个实例省略了偏置,所以第一个运算确实是线性的。若使用默认偏置,PyTorch 将其描述为仿射运算。激活函数保留输出形状,却无法通过向量组合检验。形状相同并不能说明一个运算是否线性;决定因素是代数规则。

线性映射仍可能丢失信息

线性并不意味着映射可逆、保长度,甚至不意味着它对所有下游任务都有用。零矩阵会把每个输入映射为零向量,但仍满足线性的两项规则。从 R3\mathbb{R}^3 到 R2\mathbb{R}^2 的线性映射不可能是一一映射:至少有一个输入方向的信息会消失。要判断信息是否得到保留,还需要线性无关、秩和可逆性等其他概念。

检查神经网络模块时,应写出每项运算前后的空间,并检验每项运算采用的规则。矩阵乘法以可预测的方式变换组合;偏置会平移原点;激活函数会改变组合的行为。记住这一区分,下一课将进一步介绍线性映射的具体矩阵表示。

检查理解

问题 1

映射要成为线性的,必须满足哪两项性质?只检验向量加法还遗漏了什么?

显示分步解答

线性映射必须保留加法和标量乘法:对每个有效的 u,vu,v 和每个实数标量 cc,都有 T(u+v)=T(u)+T(v)T(u+v)=T(u)+T(v) 和 T(cu)=cT(u)T(cu)=cT(u)。应用这两项性质即可得到组合规则:T(au+bv)=T(au)+T(bv)=aT(u)+bT(v)T(au+bv)=T(au)+T(bv)=aT(u)+bT(v)。加法检验只覆盖输入的求和;要直接确立定义,还需检验每个实数缩放。

问题 2

对于 T(x₁, x₂) = (2x₁ + x₂, −x₁ + x₂),计算 T(3, 2)。写出两个输出坐标,并说明输入空间和输出空间。

显示分步解答

矩阵有两列,因此接受来自 R2\mathbb{R}^2 的向量。矩阵有两行,因此输出属于 R2\mathbb{R}^2。用输入分别乘以每一行:

T(32)=(2⋅3+1⋅2−1⋅3+1⋅2)=(8−1).T\begin{pmatrix}3\\2\end{pmatrix} =\begin{pmatrix}2\cdot3+1\cdot2\\-1\cdot3+1\cdot2\end{pmatrix} =\begin{pmatrix}8\\-1\end{pmatrix}.

所以这是映射 T:R2→R2T:\mathbb{R}^2\to\mathbb{R}^2,输出为 (8,−1)(8,-1)。

问题 3

使用本课的矩阵,验证 T((1, 0) + (0, 1)) = T(1, 0) + T(0, 1)。

显示分步解答

令 u=(1,0)u=(1,0),v=(0,1)v=(0,1)。例题给出 T(u)=(2,−1)T(u)=(2,-1),T(v)=(1,1)T(v)=(1,1),因此二者之和为 (3,0)(3,0)。输入之和为 u+v=(1,1)u+v=(1,1),矩阵乘法得出 T(1,1)=(3,0)T(1,1)=(3,0)。两边相等,因此这次具体的加法检验成立。这个例子支持该规则,但不能证明它对每个向量都成立;矩阵乘法的分配律才给出一般证明。

问题 4

对于同一个矩阵,取 u = (1, 0),计算 T(−2u),并与 −2T(u) 比较。这个检验考查什么?

显示分步解答

首先,T(u)=(2,−1)T(u)=(2,-1),所以 −2T(u)=(−4,2)-2T(u)=(-4,2)。另外,−2u=(−2,0)-2u=(-2,0),并且

T(−2u)=(21−11)(−20)=(−42).T(-2u)=\begin{pmatrix}2&1\\-1&1\end{pmatrix} \begin{pmatrix}-2\\0\end{pmatrix} =\begin{pmatrix}-4\\2\end{pmatrix}.

两项结果一致。这检验了负标量下的缩放保持性;这很重要,因为线性要求对每个实数标量都成立。

问题 5

某个候选层定义为 F(x) = Ax + (0, 2)。F 能是线性映射吗?使用零向量检验,并说明所加向量的作用。

显示分步解答

对于线性映射,T(0)T(0) 必须等于零:任何输入乘以 00,其输出也必须乘以 00。这里,F(0)=A0+(0,2)=(0,2)≠(0,0)F(0)=A0+(0,2)=(0,2)\ne(0,0)。因此 FF 不是线性的。所加的向量会把每个输出平移 (0,2)(0,2),使它成为仿射映射。

问题 6

PyTorch 模块先执行 <code>nn.Linear(4, 8)</code>,再执行 <code>nn.ReLU()</code>。请给出输入和输出特征空间,并判断每项运算的类型。

显示分步解答

每个输入样本有四个特征,因此是 R4\mathbb{R}^4 中的向量。线性层生成八个坐标,属于 R8\mathbb{R}^8。PyTorch 默认启用偏置,所以 nn.Linear(4, 8) 通常是仿射映射,而不是数学意义上的线性映射。nn.ReLU() 保留八维形状,但对每个坐标应用 t↦max⁡(0,t)t\mapsto\max(0,t),因此是非线性运算。设置 bias=False 时,第一个运算才是 R4→R8\mathbb{R}^4\to\mathbb{R}^8 的线性映射。

问题 7

用输入 −1 和 1 说明 ReLU 不保留加法。它的失败会改变输出维数吗?

显示分步解答

ReLU 把 tt 映射为 max⁡(0,t)\max(0,t)。如果它保留加法,那么先对输入求和再应用它,应与分别变换后再相加相同。但是,ReLU⁡(−1+1)=ReLU⁡(0)=0\operatorname{ReLU}(-1+1)=\operatorname{ReLU}(0)=0,而 ReLU⁡(−1)+ReLU⁡(1)=0+1=1\operatorname{ReLU}(-1)+\operatorname{ReLU}(1)=0+1=1。两项结果不同,因此 ReLU 是非线性的。它仍对每个输入数值返回一个数值,所以输出形状与输入形状相同,尽管规则是非线性的。

问题 8

每个线性映射都可逆或保长度吗?请为其中一项说法给出线性反例。

显示分步解答

不是。零映射 T(x)=0T(x)=0 是线性的,因为 T(u+v)=0=0+0T(u+v)=0=0+0 且 T(cu)=0=cT(u)T(cu)=0=cT(u);但它把每个输入都映射成同一输出,因而无法逆转。保长度也不是线性的必然性质:S(x1,x2)=(2x1,x2)S(x_1,x_2)=(2x_1,x_2) 是线性映射,但 S(1,0)=(2,0)S(1,0)=(2,0) 的长度为 22,而不是 11。线性描述的是组合如何变化,并不表示长度或信息保持不变。

资料来源

  1. Mathematics for Machine Learning book PDF, Section 2.7
  2. PyTorch documentation: torch.nn.Linear
  3. PyTorch documentation: torch.nn.ReLU