线性变换

线性代数,用来研究线性关系。

一开始是为了解决一组一次方程:

{2x+y=5x−y=1 \begin{cases} 2x+y=5 \\\\ x-y=1 \end{cases}

  1. 线性:关系中变量只出现一次方,是直线。
  2. 代数:通过符号,方程和运算规则研究数量与结构。

线性变换:

  1. T(u+v)=T(u)+T(v)T(u+v) = T(u) + T(v)
  2. T(cu)=cT(u)T(cu)=cT(u)

先合并再变换,和先分别变换再合并,结果一样;输入放大几倍,输出也放大几倍。

为什么这个叫线性变换,因为这个变换会把一条直线变为另外一条直线。

任意直线可以写为:

x=u+tvx=u+tv

T(u+tv)=T(u)+tT(v)T(u+tv) = T(u) + tT(v)

变换后右边仍然是一条直线的参数方程,可以这样理解:

  1. 一条直线可以写为参数形式 x(t)=p+tvx(t)=p+tv
  2. p 是直线上的一个固定点,可以是多维
  3. v 是固定方向,可以是多维
  4. t 是任意实数
  5. 改变 t,就是从 p 出发,沿固定方向 v 前后移动

矩阵

矩阵是为了让一张表来记录一个线性变换。

  1. T(x,y)=(2x+y,3y)T(x,y) = (2x + y, 3y)
  2. 输入 x,y 输出两个新坐标 {X=2x+yY=0x+3y \begin{cases} X = 2x+y \\\\ Y = 0x + 3y \end{cases}
  3. 系数整理出来: [2103] \begin{bmatrix}2&1\\\\0&3\end{bmatrix}
  4. 变换可以简写成: [XY]=[2103][xy]\begin{bmatrix}X\\\\Y\end{bmatrix}=\begin{bmatrix}2&1\\\\0&3\end{bmatrix}\begin{bmatrix}x\\\\y \end{bmatrix}

矩阵为什么满足线性变换:

  1. 保持加法:A(u+v)=Au+AvA(u+v) = Au + Av
  2. 保持乘法:A(cu)=c(Au)A(cu)=c(Au)

矩阵的形状: A∈Rm×nA\in\mathbb R^{m\times n}

表示一个从 n 维空间到 m 维空间的线性变换:A:Rn→RmA:\mathbb R^n\rightarrow\mathbb R^m

矩阵的列: A=[∣∣∣a1a2⋯an∣∣∣]A= \begin{bmatrix} |&|&&|\\\\ a_1&a_2&\cdots&a_n\\\\ |&|&&| \end{bmatrix}

Ax=x1a1+x2a2+...+xnanAx=x_1a_1+x_2a_2+...+x_na_n

  1. 矩阵的每一列记录了一个基础方向被变到哪里
  2. 输出 Ax 是这些列向量的线性组合
  3. Ax 一定落在矩阵各列所张成的空间中

内积与正交

内积:把两个向量算成一个数,u⋅v=∑i=1nuiviu\cdot v=\sum_{i=1}^{n}u_iv_i

  1. 结果是标量,不再是向量
  2. 交换律:u⋅v=v⋅uu\cdot v=v\cdot u
  3. 分配律:(au+bv)⋅w=a(u⋅w)+b(v⋅w)(au+bv)\cdot w=a(u\cdot w)+b(v\cdot w)
  4. 自己和自己:u⋅u=∥u∥2u\cdot u=\|u\|^2

第 4 条让「长度」有了定义:∥u∥=u⋅u\|u\|=\sqrt{u\cdot u}

有了内积,角度也能算出来:cos⁡θ=u⋅v∥u∥∥v∥\cos\theta=\frac{u\cdot v}{\|u\|\|v\|}

  1. u⋅v=0u\cdot v=0:夹角 90°,两个向量正交
  2. u⋅v>0u\cdot v>0:锐角
  3. u⋅v<0u\cdot v<0:钝角

正交:内积为 0,也就是互相垂直。

正交基:一组两两正交的基向量。

正交基的价值在于算投影特别简单。在正交基下,向量 v 沿方向 u 的投影是

projuv=v⋅uu⋅uu\text{proj}_u v=\frac{v\cdot u}{u\cdot u}u

如果基底不正交,同一个投影要解一个方程组才能求出系数;正交基直接一次内积就算完了,各个方向互不干扰。

任意一组线性无关的向量,都可以通过施密特正交化变成正交基,而且张成的空间完全不变。

这让前面「秩」的说法变精确了:一个空间最多能撑起多少个两两正交的方向,那个个数就是它的维数,也就是 rank(A)。

投影:把 v 沿 u 的方向压过去,垂直于 u 的那一部分丢掉。

当 u 是单位向量时系数简化成 v⋅uv\cdot u,也就是「v 在 u 方向上有多少长度」。

正交矩阵:把一组正交基映射到另一组正交基的变换,所以它只改方向,不改长度和夹角:

  1. ∥Ux∥=∥x∥\|Ux\|=\|x\|
  2. (Ux)⋅(Uy)=x⋅y(Ux)\cdot(Uy)=x\cdot y
  3. UTU=IU^TU=I

SVD 里的 U 和 V 就是这样的矩阵,所以才说它们「只负责旋转」。

最小二乘就是投影:想找一条直线,使所有点到它的垂直距离平方和最小,等价于把目标值投影到这条直线上,让所有残差都落在垂直方向上(也就是与这条直线正交)。后面截断 SVD 保留前 r 个奇异方向,本质同样是把原矩阵投影到一个 r 维子空间上。

矩阵的秩

经过这个矩阵变换后,输出还保留多少个独立方向,记作 rank(A)。

通过秩来判断:

  1. 信息是否丢失
  2. 方程是否有解
  3. 解是否唯一
  4. 矩阵是否可逆

零空间与秩-零化度定理

零空间:被矩阵压扁成零的那些方向,也就是所有满足 Av=0Av=0 的向量 vv 组成的集合 N(A)N(A)。

  1. 零向量总在零空间里,因为 A0=0A0=0,所以零空间至少有零向量这一个元素
  2. 零空间里的非零向量经过变换后彻底消失,信息全部丢失
  3. 齐次方程 Ax=0Ax=0 什么时候有非零解:正好是 rank(A)<nrank(A)<n 的时候

秩-零化度定理:

rank(A)+dim(N(A))=nrank(A)+dim(N(A))=n

dimdim 的含义:dimdim 就是一个空间由多少个独立方向撑起来,也就是这个空间的维数。

  1. dim(N(A))=0dim(N(A))=0:零空间里只剩零向量,没有独立方向
  2. dim(N(A))=1dim(N(A))=1:零空间是一条直线,丢掉了 1 个独立方向
  3. dim(N(A))=2dim(N(A))=2:零空间是一个平面,丢掉了 2 个独立方向

零空间本身就是一个向量集合,所以它和输入空间一样可以谈维数。dimdim 和 rankrank 是同一套计数的两种用法:一个数活下来的方向,一个数被压扁的方向。

nn 是输入空间的维数,也就是矩阵的列数。

这句话说的是:输入的 n 个独立方向进了矩阵之后只可能分成两拨,一拨活下来变成独立方向(rank(A)rank(A) 个),另一拨被压扁成零(dim(N(A))dim(N(A)) 个),两拨加起来正好还是 n。

所以「通过秩来判断」的四件事其实是同一件事,因为 dim(N(A))=n−rank(A)dim(N(A))=n-rank(A) 直接给出了丢掉多少信息:

  1. 信息是否丢失:dim(N(A))>0dim(N(A))>0 就是有信息被丢掉,丢在零空间里
  2. 方程是否有解:Ax=bAx=b 有解要求 bb 落在列空间里
  3. 解是否唯一:零空间只有零向量时解唯一,否则有无穷多个解(一个特解加上零空间里的任意向量)
  4. 矩阵是否可逆:方阵时 rank(A)=nrank(A)=n,也就是零空间只剩零向量,此时才可逆

最满的情况是 rank(A)=nrank(A)=n:零空间只剩零向量,信息一点都不丢,Ax=bAx=b 对任意 bb 都有唯一解。

行列式

对于方阵,行列式 det(A) 描述空间体积的缩放比例:

  • ∣det(A)∣>1|det(A)|>1: 体积放大
  • 0<∣det(A)∣<10<|det(A)|<1: 体积缩小
  • det(A)<0det(A)<0: 方向发生翻转
  • det(A)=0det(A)=0: 空间被压扁,丢失维度

det(A) 更准确地说是「有向体积」的缩放比例,正负号记录的就是方向有没有被翻转。2×2 的时候它是两列向量张成的平行四边形的有向面积,n×2 的时候是 n 维平行多面体的有向体积。

怎么算:

  • 2×2:主对角线乘积减去副对角线乘积,det⁡[abcd]=ad−bc\det\begin{bmatrix}a&b\\\\c&d\end{bmatrix}=ad-bc
  • 3×3:沿任意一行或一列展开,每个元素乘上它对应小矩阵的行列式,符号交替加减
  • n×n:递归展开,代价是 O(n!)O(n!),所以大矩阵从来不这么算

拿前面那个矩阵举例:A=[2103]A=\begin{bmatrix}2&1\\\\0&3\end{bmatrix},det(A)=2×3-1×0=6。原来的单位面积变成了 6 倍,det(A)>0 说明方向没有被翻转。

det(A)=0 其实是同一件事的几种说法:

  • det(A)=0
  • rank(A)<n,矩阵不满秩
  • 零空间里有非零向量
  • Ax=0 有非零解
  • A 不可逆
  • A 把 n 维空间压扁成了低于 n 维

这六条是同一个数学事实的不同表述,「用秩来判断」那几条靠的就是这个。

一个关键性质:det⁡(AB)=det⁡(A)det⁡(B)\det(AB)=\det(A)\det(B)

因为先做 A 再做 B,体积先按 det(A) 缩放、再按 det(B) 缩放,总共就是两者相乘。这个性质顺便也推出了 det⁡(A−1)=1det⁡(A)\det(A^{-1})=\frac{1}{\det(A)}。

和前后两节的关系:

  • det⁡(A)=∏iλi\det(A)=\prod_i\lambda_i,行列式就是所有特征值的乘积
  • det⁡(A)=±∏iσi\det(A)=\pm\prod_i\sigma_i,也就是所有奇异值的乘积

纯旋转的行列式是 1,因为只转方向不改体积;纯反射(镜像翻转)的行列式是 -1。所以回到 SVD 那节的「旋转 + 缩放 + 旋转」,U 和 V 各自贡献 ±1,中间的 Σ 贡献 ∏iσi\prod_i\sigma_i,合起来就是 det⁡(A)=±∏iσi\det(A)=\pm\prod_i\sigma_i —— 那个正负号正是方向有没有被翻转的记录。

逆矩阵与高斯消元

上一节说了 det(A)≠0 等价于 A 可逆。可逆的意思是存在一个矩阵 A−1A^{-1},使得 AA−1=A−1A=IAA^{-1}=A^{-1}A=I,于是任何方程都有解:

Ax=b⇒x=A−1bAx=b\Rightarrow x=A^{-1}b

逆矩阵的性质:

  1. 逆矩阵本身也是一个线性变换,方向正好相反:把 A 做的事反过来做一遍
  2. det⁡(A−1)=1det⁡(A)\det(A^{-1})=\frac{1}{\det(A)},所以 det(A) 越接近 0,逆矩阵的元素越夸张
  3. (AB)−1=B−1A−1(AB)^{-1}=B^{-1}A^{-1},顺序反过来了
  4. (AT)−1=(A−1)T(A^T)^{-1}=(A^{-1})^T

高斯消元才是真正算得出来的办法,思路很简单:把左边的 A 一步步变成单位矩阵 I,右边跟着变。

  1. 把增广矩阵 [A∣b][A|b] 摆好
  2. 只用三种行变换:交换两行、某一行乘非零数、把一行加到另一行上
  3. 想办法把左边化成 I
  4. 左边是 I 的时候,右边就是 x=A−1bx=A^{-1}b 的结果

这三种行变换都不改变解,因为它们同时作用在等式两边。

举个例子:[0110][x1x2]=[35]\begin{bmatrix}0&1\\\\1&0\end{bmatrix}\begin{bmatrix}x_1\\\\x_2\end{bmatrix}=\begin{bmatrix}3\\\\5\end{bmatrix}

写成增广矩阵是 [01∣310∣5]\begin{bmatrix}0&1&|&3\\\\1&0&|&5\end{bmatrix},交换两行就变成 [10∣501∣3]\begin{bmatrix}1&0&|&5\\\\0&1&|&3\end{bmatrix},所以 x1=5, x2=3x_1=5,\ x_2=3。

如果化不出单位矩阵,说明 rank(A)<n,零空间非零,方程要么无解要么有无穷多解。

实际写代码时一般不会真的去构造逆矩阵:

  1. 解单个方程:直接高斯消元,比先求逆再乘更快
  2. 同一个 A 要解很多次:先做 LU 分解存下来,之后每次求解都很便宜
  3. 确实需要逆矩阵本身(比如反复出现 A−1bA^{-1}b):算一次存起来复用

数值上要小心:接近奇异的矩阵算出来的逆极不精确,误差会被放大。遇到这种情况通常改用 SVD 或者最小二乘,而不是硬算逆。

特征值与特征向量

矩阵通常会改变向量的方向,但是有些特殊的方向经过变换后方向不变,只会改变长度:Av=λvAv=\lambda v

  • vv 是特征向量,表示特殊方向
  • λ\lambda 是特征值,表示该方向被缩放多少

奇异值

奇异值描述的是:一个矩阵在不同方向上,分别会把向量的长度拉伸或压缩多少。

特征值要求矩阵是方阵,而且只看矩阵「自己」的方向。奇异值没有这个限制,m×nm\times n 的长条矩阵也能用,办法是先把它自己平方一下:ATAA^TA。

ATAA^TA 一定是方阵,因为它把 Rn\mathbb R^n 变回 Rn\mathbb R^n:ATA:Rn→RnA^TA:\mathbb R^n\rightarrow\mathbb R^n。

于是奇异值就这么定义:

  • σi=λi(ATA)\sigma_i=\sqrt{\lambda_i(A^TA)},奇异值就是 ATAA^TA 特征值的平方根
  • viv_i 是 ATAA^TA 的特征向量,称为右奇异向量
  • ui=Aviσiu_i=\frac{Av_i}{\sigma_i} 称为左奇异向量

和特征值对比:

  • 特征值可以是负数,奇异值一定非负,因为它来自平方根
  • 特征值是方阵在自己身上找方向,奇异值是输入方向和输出方向各记一个,所以有两个
  • 非零奇异值的个数正好等于 rank(A)

奇异值分解

任何一个 m×nm\times n 的矩阵都能拆成三步,这是线性代数里最通用的一次分解:

A=UΣVTA=U\Sigma V^T

按从右往左的顺序读,恰好是一次变换的完整过程:

  1. VTV^T:旋转输入空间,把每个坐标轴对准一个奇异方向
  2. Σ\Sigma:沿每个坐标轴各自拉伸或压缩,第 ii 个方向拉 σi\sigma_i 倍
  3. UU:再旋转一次,把结果摆进输出空间

所以任何一个线性变换都可以理解成:旋转 + 缩放 + 旋转。

其中 UU 和 VV 都是正交矩阵(UTU=IU^TU=I),它们只负责旋转,不改变任何长度;Σ\Sigma 是对角矩阵,对角线上从大到小排着奇异值 σ1≥σ2≥⋯≥0\sigma_1\geq\sigma_2\geq\cdots\geq0。

左右奇异向量之间的关系是 Avi=σiuiAv_i=\sigma_i u_i:viv_i 这个方向被拉长 σi\sigma_i 倍后,变成了 uiu_i 这个方向。这正好能和特征值对照着记——特征值是方向不变只改长度(Av=λvAv=\lambda v),奇异值分解则是把「方向也变了」这件事拆成了两次干净的旋转。

串起前面几节:

  • 非零奇异值的个数 = rank(A),所以 SVD 自己就说明了这个矩阵在哪些方向上还留着信息
  • σi=0\sigma_i=0 对应的那些 viv_i 正好张成零空间,丢的就是这些方向
  • det⁡(A)=±∏iσi\det(A)=\pm\prod_i\sigma_i,所以行列式说的缩放比例,就是所有奇异值乘起来

低秩近似

把 Σ\Sigma 里最小的那些奇异值直接置零,只保留最大的 r 个,就得到一个秩为 r 的近似矩阵 ArA_r。

这不只是「随便删一删」:ArA_r 是所有秩不超过 r 的矩阵里面离 A 最近的一个,即最优低秩近似。

之所以敢丢,是因为奇异值是从大到小排的,能量集中在前面几个上面,后面那些小的对结果的贡献很小。

实际用在哪:

  • PCA 就是对数据的协方差矩阵做 SVD
  • 图片压缩:把图像当成矩阵,保留最大的几个奇异值就能压掉很多体积
  • LoRA:微调大模型时把权重更新假设成低秩的,用的就是截断 SVD